• SpringCloud:网关gateway


    一、简介

    网关是一个服务:
    Spring Cloud GateWay是Spring Cloud的⼀个全新项⽬,⽬标是取代Netflix Zuul,基于Spring5.0+SpringBoot2.0+WebFlux(基于⾼性能的Reactor模式响应式通信框架Netty,异步⾮阻塞模型)等技术开发,性能⾼于Zuul,官⽅测试,GateWay是Zuul的1.6倍,旨在为微服务架构提供⼀种简单有效的统⼀的API路由管理⽅式。

    二、开始使用

    1.引入包(gateway)        

    1. <!-- 网关 -->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-gateway</artifactId>
    5. </dependency>
    6. <!-- 负载均衡 -->
    7. <dependency>
    8. <groupId>org.springframework.cloud</groupId>
    9. <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    10. </dependency>

    2. 配置nacos进行服务注册和发现

            描述:使用nacos+gateway实现各模块服务的负载均衡

            nacos的配置使用可以参考文章:

            SpringCloud:注册中心nacos_Cx_轩的博客-CSDN博客

    3..yml配置

    1. spring:
    2. application:
    3. name: Cx-gateway
    4. cloud:
    5. gateway:
    6. httpclient:
    7. connect-timeout: 90000 #连接超时 毫秒
    8. response-timeout: 90s #应答超时 java.time.Duration http状态码504
    9. discovery:
    10. locator:
    11. enabled: false # 启用探测器 默认false,开启后可以通过ip:port/服务名称/接口地址进行服务转发
    12. lower-case-service-id: true # 路由名小写
    13. routes:
    14. - id: Cx-admin # admin后台
    15. uri: lb://Cx-admin
    16. predicates:
    17. - Path=/admin/**
    18. filters:
    19. - StripPrefix=1 # 过滤前缀 admin
    20. - id: Cx-es # es服务
    21. uri: lb://Cx-es
    22. predicates:
    23. - Path=/es/**
    24. filters:
    25. - StripPrefix=1 # 过滤前缀 es

    此处对predicates断言进行使用描述:(常用的几种列举出来方便大家参考)

    1. 1.Path路径断言
    2. predicates:
    3. -Path=/xx # 拦截此路径下的所有请求发送到网关配置的uri (以一个模块一个路径去区分)
    4. 2.Query断言
    5. predicates:
    6. -Query=name,age. #参数值可以写正则,也可以只写参数名
    7. 3.Method断言
    8. predicates:
    9. -Method=get
    10. 4.Host断言
    11. predicates:
    12. -Host=xxxx.com
    13. 5.Cookie断言
    14. predicates:
    15. -Cookie=user,Cx #cookie断言和上面介绍的几种断言方式都大同小异,唯一不同的是他必须连同属性值一起验证,不能单独只验证属性是否存在
    16. 6.Header断言
    17. predicates:
    18. -Header=id,1234\d+ # 正则表达式\d+ 数字,header断言是检查头信息里是否携带了相关属性或令牌
    19. 7.时间路由
    20. predicates:
    21. - After=2022-02-07T17:05:00.789+08:00[Asia/Shanghai] # 时间匹配有三种模式,分别是Before、After和Between,指定了在什么时间范围内路由才会生效

    三、网关+单点登录使用

    1.使用jwt生成无状态token令牌,然后在网关项目中进行auth验证。

    2.创建网关全局拦截

    1. @Configuration
    2. @Component
    3. @Slf4j
    4. public class AuthFilter implements GlobalFilter,Ordered {
    5. private static final String AUTHORIZE_TOKEN = "token";
    6. private static AntPathMatcher matcher = new AntPathMatcher();
    7. @Override
    8. public int getOrder() {
    9. return 0;
    10. }
    11. @Override
    12. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    13. ServerHttpRequest request = exchange.getRequest();
    14. String url = request.getPath().toString();
    15. log.info("【登录拦截】获取请求地址路径:"+url);
    16. // 不需要拦截的url直接通过
    17. if(isNotAuth(url)){
    18. return chain.filter(exchange);
    19. }
    20. String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN);
    21. if(StrUtil.isBlank(token)){
    22. token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
    23. }
    24. if(StrUtil.isBlank(token)){
    25. log.info("【登录拦截】未获取到token值...");
    26. loginResponse(exchange);
    27. }
    28. log.debug("【登录拦截】获取token值:"+token);
    29. try {
    30. SSOToken ssoToken = SSOToken.parser(token);
    31. // 获取token中的用户名
    32. String userId = ssoToken.getId();
    33. log.info("【登录拦截】获取userId:"+userId);
    34. } catch (Exception e) {
    35. log.error("【登录拦截】异常:"+e.getMessage());
    36. return loginResponse(exchange);
    37. }
    38. return chain.filter(exchange);
    39. }
    40. public static Mono<Void> loginResponse(ServerWebExchange exchange) {
    41. JSONObject json = JSONUtil.createObj();
    42. json.set("code", 401);
    43. json.set("msg", "请重新登陆授权");
    44. ServerHttpResponse response = exchange.getResponse();
    45. byte[] bytes = JSONUtil.toJsonStr(json).getBytes(StandardCharsets.UTF_8);
    46. //指定编码,否则在浏览器中会中文乱码
    47. response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
    48. DataBuffer buffer = response.bufferFactory().wrap(bytes);
    49. return response.writeWith(Flux.just(buffer));
    50. }
    51. private boolean isNotAuth(String url) {
    52. List<String> uriList = new ArrayList<>();
    53. // admin后台不需要拦截
    54. uriList.add("/admin/**");
    55. uriList.add("/sso/login");
    56. for (String pattern : uriList) {
    57. if (matcher.match(pattern, url)) {
    58. // 不需要拦截
    59. return true;
    60. }
    61. }
    62. return false;
    63. }
    64. }

    上述代码中SSOToken就是jwt的封装,大家可以直接使用jwt进行解析即可。

    注:此处使用jwt无状态token令牌,为了方便不同模块、不同前端项目针对不同ip和端口部署的分布式应用时在进行用户验权时可以不需要考虑会话session和cookie只需要将token存储在浏览器中即可全局使用。在访问时只校验token的有效性。所以在使用jwt的token时可以降低token的有效时长在增加安全性。

  • 相关阅读:
    Python自学之路--002:Python 如何生成exe可执行文件
    内网渗透-常用反弹shell方法总结
    数据分析(1)——如何用postgres快速找出数据库中所有表格包含空值的列
    swift语言下SurfGen库做的爬虫是什么样的 ?
    Winform控件绑定数据
    python解析xml遇到的问题分享(命名空间有关)
    P33 JSlider滑块
    软件测试周刊(第82期):其实所有纠结做选择的人心里早就有了答案,咨询只是想得到内心所倾向的选择。
    【无标题】简析天津某产业园能耗监测系统设计与应用
    战略调整?顺丰科技将从深圳撤退到武汉!
  • 原文地址:https://blog.csdn.net/qq_25223941/article/details/125599768