springcloud-gateway-2-鉴权

这篇具有很好参考价值的文章主要介绍了springcloud-gateway-2-鉴权。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、跨域安全设置

二、GlobalFilter实现全局的过滤与拦截。

三、GatewayFilter单个服务过滤器

1、原理-官方内置过滤器

2、自定义过滤器-TokenAuthGatewayFilterFactory

3、完善TokenAuthGatewayFilterFactory的功能

4、每一个服务编写一个或多个过滤器,实现鉴权的需要

四、总结


续前篇,介绍了gateway中实现了动态路由转发功能以后,本篇将介绍何在spring gateway中实现鉴权的功能。

鉴权目的就是为了安全。仅开放给指定的有权限的合适的人资源。网关在提供统一的路由解析的同时,会提供统一和token认证,统一的加解密,统一的身份认证等功能。

一般作为网关,需要转发的服务较多,在服务级权限分类上,可能有这么几种类理:

  • 直接放行,比如静态资源。当然这种一般建议直接在nginx跳转,减少网关流量。但是还是会有一些比如login等,需要直接放行的接口。
  • 需要jwt等TOKEN验证。在请求头中携带token字段,用来验证是否有合适的身份。这个用得比较多,通常会把token存到redis中。
  • 需要sign验证。在请求头或url参数中携带sign验证字段。可能采用md5等计算方法。
  • 需要jwt验证,同时需要对报文进行加密传输。比如采用rsa\m3等加密。
  • 除此之外还有黑名单。需要全局生效

针对上面的需求,我们就可以利用下面这两个过滤器进行分类实现: 

  • GlobalFilter 全局过滤器
  • GatewayFilter 将应用到单个路由或者同一个分组中的路由上

一、跨域安全设置

如果生产环境限定域名的,可以配置。如果前后端分离的,一般要设置允许所有的网站访问。

    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedMethods: # 支持的方法
              - GET
              - POST
              - PUT
              - DELETE

二、GlobalFilter实现全局的过滤与拦截。

利用GlobalFilter实现全局过滤-黑名单功能,新建一个类,继承GlobalFilter就好了:

package com.iuyun.gateway.filter;

import com.iuyun.gateway.services.IpService;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * 这是自定义的全局过滤器
 * 1、 黑名单禁止访问
 * 2、 ...

 */
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {

    @Resource
    IpService ipService;

    @Override
    public int getOrder() {
        // TODO Auto-generated method stub
        return -1;   // 数字越小,优先级越高。定义-1为最高优先级
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        System.out.println("MyGlobalFilter: uri:" + request.getURI() );

        
        // 获取请求ip
        String ip = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();


        // 1 调用服务,检查是否在黑名单池内.如果是黑名单,则中断。
        if (ipService.isIpBlocked(ip)) {
            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
            return exchange.getResponse().setComplete();
        }

        // 2 执行其他全局服务

        // 3 放行
        return chain.filter(exchange);
    }

}

调用到的方法(模拟): 


@Service
public class IpService {

    /**
     *  根据IP地址查询数据库中的黑白名单列表,判断是否被阻止
     * */

    public boolean isIpBlocked(String ipAddress) {
        System.out.println("ip:"+ipAddress);
        // 将ip去redis或者数据库中查找,是否在黑名单内。
        //    return count >0; // 只要出现条数大于0,则表示在默名单内

        // 这里面是模拟,写死了
        return ipAddress.equals("192.168.2.3");

    }
}

 测试:我们从不同IP来访问不同的服务,可以看到都会被执行:

springcloud-gateway-2-鉴权,spring cloud,gateway,spring boot

 当IP在黑名单内时,会返回403:

springcloud-gateway-2-鉴权,spring cloud,gateway,spring boot

三、GatewayFilter单个服务过滤器

将应用到单个路由或者同一个分组中的路由上。

1、原理-官方内置过滤器

我们先看一下官方的示例:

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue
表示使用过滤器AddResponseHeader,=后面的是参数,它接收一个名称和一个正则表式。

那我们去看看它是怎么实现的:

springcloud-gateway-2-鉴权,spring cloud,gateway,spring boot

看了一下其他的filterFactory,都差不多,简单总结一下:

1、命名:PrefixPathGatewayFilterFactory => XXXXGatewayFilterFactory

2、继承抽象类 AbstractGatewayFilterFactory<PrefixPathGatewayFilterFactory.Config> 

3、重写方法GatewayFilter apply(Config config)

我们如果照抄一份,是不是就可以实现自定义过滤器了呢?下面我就来试一下。

