尚品汇-网关过滤用户请求、登录流程(三十五)

news2024/9/23 15:23:23

目录:

(1)用户认证与服务网关整合

(2)server-gateway网关配置  

(3)在服务网关中判断用户登录状态

(4)登录流程

(1)用户认证与服务网关整合

 实现思路

  1. 所有请求都会经过服务网关,服务网关对外暴露服务,不管是api异步请求还是web同步请求都走网关,在网关进行统一用户认证
  2. 既然要在网关进行用户认证,网关得知道对哪些url进行认证,所以我们得对url制定规则
  3. Web页面同请求(如:*.html),我采取配置白名单的形式,凡是配置在白名单里面的请求都是需要用户认证的(注:也可以采取域名的形式,方式多多)
  4. Api接口异步请求的,我们采取url规则匹配,如:/api/**/auth/**,如凡是满足该规则的都必须用户认证

redis:

  host: 192.168.200.129

  port: 6379

  database: 0

  timeout: 1800000

  password:

 
 

authUrls:

  url: trade.html,myOrder.html,list.html

(2)server-gateway网关配置  

pom.xml

<dependency>

   <groupId>org.springframework.boot</groupId>

   <artifactId>spring-boot-starter-data-redis-reactive</artifactId>

</dependency>

在网关中添加redis的配置类。

注意需要引入RedisConfig配置类:因为这个模块没有扫描service-util

server-gateway 项目中添加一个过滤器

ResultCodeEnum :

package com.atguigu.gmall.common.result;

import lombok.Getter;

/**
 * 统一返回结果状态信息类
 *
 */
@Getter
public enum ResultCodeEnum {

    SUCCESS(200,"成功"),
    FAIL(201, "失败"),
    SERVICE_ERROR(2012, "服务异常"),
    ILLEGAL_REQUEST( 204, "非法请求"),
    PAY_RUN(205, "支付中"),

    LOGIN_AUTH(208, "未登陆"),
    PERMISSION(209, "没有权限"),
    SECKILL_NO_START(210, "秒杀还没开始"),
    SECKILL_RUN(211, "正在排队中"),
    SECKILL_NO_PAY_ORDER(212, "您有未支付的订单"),
    SECKILL_FINISH(213, "已售罄"),
    SECKILL_END(214, "秒杀已结束"),
    SECKILL_SUCCESS(215, "抢单成功"),
    SECKILL_FAIL(216, "抢单失败"),
    SECKILL_ILLEGAL(217, "请求不合法"),
    SECKILL_ORDER_SUCCESS(218, "下单成功"),
    COUPON_GET(220, "优惠券已经领取"),
    COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
    ;

    private Integer code;

    private String message;

    private ResultCodeEnum(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}
package com.atguigu.gmall.gateway.filter;

@Component
public class AuthGlobalFilter implements GlobalFilter{

    @Autowired
    private RedisTemplate redisTemplate;

    // 匹配路径的工具类
      private AntPathMatcher antPathMatcher = new AntPathMatcher();
 
    //获取nacos配置文件中的配置
    @Value("${authUrls.url}")
    private String authUrls;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取到请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 获取Url
        String path = request.getURI().getPath();
        // 如果是内部接口,则网关拦截不允许外部访问!
        if (antPathMatcher.match("/**/inner/**",path)){
            ServerHttpResponse response = exchange.getResponse();
            return out(response,ResultCodeEnum.PERMISSION);
        }
        // 获取用户Id
        String userId = getUserId(request);

//token被盗用
       if("-1".equals(userId)) {
          ServerHttpResponse response = exchange.getResponse();
          return out(response,ResultCodeEnum.PERMISSION);
       }
        // 用户登录认证
        //api接口,异步请求,校验用户必须登录
        if(antPathMatcher.match("/api/**/auth/**", path)) {
            if(StringUtils.isEmpty(userId)) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response,ResultCodeEnum.LOGIN_AUTH);
            }
        }
        // 验证url
        for (String authUrl : authUrls.split(",")) {
            // 当前的url包含登录的控制器域名,但是用户Id 为空!
            if (path.indexOf(authUrl)!=-1 && StringUtils.isEmpty(userId)){
                ServerHttpResponse response = exchange.getResponse();
                //303状态码表示由于请求对应的资源存在着另一个URI,应使用重定向获取请求的资源
                response.setStatusCode(HttpStatus.SEE_OTHER);
             
             //设置地址location   originUrl当前请求的地址   
          
         response.getHeaders().set(HttpHeaders.LOCATION,"http://www.gmall.com/login.html?originUrl="+request.getURI());
                // 重定向到登录
                return response.setComplete();
            }
        }

         
         //存储userId到请求中
        // 将userId 传递给后端
        if (!StringUtils.isEmpty(userId)){
            request.mutate().header("userId",userId).build();
            // 将现在的request 变成 exchange对象
            return chain.filter(exchange.mutate().request(request).build());
        }
        return chain.filter(exchange);
    }







/**
 * 获取当前登录用户id
 * @param request
 * @return
 */
