AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
![](https://img.kancloud.cn/75/7c/757c5749fb417a443b05b78664e9a5e8_455x296.png) 在上一小节中我们已经实现了用户登录认证,用户如果认证成功后会返回给用户客户端一个令牌,也就是JWT。本节我们继续为大家介绍,当用户客户端再次访问网关的其他服务的时候,需要携带JWT,网关验证JWT的合法性,并从JWT中解析出用户身份信息转发出去。 ## 一、全局过滤器实现JWT鉴权 对于网关的所有请求都要验证JWT的合法性(除了“/authentication”),所以使用Gateway全局过滤器 GlobalFilter就再合适不过了。在上一节代码基础上增加一个全局过滤器 ~~~ @Configuration public class JWTAuthCheckFilter { @Resource private JwtProperties jwtProperties; @Resource private JwtTokenUtil jwtTokenUtil; @Bean @Order(-101) public GlobalFilter jwtAuthGlobalFilter() { return (exchange, chain) -> { ServerHttpRequest serverHttpRequest = exchange.getRequest(); ServerHttpResponse serverHttpResponse = exchange.getResponse(); String requestUrl = serverHttpRequest.getURI().getPath(); if(!requestUrl.equals("/authentication")){ //从HTTP请求头中获取JWT令牌 String jwtToken = serverHttpRequest .getHeaders() .getFirst(jwtProperties.getHeader()); //对Token解签名,并验证Token是否过期 boolean isJwtValid = jwtTokenUtil.isTokenExpired(jwtToken); if(isJwtNotValid){ //如果JWT令牌不合法 return writeUnAuthorizedMessageAsJson(serverHttpResponse,"请先去登录,再访问服务!"); } //从JWT中解析出当前用户的身份(userId),并继续执行过滤器链,转发请求 ServerHttpRequest mutableReq = serverHttpRequest .mutate() .header("userId", jwtTokenUtil.getUsernameFromToken(jwtToken)) .build(); ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build(); return chain.filter(mutableExchange); }else{ //如果是登录认证请求,直接执行不需要进行JWT权限验证 return chain.filter(exchange); } }; } //将JWT鉴权失败的消息响应给客户端 private Mono<Void> writeUnAuthorizedMessageAsJson(ServerHttpResponse serverHttpResponse,String message) { serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED); serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); AjaxResponse ajaxResponse = AjaxResponse.error(CustomExceptionType.USER_INPUT_ERROR,message); DataBuffer dataBuffer = serverHttpResponse.bufferFactory() .wrap(JSON.toJSONStringWithDateFormat(ajaxResponse,JSON.DEFFAULT_DATE_FORMAT) .getBytes(StandardCharsets.UTF_8)); return serverHttpResponse.writeWith(Flux.just(dataBuffer)); } } ~~~ 过滤器核心代码做了两件事 * 验证JWT的合法性,对于不合法请求直接返回,不予转发。 * 对于JWT合法的情况,从JWT中解析出userId(用户身份信息),并放入HTTP header中。(网关后面的服务会用到,下一节) ![](https://img.kancloud.cn/bc/63/bc63c53b2cb2131a5d01ebf2554ecb0e_602x208.png) 请结合上面的注释理解全局JWT鉴权的实现。如果理解有困难,结合下面的测试过程理解上面的代码。 ## 二、测试 * 不携带JWT token访问`http://127.0.0.1:8777/sysuser/pwd/reset`。 ![](https://img.kancloud.cn/51/1a/511aee41f393ce6d0c9406fc0d34906b_1203x539.png) * 去登陆`http://127.0.0.1:8777/authentication`,得到JWT令牌 ![](https://img.kancloud.cn/bc/51/bc51aa51f5a6db80ab6366c4eb6db60f_1268x643.png) * 将JWT令牌添加到`http://127.0.0.1:8777/sysuser/pwd/reset`访问请求的Header中,再次发起请求 ![](https://img.kancloud.cn/95/c6/95c6d9391a62753758acb737572f57c5_1038x91.png) 结果如下 ![](https://img.kancloud.cn/c9/f6/c9f698660d88383a4c799ec75aa4ded1_368x129.png) 我们随便修改一下JWT令牌字符串,再次访问`http://127.0.0.1:8777/sysuser/pwd/reset`,结果如下: ![](https://img.kancloud.cn/29/3a/293a3dd58de419dafb0edd747ba3eb3c_455x114.png)