首页 > 其他分享 >网关登录校验

网关登录校验

时间:2024-05-28 16:59:35浏览次数:17  
标签:网关 return 请求 登录 用户 校验 public

  1. 自定义过滤器

    • 网关过滤器有两种,分别是:

    • GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效。

    • GlobalFilter:全局过滤器,作用范围是所有路由;声明后自动生效。

  2. 用自定义的GlobalFilter来完成登录校验

    • 提前准备的工具:

      • AuthProperties:配置登录校验需要拦截的路径,因为不是所有的路径都需要登录才能访问
      • JwtProperties:定义与JWT工具有关的属性,比如秘钥文件位置
      • SecurityConfig:工具的自动装配
      • JwtTool:JWT工具,其中包含了校验和解析token的功能
      • hmall.jks:秘钥文件
    • 其中AuthProperties和JwtProperties所需的属性要在application.yaml中配置

    hm:
      jwt:
        location: classpath:hmall.jks # 秘钥地址
        alias: hmall # 秘钥别名
        password: hmall123 # 秘钥文件密码
        tokenTTL: 30m # 登录有效期
      auth:
        excludePaths: # 无需登录校验的路径
          - /search/**
          - /users/login
          - /items/**
    
    • 定义一个登录校验的过滤器:网关已经可以完成登录校验并获取登录用户身份信息,在网关模块进行配置,只要是请求就都到这个过滤器走一遍,排除的就直接放行,拦截到的就进行登录校验,校验通过后将user信息放到请求头中就放行,这样后面的微服务就可以拿到当前这个登录人的登录信息。
    @Component
    @RequiredArgsConstructor
    @EnableConfigurationProperties(AuthProperties.class)
    public class AuthGlobalFilter implements GlobalFilter, Ordered {
    
        private final JwtTool jwtTool;
    
        private final AuthProperties authProperties;
    
        private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 1.获取Request
            ServerHttpRequest request = exchange.getRequest();
            // 2.判断是否不需要拦截
            if(isExclude(request.getPath().toString())){
                // 无需拦截,直接放行
                return chain.filter(exchange);
            }
            // 3.获取请求头中的token
            String token = null;
            List<String> headers = request.getHeaders().get("authorization");
            if (!CollUtils.isEmpty(headers)) {
                token = headers.get(0);
            }
            // 4.校验并解析token
            Long userId = null;
            try {
                userId = jwtTool.parseToken(token);
            } catch (UnauthorizedException e) {
                // 如果无效,拦截
                ServerHttpResponse response = exchange.getResponse();
                response.setRawStatusCode(401);
                return response.setComplete();
            }
    
            // TODO 5.如果有效,传递用户信息
            System.out.println("userId = " + userId);
            // 6.放行
            return chain.filter(exchange);
        }
    
        private boolean isExclude(String antPath) {
            for (String pathPattern : authProperties.getExcludePaths()) {
                if(antPathMatcher.match(pathPattern, antPath)){
                    return true;
                }
            }
            return false;
        }
    
        @Override
        public int getOrder() {
            return 0;
        }
    }
    
  3. 当网关将请求转发到微服务时,微服务又该如何获取用户身份呢?可以将用户信息以请求头的方式传递到下游微服务。然后微服务可以从请求头中获取登录用户信息。考虑到微服务内部可能很多地方都需要用到登录用户信息,因此我们可以利用SpringMVC的拦截器来实现登录用户信息获取,并存入ThreadLocal,方便后续使用

    • 改造网关过滤器,在获取用户信息后保存到请求头,转发到下游微服务

    • 拦截器获取用户:由于每个微服务都有获取登录用户的需求,因此拦截器我们直接写在通用工具类模块中,并写好自动装配。这样微服务只需要引入hm-common就可以直接具备拦截器功能,无需重复编写。在此模块中定义一个工具类

    public class UserInfoInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 1.获取请求头中的用户信息
            String userInfo = request.getHeader("user-info");
            // 2.判断是否为空
            if (StrUtil.isNotBlank(userInfo)) {
                // 不为空,保存到ThreadLocal
                    UserContext.setUser(Long.valueOf(userInfo));
            }
            // 3.放行
            return true;
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // 移除用户
            UserContext.removeUser();
        }
    }
    
    • 编写SpringMVC的配置类,配置登录拦截器
    @Configuration
    @ConditionalOnClass(DispatcherServlet.class)
    public class MvcConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new UserInfoInterceptor());
        }
    }
    
    • 但是因为这个配置类默认是不会生效的,因为目前它所在的包是com.hmall.common.config,与其他微服务的扫描包不一致,无法被扫描到,因此无法生效,基于springboot的自动装配原理,我们要将其添加到resources目录下的META-INF/spring.factories文件中
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      com.hmall.common.config.MyBatisConfig,\
      com.hmall.common.config.MvcConfig
    
  4. OpenFeign传递用户: 有些业务是比较复杂的,请求到达微服务后还需要调用其它多个微服务,比如一个复杂的下单业务,所以必须在微服务发起调用时把用户信息存入请求头:

    • 借助Feign中提供的一个拦截器接口:feign.RequestInterceptor,实现这个接口,然后实现apply方法,利用RequestTemplate类来添加请求头,将用户信息保存到请求头中,目的是让每一个由OpenFeign发起的请求自动携带登录用户信息。
     @Bean
    public RequestInterceptor userInfoRequestInterceptor(){
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate template) {
                // 获取登录用户
                Long userId = UserContext.getUser();
                if(userId == null) {
                    // 如果为空则直接跳过
                    return;
                }
                // 如果不为空则放入请求头中,传递给下游微服务
                template.header("user-info", userId.toString());
            }
        };
    }
    

标签:网关,return,请求,登录,用户,校验,public
From: https://www.cnblogs.com/hytip/p/18217670

相关文章

  • 企业微信H5授权登录
    在企业中如果需要在打开的网页里面携带用户的身份信息,第一步需要获取code参数如何实现企业微信H5获取当前用户信息即accessToken?1.在应用管理--》创建应用2.创建好应用,点击应用主页-》设置-》网页-》将授权链接填上去官方文档可以看这---->构造网页授权链接-接口文档-......
  • 网关限流方案
    网关限流是保护后端服务的一种常见方法,它可以防止流量激增导致系统崩溃。以下是几种常见的网关限流方案及其实现示例:一、基于Nginx的限流1.配置示例(nginx)http{#定义限速器limit_req_zone$binary_remote_addrzone=mylimit:10mrate=1r/s;server{......
  • uniapp 微信小程序 登录时 记住账号、密码
    登录时,记住账号和密码。点击radio取消,就取消账号密码记住radio点击checkedTap1(){ this.radioPactChecked=!this.radioPactChecked },点击登录login(){ if(this.radioPactChecked){ this.loading=true this.$H.post('/login',{ "username":th......
  • HTTP的系统登录页面,如何避免明文传输用户密码?
    系统登录页面,作为开发人员,应该没有陌生的吧。就像下面这样子。 点击登录,调用/login接口。来看下面截图中的载荷(payload)数据,其中,密码password的值是明文。 如果你的站点使用的是HTTPS协议,配置了有效的SSL证书,那将很好。HTTPS通过SSL/TLS协议建立安全的加密通信通道,确保......
  • Go实战全家桶之九:统一网关
    开源:https://gitee.com/ichub/gocenter.git代码:配置:gateway:bypass:-path:/goauth/login-path:/goauth/logoutroutes:-path:/datadictserviceId:web.platform.com-path:/deptempserviceId:web.platform.com-p......
  • 网关路由快速入门
    在SpringBoot中整合SpringCloudGateway是一个常见的需求,尤其是当需要构建一个微服务架构的应用程序时。SpringCloudGateway是SpringCloud生态系统中的一个项目,它提供了一个API网关,用于处理服务之间的请求路由、安全、监控和限流等功能。使用引入依赖<dependency>......
  • 创建一个配置为信任所有HTTPS连接的RestTemplate实例,不验证服务器的SSL证书。这个示
    这个配置类使用背景:可参考博客:springboot使用restTemplate发送https请求忽略ssl证书https://jsonll.blog.csdn.net/article/details/129191580?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-1......
  • ssh 登录远程ssh 和退出
    登录远程SSH服务器通常使用以下命令:bashssh用户名@远程主机地址替换 用户名 为你的远程服务器账户名,远程主机地址 为服务器的IP地址或域名。例如,如果你的用户名是 yourusername,服务器地址是 example.com,则命令将是:[email protected]登录后,你将在......
  • 使用istio服务网格作为api网关
    API网关作为客户端访问后端的入口由来已久,主要是管理“南北”流量,近几年开始流行ServiceMesh架构,主要是管理内部系统,(即“东西”流量),而像Istio这样的服务网格也有内置网关,可以将系统内外的流量置于统一控制之下。这通常会给Istio的初次用户带来困惑。ServiceMesh和A......
  • js怎么保存用户登录信息?js cookie操作封装
    在web开发中,用户登录后需要保存登录信息进行身份识别,登录后的操作都需要带上身份信息请求接口。保存登录信息有多种方法,这里使用cookie进行操作。最终成果:封装cookie操作模块//utils/cookie.jsexportdefault{//设置cookiesetCookie:function(name,value,......