//public static String getUserId(HttpServletRequest request) {
//    String userId = request.getHeader("userId");
//    return StringUtils.isEmpty(userId) ? "" : userId;
// }

(3)在服务网关中判断用户登录状态

在网关中如何获取用户信息:

  1. 从cookie中获取(如:web同步请求)
  2. 从header头信息中获取(如:异步请求)

如何判断用户信息合法:

登录时我们返回用户token,在服务网关中获取到token后,我在到redis中去查看用户id,如果用户id存在,则token合法,否则不合法,同时校验ip,防止token被盗用。

 

/**
 * 获取当前登录用户id
 * @param request
 * @return
 */
private String getUserId(ServerHttpRequest request) {
    String token = "";
    //头信息
    List<String> tokenList = request.getHeaders().get("token");
    if(null  != tokenList) {
        token = tokenList.get(0);
    } else {

        //从cookie中获取
        MultiValueMap<String, HttpCookie> cookieMultiValueMap =  request.getCookies();
        HttpCookie cookie = cookieMultiValueMap.getFirst("token");
        if(cookie != null){
            token = URLDecoder.decode(cookie.getValue());
        }
    }


//获取数据
  if(!StringUtils.isEmpty(token)) {
        //从Redis中获取
        String userStr = (String)redisTemplate.opsForValue().get("user:login:" + token);
        //转换 
        JSONObject userJson = JSONObject.parseObject(userStr);
        //获取ip
        String ip = userJson.getString("ip");
        //获取请求的ip
        String curIp = IpUtil.getGatwayIpAddress(request);
        //校验token是否被盗用
        if(ip.equals(curIp)) {
            return userJson.getString("userId");
        } else {
            //ip不一致
            return "-1";
        }
    }
    return "";
}

 

输入信息out 方法

// 接口鉴权失败返回数据
private Mono<Void> out(ServerHttpResponse response,ResultCodeEnum resultCodeEnum) {
    // 返回用户没有权限登录
    Result<Object> result = Result.build(null, resultCodeEnum);
    byte[] bits = JSONObject.toJSONString(result).getBytes(StandardCharsets.UTF_8);

    //获取DataBuffer 
    DataBuffer wrap = response.bufferFactory().wrap(bits);

    //乱码处理
    response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
    // 输入到页面
    return response.writeWith(Mono.just(wrap));
}

当退出登录后,点击 

跳转到登录页面

登录后:

会跳转到点击的页面

后面就可以用了

(4)登录流程

 

 

退出:

 

网关中的过滤器:如果有多个过滤器可以实现Order,执行过滤器的执行顺序,谁的越小谁就先执行

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2057219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一对一私密发送分班结果,就用易查分

暑假即将结束&#xff0c;老师们又要开始忙碌起来&#xff0c;其中一项重要任务就是搭建一个分班信息查询系统。对于家长和学生来说&#xff0c;简直就是神器&#xff0c;因为它能提供快速便捷的查询服务。 想象一下&#xff0c;家长和学生通过扫描二维码&#xff0c;就能轻松…

【鸿蒙学习】HarmonyOS应用开发者基础 - 认证通过

考试时间&#xff1a;2024-08-20 22:00 考试结果&#xff1a;成功&#xff08;99分&#xff09; 一、开局叨叨 HarmonyOS应用开发者基础认证&#xff0c;不完美通过&#xff0c;考试分数99分&#xff0c;为啥不考100分。主要是当时没找到&#xff0c;后面通过录屏看了一下&am…

2024“华为杯”第二十一届中国研究生数学建模竞赛2004-2023华为杯数学建模优秀论文(见文末)

2024“华为杯”第二十一届中国研究生数学建模竞赛&2004-2023华为杯数学建模优秀论文&#xff08;见文末&#xff09; 各研究生培养单位&#xff1a; 中国研究生数学建模竞赛&#xff08;以下简称“竞赛”&#xff09;是教育部学位管理与研究生教育司指导&#xff0c;中国学…

TUIKit:chat-uikit-vue在微信中上传图片的一个bug

一、问题描述 今天使用腾讯IM的TUIKIT示例工程&#xff1a;https://github.com/TencentCloud/chat-uikit-vue.git &#xff0c;发现在Android设备的微信里打开&#xff0c;选择相册的图片进行编辑后发送会失败&#xff1a; 二、问题排查 由于在微信中不好排查问题&#xff…

docker 安装minio并配置https域名访问

一、准备目录 mkdir -p /home/minio/data/home/minio/config/home/minio/config/certs/二、下载域名证书&#xff0c;注意要Apache的 注意.key的换成 private.key&#xff0c;public.crt换成 public.crt&#xff0c;然后将这两个文件放到/home/minio/config/certs/目录下 三、…

微信小程序开发工具最新版版下载

最近&#xff0c;下载微信小程序开发工具的时候&#xff0c;因为网络问题&#xff0c;发现不能够直接下载&#xff0c;需要使用代理才行 如果你也遇到这个问题&#xff0c;可以通过网盘进行下载。 一、官网下载 下载地址&#xff1a;https://developers.weixin.qq.com/miniprog…

DC-1综合靶场渗透从外网打到内网,权限提升,入侵痕迹清除,干货,建议收藏

