ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot整合SpringCloud组件-Gateway网关

2021-12-11 14:02:19  阅读:187  来源: 互联网

标签:网关 SpringBoot SpringCloud token 路由 import gateway cloud


一、网关的简单介绍

(一)网关的定义和职能

1、网关的的定义

网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。

API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。

2、网关的的职能

在这里插入图片描述

(二)Gateway的介绍

1、什么是Gateway

Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。

2、为什么要用Gateway

Gateway是用来替代Zuul网关的,其明确的区分了Router和Filter,并且内置了许多功能都可以通过配置就行直接使用。
其内置了多种Router,可以在配置文件中根据Header、Path、Host等方式来做路由,我后面只介绍通过path的方式进行路由,至于其他方式可以自行查看网上资料。
其也内置了一般Filter和全局Filter,我们也可以自定义Filter进行业务处理,后面将介绍通过内置的Filter对请求path进行处理以及通过自定义Filter对token进行校验。

在这里插入图片描述

3、概念

在这里插入图片描述

二、基础路由规则的配置使用

(一)项目说明

用gateway作为项目的整体网关,所有请求都先打到gateway上,经过安全、权限过滤以后通过的请求再根据路由规则从nacos上获取服务名然后转发到对应的服务上。

gateway网关项目整体就是一个springboot项目,在项目里面做路由配置以及权限过滤等操作,该项目整体结构如下:
在这里插入图片描述

(二)依赖的导入

由于是微服务的,所以需要导入springcloud和springCloudAlibaba的依赖,至于2者与springboot版本之间的应该选择哪个版本可以参考我之前的文章:Spring,SpringCloud,SpringCloudAlibaba各版本对应关系
在这里插入图片描述
在这里插入图片描述
由于要用nacos做为注册中心获取各服务的真实地址,所以还需要导入nacos
在这里插入图片描述

当然gateway本身的依赖也是必不可少的
在这里插入图片描述

(三)配置文件说明

server:
  port: 7000
#
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      globalcors:
        # gateway 跨域设置
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedHeaders: "*"
            allowCredentials: true
            allowedMethods:
              - GET
              - POST
              - PUT
              - OPTIONS
      discovery:
        locator:
          ####开启以服务id去注册中心上获取转发地址
          enabled: true
        ###路由策略
      routes:
        ##路由策略id
        - id: cloud-admin
          #### 基于lb负载均衡形式转发(通过注册中心服务名称,获取真实访问地址)
          uri: lb://cloud-admin
          ###匹配规则
          predicates:
            - Path=/cloud-admin/**
          filters:
            # 去除的路径前缀的个数(strip)
            - StripPrefix=1
    nacos:  #注册中心地址
      discovery:
        server-addr: 10.10.83.73:8848

配置文件解释:
跨域和nacos注册中心的配置就不说了,主要细说路由策略
1)上面配置了一个路由规则id为cloud-admin,当请求的路径为/cloud-admin/**时将请求通过负载均衡转发到服务名为cloud-admin的服务上,从nacos上根据服务名获取服务真是地址进行转发。
2)至于配置文件中的StripPrefix=1代表将请求的前缀去除一个,例如我的请求路径是/cloud-admin/user/getUserById,该请求被转发至cloud-admin服务上时请求路径就变成了/user/getUserById。

为什么要去除前缀,直接用/user/getUserById不就行了吗?
前端服务可能会调取多个后端服务的方法,如果不在路径上做区分,等所有请求都到gateway时就没法区分调用哪个服务。

注:路由策略有很多,我只是用来path来做路由,真正用的时候可能多个Router共同组合来做策略。

三、全局token校验处理

gateway不仅能做路由转发,还能对所有的请求进行权限校验、过滤。我这个项目中需要在gateway中校验是否携带token,token校验通过以后把提取到的用户id再传到后面的服务中。
我在项目中自定义了一个token然后实现全局的filter,这样所有的请求都得进行token校验,代码如下:

package com.cloud.cloudgateway.filter;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * @Description: 自定义全局token校验
 * @Author: yl
 * @Date: 2021年10月9日15:42:31
 */
@Component
public class GlobalTokenFilter  implements GlobalFilter, Ordered {

    private static final String PATH = "/login";
    public static final String SECRET = "develop-Platform";            // JWT密钥
    public static final String TOKEN_KEY = "Authorization";// 存放Token的Header Key

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();

        // 获取请求路径
        String path = request.getPath().toString();
        //登录请求直接到认证服务
        if(path.contains(PATH)){
            return chain.filter(exchange);
        }

        //验证token
        HttpHeaders headers = request.getHeaders();
        List<String> headerList = headers.get(TOKEN_KEY);
        if(headerList.isEmpty()){
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            String msg = "无token,请重新登录";
            DataBuffer buffer = response.bufferFactory().wrap(msg.getBytes());
            return response.writeWith(Mono.just(buffer));
        }

        String token = headerList.get(0);
        String userId;
        try {
            userId = JWT.decode(token).getAudience().get(0);
        } catch (JWTDecodeException j) {
            throw new RuntimeException("401");
        }

        // 验证 token
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
        try {
            jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            throw new RuntimeException("401");
        }

        ServerHttpRequest host = request.mutate().header("userId",userId).header("userToken",token).build();

        //将request变成change对象
        ServerWebExchange build = exchange.mutate().request(host).build();
        return chain.filter(build);
    }

    //实现Ordered接口保证优先级,值越小加载的优先级越高
    @Override
    public int getOrder() {
        return -1;
    }
}

标签:网关,SpringBoot,SpringCloud,token,路由,import,gateway,cloud
来源: https://blog.csdn.net/xiaoye319/article/details/121872546

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有