2、自定义过滤器-TokenAuthGatewayFilterFactory

1)编写一个GatewayFilterFactory(复制AddResponseHeaderFilterFactory的内容,改个名)


@Component
public class TokenAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                String value = ServerWebExchangeUtils.expand(exchange, config.getValue());
                exchange.getResponse().getHeaders().add(config.getName(), value);
                System.out.println("config.getName():" + config.getName());
                System.out.println("value:" + value);

                return chain.filter(exchange);
            }

            @Override
            public String toString() {
                return filterToStringCreator(TokenAuthGatewayFilterFactory.this)
                        .append(config.getName(), config.getValue()).toString();
            }
        };
    }

}

2)application配置

springcloud-gateway-2-鉴权,spring cloud,gateway,spring boot

3)重启,看一下测试效果

 springcloud-gateway-2-鉴权,spring cloud,gateway,spring boot

先走了全局过滤器,然后这个se-a服务走了这个filter,打印了变量。

这就证明了可以这样实现自定义过滤器,那么,我们在gateway中做任何的校验就方便了。且predicates和filters是可以使用多个进行组合的:

filters: 
  - StripPrefix=1
  - TokenAuth=jwt,Hello
  - AddResponseHeader=jwt,Hello1

这样就使用了三个filter。

3、完善TokenAuthGatewayFilterFactory的功能

(这个过程就根据自己的需要进行编写吧,比如,采用RSA加密,sm3加密,验证JWT等)

这里我模拟一个需求如下:

每次请求必须在请求头或url参数中传递一个token字段。

如果没有直接拒绝请求.如果token不对,返回401。

只有token正确,才放行,并在请求头添加一个userId字段传递给被调用的微服务。

要想实现直接拒绝不响应,可以使用predicatie,不符合条件就返回404了