前言 博客主页&#xff1a;【h0ck1r丶羽】的公众号~~ 由于传播、利用本公众小羽网安提供的文章、工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;公众号小羽网安及作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担&#xff01…

Jmeter进行http接口测试,这一篇就搞定

jmeter-http接口测试脚本 jmeter进行http接口测试的主要步骤&#xff08;1.添加线程组 2.添加http请求 3.在http请求中写入接口的URL&#xff0c;路径&#xff0c;请求方式&#xff0c;参数 4.添加查看结果树 5.调用接口&#xff0c;查看返回值&#xff09; 针对接口添加heade…

【数据分享】《云南省统计年鉴》(2000-2023)

而今天要限时免费分享的数据就是2000-2023年间出版的《云南省统计年鉴》并以多格式提供免费下载。&#xff08;无需分享朋友圈即可获取&#xff09; 数据介绍 在过去的二十多年里&#xff0c;云南省作为中国西南的重要门户&#xff0c;经历了翻天覆地的变化。这些变化不仅…

《机器学习》—— 通过下采样方法实现银行贷款分类问题

文章目录 一、什么是下采样方法&#xff1f;二、通过下采样方法实现银行贷款分类问题三、下采样的优缺点 一、什么是下采样方法&#xff1f; 机器学习中的下采样&#xff08;Undersampling&#xff09;方法是一种处理不平衡数据集的有效手段&#xff0c;特别是在数据集中某些类…

YUM和NFS

文章目录 yum软件仓库的提供方式RPM软件包的来源Linux系统各家厂商用的安装源命令---yum 配置本地yum源具体操作 搭建ftp yum仓库环境具体操作实操环境服务端一、安装 vsftpd服务二、创建一个文件&#xff0c;并且挂载三、开启服务四、查看挂载 客户端五、备份六、搭建ftp yum仓…

Word--两列(两栏、多栏、多列)文档中间插入横跨两列(多列)的表格

最终效果如下图所示 最终效果展示图 即&#xff1a;在原本是两列&#xff08;两栏、多栏、多列&#xff09;显示的Word文档中&#xff0c;插入一个横跨两列的表格&#xff0c;并且不影响文字排列&#xff0c;表格上侧的文字自动排序&#xff0c;表格下侧的文字自动排序&#…

JUC阻塞队列(三):PriorityBlockingQueue

1、PriorityBlockingQueue 介绍 PriorityBlockingQueue 是一个优先级队列&#xff0c;它不满足队列的先进先出特点&#xff1b; PriorityBlockingQueue 会对队列的数据进行排序&#xff0c;排序规则是数据的优先级&#xff1b; PriorityBlockingQueue是基于二叉堆来实现优先级的…

鸿蒙(API 12 Beta3版)【DRM会话管理(ArkTS)】数字版权保护

DRM会话管理&#xff08;MediaKeySession&#xff09;支持媒体密钥管理及媒体解密等&#xff0c;MediaKeySession实例由系统管理里的MediaKeySystem实例创建和销毁。 开发步骤 导入相关接口&#xff0c;导入方法如下。 import { drm } from kit.DrmKit;导入BusinessError模块&…

巡检机器人的使用方法和维护保养

在当今快速发展的工业环境中&#xff0c;智能巡检机器人正逐渐成为提升运维效率和安全性的重要工具。旗晟机器人凭借其核心技术团队和多年的行业经验&#xff0c;推出了多款高效、智能的巡检机器人&#xff0c;旨在帮助企业实现设备运维的智能化升级。本文将介绍旗晟巡检机器人…

第1章-02-Python环境安装与测试

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲。 🎉欢迎 👍点赞✍评论⭐收…

ensp小实验(ospf+dhcp+防火墙)

前言 今天给大家分享一个ensp的小实验&#xff0c;里面包含了ospf、dhcp、防火墙的内容&#xff0c;如果需要文件的可以私我。 一、拓扑图 二、实训需求 某学校新建一个分校区网络&#xff0c;经过与校领导和网络管理员的沟通&#xff0c;现通过了设备选型和组网解决方案&…

JUC- Synchronized原理

对象头概念 以 32 位虚拟机为例 Klass Word&#xff1a;指向类对象的指针&#xff0c;标明这个对象的类型 普通对象 |--------------------------------------------------------------| | Object Header (64 bits) | |---------------…

第二十二讲 python中traceback 模块

目录 1. traceback 模块概述 2.捕获和记录异常 3.traceback 模块的函数 3.1 traceback.format_exc() 3.2 traceback.format_exception(etype, value, tb) 3.3 traceback.print_exc() 3.4 traceback.extract_tb(tb) 1. traceback 模块概述 traceback 模块提供了多种函数&#xf…

django实现手机号归属地查询

要在 Django 中创建一个手机归属地查询页面&#xff0c;前端部分通常包括一个输入框用于输入手机号码和一个按钮用于提交查询请求&#xff0c;随后在页面上显示查询结果。 1. 前端页面设计 在 Django 中&#xff0c;创建一个模板文件&#xff08;例如 phone_location_query.h…