SpringCloud Gateway配置全局过滤JWT统一Token处理

前言

  今天打算用Jwt给我的微服务毕设进行权限认证,就打算配一个拦截器在网关服务进行拦截,验证Jwt,如果不知道Jwt是什么的小伙伴可以先进行相关知识学习。

存在问题

如果用的是springboot的小伙伴可以直接使用拦截器进行配置,可以忽略这个问题,可以看其他文章直接配置拦截器即可

为什么使用过滤器而不是拦截器

   刚开始我是采用拦截器进行配置,但是拦截器需要导入对应的org.springframework.web包,才能实现HandlerInterceptor这个接口,等我配好之后呢,发现网关服务无法启动,不知道是什么原因,可能存在冲突,去掉对应的拦截器所需的包才能启动,寻思着换过滤器吧,反正功能一样。

在这里插入图片描述

GateWay配置过滤器

1.导入 Jwt包

可以在公共包中导入

 <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
 </dependency>

2.添加一个工具类

public class JWTUtil {
    /**
     * 密钥要⾃⼰保管好
     */
    private static String SECRET = "privatekey#^&^%!save";

    /**
     * 传⼊payload信息获取token
     *
     * @param map payload
     * @return token
     */
    public static String getToken(Map<String, String> map) {
        JWTCreator.Builder builder = JWT.create();
        //payload
        map.forEach(builder::withClaim);
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE, 3); //默认3天过期
        builder.withExpiresAt(instance.getTime());//指定令牌的过期时间
        return builder.sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 验证token
     */
    public static DecodedJWT verify(String token) {
        //如果有任何验证异常,此处都会抛出异常
        return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
    }

    /**
     * 获取token中的payload
     */
    public static Map<String, Claim> getPayloadFromToken(String token) {
        return
                JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token).getClaims();
    }
}

3.新建一个过滤器

@Component
public class JWTFilter implements GlobalFilter, Ordered {
    /**
     * 核心过滤方法:业务处理
     *
     * @param exchange:请求上下文(获取request和response)
     * @param chain:过滤器链(控制程序放行)
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求头中的令牌
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //1、获取当前的请求连接
        String path = request.getURI().getPath();
        //2、判断,此请求地址是否需要进行token检验,如果不需要,直接放行,进入微服务
        if (path.contains("/api/member/register")) { //包含则需要拦截
            R r = new R();
            //获取请求头参数token
            String token = request.getHeaders().getFirst("Authorization");
            try {
                JWTUtil.verify(token);//验证令牌
                chain.filter(exchange);//放行
            } catch (SignatureVerificationException e) {
                e.printStackTrace();
                r = R.error(BizCodeEnume.INVALID_SIGN_EXCEPTION.getCode(), BizCodeEnume.INVALID_SIGN_EXCEPTION.getMsg()); //无效签名
            } catch (TokenExpiredException e) {
                e.printStackTrace();
                r = R.error(BizCodeEnume.TOKEN_EXPIRE_EXCEPTION.getCode(), BizCodeEnume.TOKEN_EXPIRE_EXCEPTION.getMsg()); //token过期
            } catch (AlgorithmMismatchException e) {
                e.printStackTrace();
                r = R.error(BizCodeEnume.TOKEN_DIFFER_EXCEPTION.getCode(),BizCodeEnume.TOKEN_DIFFER_EXCEPTION.getMsg()); //算法不一致
            } catch (Exception e) {
                e.printStackTrace();
                r = R.error(BizCodeEnume.TOKEN_INVALID_EXCEPTION.getCode(),BizCodeEnume.TOKEN_INVALID_EXCEPTION.getMsg()); //token无效
            }
            //3.3作JSON转换
            byte[] bytes = JSON.toJSONString(r).getBytes(StandardCharsets.UTF_8);
            //3.4调用bufferFactory方法,生成DataBuffer对象
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            //指定编码,否则在浏览器中会中文乱码
            response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
            //4.调用Mono中的just方法,返回要写给前端的JSON数据
            return response.writeWith(Mono.just(buffer));
        } else {
            return chain.filter(exchange);
        }

    }

    @Override
    public int getOrder() {
        return 0;
    }
}

4.生成jwt令牌

业务完成后可以生成jwt令牌,放入到响应体中

  @ApiOperation(value = "用户密码登录")
    @PostMapping("/login")
    public R login(HttpServletResponse response, @RequestBody MemberLoginVo vo) {
        MemberEntity entity = memberService.login(vo);
        if (entity != null) {
            //生成JWT令牌
            Map<String, String> payload = new HashMap<>();
            payload.put("id", entity.getId().toString());
            payload.put("username", entity.getUsername());
            //生成Token
            String token = JWTUtil.getToken(payload);
            response.setHeader("Authorization",token);//存到响应体
            response.setHeader("Access-Control-Expose-Headers", "Authorization");
             return R.ok();
        } else {
            return R.error(BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getCode(), BizCodeEnume.LOGINACCT_PASSWORD_INVAILD_EXCEPTION.getMsg());
        }
    }

4.最后

最后可以去试一下效果了,j将jwt存到响应体中,还需要前端把状态存起来,请求的时候还要带上token回来验证jwt,暂时先做到这里,前端怎么做还不太熟。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值