- id: service-a
  uri: lb://service-a # lb:服务名称。表示调用nacos注册的服务名称为service-b的服务
  predicates:
    - Path=/se-a/**
    - Header=token,\d+
  filters: 
    - StripPrefix=1  
    - TokenAuth=jwt,Hello

但是这样并不友好,有统一返回值是现在流行的做法。且万一在prdicates中忘记加这个Header了,在filter中就因为没有token字段而出错。所以为了防止出错在filter还是要再进行一次token是否为空的校验,那么就干脆都在filter中实现吧。


@Component
public class TokenAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {

    @Override
    public GatewayFilter apply(NameValueConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                String value = ServerWebExchangeUtils.expand(exchange, config.getValue());  // config.getValue()  config.getName()
                String headerToken = exchange.getRequest().getHeaders().getFirst("token");
                String urlToken = exchange.getRequest().getQueryParams().getFirst("token");

                // 优先使用header中的token,其次是url中的token,如果没有则继续为null
                String reqToken =StringUtils.isBlank(headerToken)? urlToken:headerToken;
                // 检查token是否存在且正确,一般都需要去调auth服务,从数据库或redis拿到密码并校验
                String userId = TokenCheck.JwtCheck(reqToken);
                if(StringUtils.isBlank(reqToken) || StringUtils.isBlank(userId)){
                    // 返回状态码401表示未授权
                    exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                    return exchange.getResponse().setComplete();
                }

                // 运行到这里,表示token计算正确。将UserID添加到header进行传递
                ServerHttpRequest request = exchange.getRequest().mutate()
                        .headers(httpHeaders -> httpHeaders.add("userId",userId)).build();

                return chain.filter(exchange.mutate().request(request).build());
            }

            @Override
            public String toString() {
                return filterToStringCreator(TokenAuthGatewayFilterFactory.this)
                        .append(config.getName(), config.getValue()).toString();
            }
        };
    }

}
@Component
public class TokenCheck {

    public static String JwtCheck(String token){
        // 去redis获取是否存在这个token,如果不存在,则表示未登陆或登陆已过期。
        // 如果没存到redis,则这里要粗数据库调user表,查询用户的密码,并调用jwt的方法计算密码是否正确

        // 这里做模拟,先写死。如果正确,返回一个userId =
        if(!StringUtils.isBlank(token) && !token.equals("jwt11234")){
            return null;
        }else{
            // 这里写死,返回一个userID
            return "admin";
        }
    }
}

4、每一个服务编写一个或多个过滤器,实现鉴权的需要

也可以多个服务使用同一个过滤器。

springcloud-gateway-2-鉴权,spring cloud,gateway,spring boot文章来源地址https://www.toymoban.com/news/detail-770652.html

四、总结

由于本篇重点是讲gateway中如何实现鉴权,所以并未展开介绍。在上面的示例中,我们并没有真的实现jwt验证等,只是做了一个固定值的返回。后面我们将继续介绍实现jwt的验证。

到了这里,关于springcloud-gateway-2-鉴权的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringCloud-Gateway实现RSA加解密

    Gateway网关作为流量的入口,有的接口可能需要对请求内容加密,返回结果加密,保证数据安全性。 一、RSA介绍         RSA主要使用大整数分解这个数学难题进行设计,巧妙地利用了数论的概念。给了RSA公钥,首先想到的攻击就是分解模数,给了的因子攻击者可以计算得到

    2024年02月16日
    浏览(51)
  • SpringCloud-Gateway路由动态配置Nacos实现

    编写配置类 properties添加配置 自定义RouteDefinitionLocator 编写GatewayDynamicConfiguration配置类

    2024年02月07日
    浏览(50)
  • springcloud-gateway升级版本allowedOrigins要改allowedOriginPatterns

    前言 报错: 原因:springboot升级2.6.0后所出现的问题 解决方法:将.allowedOrigins 替换成. allowedOriginPatterns 即可。 如下图: ps:这是2.3时代的配置,现在不叫这个了,要用:

    2024年02月22日
    浏览(46)
  • springcloud-gateway集成knife4j

    springcloud-gateway集成knife4j(swagger2) 环境信息 准备工作 微服务集成knife4j 第一步:编写Knife4jApiInfoProperties 第二步:编写配置类Knife4jConfig 第三步:放行相关资源 保证启动了knife4j 网关集成knife4j 编写配置类Knife4jGatewayConfig 测试验证 相关资料 spring-boot:2.6.3 spring-cloud-alibaba:2

    2023年04月09日
    浏览(40)
  • 【springcloud 微服务】Spring Cloud 微服务网关Gateway使用详解

    目录 一、微服务网关简介 1.1 网关的作用 1.2 常用网关 1.2.1 传统网关 1.2.2 云原生网关

    2023年04月16日
    浏览(55)
  • Spring Boot 中的 Spring Cloud Gateway

    Spring Cloud Gateway 是一个基于 Spring Boot 的网关框架,它提供了一种统一的入口,将所有的请求路由到不同的后端服务中。Spring Cloud Gateway 采用了 Reactive 编程模型,可以处理大量并发请求,同时还具备负载均衡、熔断、限流等功能。本文将介绍 Spring Cloud Gateway 的原理和使用方法

    2024年02月12日
    浏览(49)
  • 【SpringCloud】11、Spring Cloud Gateway使用Sentinel实现服务限流

    1、关于 Sentinel Sentinel 是阿里巴巴开源的一个流量防卫防护组件,可以为微服务架构提供强大的流量防卫能力,包括流量控制、熔断降级等功能。Spring Cloud Gateway 与 Sentinel 结合,可以实现强大的限流功能。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近

    2024年02月01日
    浏览(57)
  • Java之SpringCloud Alibaba【七】【Spring Cloud微服务网关Gateway组件】

    Java之SpringCloud Alibaba【一】【Nacos一篇文章精通系列】 跳转 Java之SpringCloud Alibaba【二】【微服务调用组件Feign】 跳转 Java之SpringCloud Alibaba【三】【微服务Nacos-config配置中心】 跳转 Java之SpringCloud Alibaba【四】【微服务 Sentinel服务熔断】 跳转 Java之SpringCloud Alibaba【五】【微服务

    2024年02月06日
    浏览(64)
  • SpringCloud - Spring Cloud 之 Gateway网关,Route路由,Predicate 谓词/断言,Filter 过滤器(十三)

    阅读本文前可先参考 ​​​​​​SpringCloud - Spring Cloud根/父项目,开发准备(二)_MinggeQingchun的博客-CSDN博客 SpringCloud - Spring Cloud 之 Gateway网关(十三)_MinggeQingchun的博客-CSDN博客 Web 有三大组件(监听器 过滤器 servlet),Spring Cloud GateWay 最主要的功能就是路由转发,而在定义

    2024年02月14日
    浏览(67)
  • spring cloud整合spring boot,整合nacos、gateway、open-feign等组件

    想看具体详情的可以看我的github链接:codeking01/platform-parent: spring cloud整合spring boot、nacos、gateway、open feign等组件 (github.com) 由于我升级了jdk17,所以用上了spring boot 3.0.2了。 踩坑无数,一堆无用文章,写来写去,本文主要是提供给有基础的开发者再次快速搭建使用(确定版本

    2024年02月11日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包