spring cloud gateway 路由转发 token校验

微服务的时代背景下,多个服务之间协同合作已经成为常态,一个高可用的项目应该将细粒度化业务,多节点部署。网关转发即多个服务的门户,暴露一个接口对外,安全性高,只需要在网关层做校验,其余的服务依赖网关转发,代码不冗余,可读性强。

pom依赖:

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>
spring-cloud-starter-netflix-eureka-client
            </artifactId>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.2</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.60</version>
        </dependency>

注:pom文件中不要引入web依赖,网关和网页严格区分开

yml文件:

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true  #开启注册中心路由功能

      routes:
        - id: payment_routh
          uri: lb://cloud-payment-service 
          predicates: # 断言 先判断是否满足这个接口的规则 满足返回true继续访问 不满足 直接返回false
            - Path=/**
        - id: payment_routh2
          uri: lb://cloud-order-service
          predicates:
            - Path=/**
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://127.0.0.1:7001/eureka 

这里的注册中心 没有用nacos/consul 用的是自带的eureka,写了几个demo 都注册到注册中心中,方便网关转发。

主启动类:

@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
    public static void main(String[] args) {
        SpringApplication.run(GateWayMain9527.class, args);
    }
}

其实就已经可以简单转发了。为了接口的安全性 我加上了token进行校验

TokenUtil工具类 用于生成和校验token

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenUtil {
    //设置过期时间
    private static final long EXPIRE_DATE=60*1000*60*12;
    //token秘钥
    private static final String TOKEN_SECRET = "ZCfasfhuaUUHufguGuwu2020BQWE";


    public static String token (String username){

        String token = "";
        try {
            //过期时间
            Date date = new Date(System.currentTimeMillis()+EXPIRE_DATE);
            //秘钥及加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            //设置头部信息
            Map<String,Object> header = new HashMap<>();
            header.put("typ","JWT");
            header.put("alg","HS256");
            //携带username,生成签名
            token = JWT.create()
                    .withHeader(header)
                    .withClaim("username",username)
                    .withExpiresAt(date)
                    .sign(algorithm);
        }catch (Exception e){
            e.printStackTrace();
            return  null;
        }
        return token;
    }

    /**
     * @desc   验证token,通过返回true
     * @params [token]需要校验的串
     **/
    public static boolean verify(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return  false;
        }
    }
}

访问所有接口前,增加校验

TokenHandle类

mport com.alibaba.fastjson.JSON;
import com.springcloud.entities.CommonResult;
import org.apache.commons.lang.StringUtils;
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.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.Flux;
import reactor.core.publisher.Mono;



@Component
public class TokenHandle implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String path = request.getURI().getPath();
        //如果是登陆接口 就直接放过校验
        if(path.indexOf("/login")>=0){
            return chain.filter(exchange);
        }
        String token = request.getHeaders().getFirst("token");
        if(StringUtils.isEmpty(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return getMono(response,"token 缺失");
        }
        boolean verify = TokenUtil.verify(token);
        if(!verify){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return getMono(response,"token 失效");
        }

        return chain.filter(exchange);
    }

    public Mono<Void> getMono(ServerHttpResponse response,String msg){
        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
        CommonResult<Object> objectCommonResult = new CommonResult<>();
        objectCommonResult.setCode(-1);
        objectCommonResult.setMessage(msg);
        DataBuffer wrap = response.bufferFactory().wrap(JSON.toJSONString(objectCommonResult).getBytes());
        return response.writeWith(Flux.just(wrap));

    }

    @Override
    public int getOrder() {
        return -100;
    }
}

这样一个完整的网关就可以运行了,只要在登陆接口 生成token传给前端 让前端进行保存,后端不做维护,只校验规则即可。

完整代码可访问:https://gitee.com/threetime/springcloud2020

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Gateway是一个轻量级的网关框架,它可以作为微服务架构中的入口,实现代理和路由功能。在进行身份验证和授权时,可以使用Token进行安全验证Token是一种令牌,通常由后端服务颁发给客户端,用于验证客户端的身份和权限。在Spring Cloud Gateway中使用Token可以通过以下方式实现: 1. 首先,客户端在请求头中携带Token,可以使用常见的认证方案,如Bearer Token。在路由的配置文件中,可以通过添加过滤器来获取请求头中的Token,并进行验证。 2. 在网关层,可以编写自定义的GlobalFilter过滤器,在请求到达后执行Token验证逻辑。可以通过解析Token的信息,比如用户名、角色等,来进行用户身份验证和授权操作。 3. 在网关层,还可以使用Spring Security进行身份验证和授权。Spring Security提供了丰富的特性,如基于角色的访问控制、加密解密等。可以通过配置Spring Security的过滤器链来实现Token验证的功能。 使用Token进行安全验证的好处是,可以将验证逻辑移到网关层,使后端服务更加专注于业务逻辑的实现Token的使用可以提供更高的灵活性和安全性,保护后端服务免受未经授权的访问。 总之,Spring Cloud Gateway可以通过添加过滤器、编写GlobalFilter过滤器或使用Spring Security来实现Token的安全验证。这样可以保护后端服务,确保只有经过身份验证和授权的客户端能够访问服务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值