Spring Cloud Gateway+Spring Security OAuth2+JWT(二)

拼搏现实的明天。 2024-04-19 11:06 123阅读 0赞

Spring Cloud Gateway+Spring Security OAuth2+JWT(二)

  • 前言
  • Gateway校验token
  • 服务获取token
  • 效果

前言

上一篇搭建了授权服务,这篇我们来讲讲网关。

Gateway校验token

我们的目标是校验token并将其解密之后传给服务。
校验token jwt有自带的。其实自己也能实现。jwt由3部分组成都有一个点分隔。

原理是第一部分base64加密 加上一个点 再加上第二部分的base64加密 利用私钥签名。
所以我们只要验第三部分,利用RSA公钥验签就行了。

  1. package com.ljl.filter;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.ljl.common.util.RSAUtil;
  4. import io.jsonwebtoken.Claims;
  5. import io.jsonwebtoken.ExpiredJwtException;
  6. import io.jsonwebtoken.Jwts;
  7. import org.apache.commons.lang.StringUtils;
  8. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
  9. import org.springframework.cloud.gateway.filter.GlobalFilter;
  10. import org.springframework.core.Ordered;
  11. import org.springframework.core.io.buffer.DataBuffer;
  12. import org.springframework.http.HttpHeaders;
  13. import org.springframework.http.HttpStatus;
  14. import org.springframework.http.server.reactive.ServerHttpRequest;
  15. import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
  16. import org.springframework.http.server.reactive.ServerHttpResponse;
  17. import org.springframework.stereotype.Component;
  18. import org.springframework.web.server.ServerWebExchange;
  19. import reactor.core.publisher.Flux;
  20. import reactor.core.publisher.Mono;
  21. import java.net.URI;
  22. import java.nio.charset.StandardCharsets;
  23. import java.util.Arrays;
  24. import java.util.Base64;
  25. import static com.ljl.common.util.RSAUtil.verify;
  26. import static com.sun.scenario.Settings.set;
  27. import static java.security.KeyRep.Type.SECRET;
  28. import static org.bouncycastle.crypto.tls.SignatureAlgorithm.rsa;
  29. /** * Created by Administrator on 2019/9/9 0009. */
  30. @Component
  31. public class JwtTokenFilter implements GlobalFilter,Ordered {
  32. private String[] skipAuthUrls = { "/ljl-auth/oauth/token"};
  33. //需要从url中获取token
  34. private String[] urlToken = { "/ljl-server-chat/websocket"};
  35. /** * 过滤器 * * @param exchange * @param chain * @return */
  36. @Override
  37. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  38. String url = exchange.getRequest().getURI().getPath();
  39. System.out.println(url);
  40. //跳过不需要验证的路径
  41. if (null != skipAuthUrls && Arrays.asList(skipAuthUrls).contains(url)) {
  42. return chain.filter(exchange);
  43. }
  44. //获取token
  45. String token = exchange.getRequest().getHeaders().getFirst("Authorization");
  46. if(null != urlToken && Arrays.asList(urlToken).contains(url)){
  47. //该方法需要修改
  48. String tokens[] = exchange.getRequest().getURI().getQuery().split("=");
  49. token = tokens[1];
  50. }
  51. if (StringUtils.isBlank(token)) {
  52. //没有token
  53. return returnAuthFail(exchange, "请登陆");
  54. } else {
  55. //有token
  56. try {
  57. //解密token
  58. Claims jwt = getTokenBody(token);
  59. ServerHttpRequest oldRequest= exchange.getRequest();
  60. URI uri = oldRequest.getURI();
  61. ServerHttpRequest newRequest = oldRequest.mutate().uri(uri).build();
  62. // 定义新的消息头
  63. HttpHeaders headers = new HttpHeaders();
  64. headers.putAll(exchange.getRequest().getHeaders());
  65. headers.remove("Authorization");
  66. headers.set("Authorization",jwt.toString());
  67. newRequest = new ServerHttpRequestDecorator(newRequest) {
  68. @Override
  69. public HttpHeaders getHeaders() {
  70. HttpHeaders httpHeaders = new HttpHeaders();
  71. httpHeaders.putAll(headers);
  72. return httpHeaders;
  73. }
  74. };
  75. return chain.filter(exchange.mutate().request(newRequest).build());
  76. /*System.out.println(jwt.toString()); //RSA公钥验签 String jwtData[] = token.split("\\."); Boolean isSgin = RSAUtil.verify((jwtData[0]+"."+jwtData[1]).getBytes(),jwtData[2]); if(isSgin){ return chain.filter(exchange); }else{ return returnAuthFail(exchange,"token验签失败"); }*/
  77. }catch (ExpiredJwtException e) {
  78. e.printStackTrace();
  79. return returnAuthFail(exchange,"token超时");
  80. }catch (Exception e) {
  81. e.printStackTrace();
  82. return returnAuthFail(exchange,"token验签失败");
  83. }
  84. }
  85. }
  86. /** * 返回校验失败 * * @param exchange * @return */
  87. private Mono<Void> returnAuthFail(ServerWebExchange exchange,String message) {
  88. ServerHttpResponse serverHttpResponse = exchange.getResponse();
  89. serverHttpResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
  90. String resultData = "{\"status\":\"-1\",\"msg\":"+message+"}";
  91. byte[] bytes = resultData.getBytes(StandardCharsets.UTF_8);
  92. DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
  93. return exchange.getResponse().writeWith(Flux.just(buffer));
  94. }
  95. private static Claims getTokenBody(String token){
  96. return Jwts.parser()
  97. .setSigningKey(RSAUtil.getPublicKey())
  98. .parseClaimsJws(token)
  99. .getBody();
  100. }
  101. @Override
  102. public int getOrder() {
  103. return -201;
  104. }
  105. }

服务获取token

这样我们就能够拿到我们的保存在token中的用户信息

  1. /** * 根据 id 查询 基础数据 * @param id 基础数据 id * @return */
  2. @RequestMapping(value="getBasicDataBy",method={ RequestMethod.GET})
  3. @ApiOperation(value="查询基础数据", httpMethod="GET", notes="查询基础数据", produces="application/json; charset=utf-8")
  4. @ResponseBody
  5. public List getBasicDataBy(@ApiParam(required=true,value="id") @RequestParam(value="id",required=true)String id, HttpServletRequest request) {
  6. String str = request.getHeader("Authorization");
  7. System.out.println(str);
  8. return basicDataService.getBasicDataBy(id);
  9. }

效果

我用的password的模式。
我们先获取token 记得密码和client_secret 都是BCrypt过的,数据库存储的是加密之后的数据。
在这里插入图片描述

之后我们那token去请求服务接口
在这里插入图片描述

好了 初步的搭建已经完成了。不过也有很多没完成。

发表评论

表情:
评论列表 (有 0 条评论,123人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Spring security Oauth2+JWT

    企业级认证授权技术 一丶用户认证与授权 > 每个项目最基本的也是最重要的是安全,用户认证与授权,是最重要的,用户认证身份。 1.1什么是用户身份认证? > 用户身份