思路: 全局过滤器对所有的请求拦截(生成token有效期30分钟,放入redis设置有效期3天。3天之类可以通过刷新接口自动刷新,超过3天需要重新登录。)

前端在调用接口之前先判断token是否过期(3o分钟),过期则先调刷新接口,换取新token,

1- 引入相关jar

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-gateway</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>io.jsonwebtoken</groupId>
  7. <artifactId>jjwt</artifactId>
  8. <version>0.9.0</version>
  9. </dependency>

2- 编写Jwt工具类(生成token + 解析token)

  1.  
  1. package spring.cloud.gateway.common;
  2.  
  3. import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import io.jsonwebtoken.ExpiredJwtException;
    import org.springframework.util.StringUtils;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
  4.  
  5. public class JwtUtil {
    public static final String SECRET = "qazwsx123444$#%#()*&& asdaswwi1235 ?;!@#kmmmpom in***xx**&";
    public static final String TOKEN_PREFIX = "Bearer";
    public static final String LOGIN_URL = "/token/userId/pwd";
    public static final String LOGOUT_URL = "/token/userId";
    public static final String HEADER_AUTH = "authorization";
    public static final String HEADER_USERID = "userid";
    //token超时时间
    public static final int TOKEN_EXPIRATION_MINUTE = 30;
    //token的redis超时时间
    public static final int TOKEN_REDIS_EXPIRATION_DAY = 7;
  6.  
  7. public static String generateToken(String userId) {
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.MINUTE, TOKEN_EXPIRATION_MINUTE); //得到前一天
    Date date = calendar.getTime();
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    df.format(date);
    //todo 优化token的生层规则
    HashMap<String, Object> map = new HashMap<>();
    map.put(HEADER_USERID, userId);
    String jwt = Jwts.builder()
    .setSubject(HEADER_USERID).setClaims(map)
    .setExpiration(date)
    .signWith(SignatureAlgorithm.HS512, SECRET)
    .compact();
    return TOKEN_PREFIX + " " + jwt;
    }
  8.  
  9. public static Map<String, String> validateToken(String token) {
    HashMap<String, String> tokenMap = new HashMap<String, String>();
    if (StringUtils.isEmpty(token)) {
    return tokenMap;
    }
    try {
    Map<String, Object> tokenBody = Jwts.parser()
    .setSigningKey(SECRET)
    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
    .getBody();
    String userId = String.valueOf(tokenBody.get(HEADER_USERID));
    tokenMap.put(HEADER_USERID, userId);
    }catch (ExpiredJwtException e){
    e.printStackTrace();
    }
    return tokenMap;
    }
  10.  
  11. /**
    * 移到jwtUtil中去
    *
    * @param token
    * @return
    */
    public static Map<String, String> validateTokenAndUser(String token, String userIdIn) {
    Map<String, String> tokenResultMap = new HashMap<>();
    if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userIdIn)) {
    return tokenResultMap;
    }
    tokenResultMap = validateToken(token);
    if (StringUtils.isEmpty(token) || StringUtils.isEmpty(userIdIn)) {
    return tokenResultMap;
    }
    //判断传入的userid和token是否匹配
    String userIdOri = tokenResultMap.get(HEADER_USERID);
    if (!userIdIn.equals(userIdOri)) {
    return new HashMap<String,String>();
    }
    return tokenResultMap;
    }
  12.  
  13. }
  1.  
  1.  

3- 编写过滤器类

  1. package spring.cloud.gateway.filter;
  2.  
  3. import java.net.URI;
  4. import java.util.Map;
  5. import org.apache.commons.lang.StringUtils;
  6. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
  7. import org.springframework.cloud.gateway.filter.GlobalFilter;
  8. import org.springframework.cloud.gateway.route.Route;
  9. import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
  10. import org.springframework.http.HttpHeaders;
  11. import org.springframework.http.HttpMethod;
  12. import org.springframework.http.server.PathContainer;
  13. import org.springframework.http.server.reactive.ServerHttpRequest;
  14. import org.springframework.stereotype.Component;
  15. import org.springframework.web.server.ServerWebExchange;
  16. import reactor.core.publisher.Mono;
  17. import spring.cloud.gateway.common.JwtUtil;
  18. import spring.cloud.gateway.exception.PermissionException;
  19.  
  20. /**
  21. * 参数参考 https://blog.csdn.net/tianyaleixiaowu/article/details/83375246
  22. * response参考 https://bbs.csdn.net/topics/392412604?list=11074255
  23. */
  24. @Component
  25. public class AuthFilter implements GlobalFilter {
  26.  
  27. @Override
  28. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  29. ServerHttpRequest request = exchange.getRequest();
  30. HttpHeaders header = request.getHeaders();
  31. HttpMethod method = request.getMethod();
  32. String token = header.getFirst(JwtUtil.HEADER_AUTH);
  33. String userId = header.getFirst(JwtUtil.HEADER_USERID);
  34. PathContainer pathContainer = request.getPath().pathWithinApplication();
  35. String path = pathContainer.value();
  36.  
  37. //2- 处理登录请求
  38. if (StringUtils.isBlank(token)) {
  39. //是登录接口则放行,否则返回异常
  40. if (path.contains(JwtUtil.LOGIN_URL) && HttpMethod.POST.equals(method)) {
  41. throw new PermissionException("please login");
  42. }
  43. return chain.filter(exchange);
  44. }
  45.  
  46. //3- 处理刷新token请求
  47. if (path.indexOf("refresh") >= 0) {
  48. //放行去掉刷新接口(在刷新前校验userId和token是否匹配)
  49. return chain.filter(exchange);
  50. }
  51.  
  52. //4- 处理刷新token请求
  53. if (path.contains(JwtUtil.LOGOUT_URL) && HttpMethod.DELETE.equals(method)) {
  54. //放行去掉登出接口(在刷新前校验userId和token是否匹配)
  55. return chain.filter(exchange);
  56. }
  57.  
  58. //5- 携带token请求其他业务接口
  59. Map<String, String> validateResultMap = JwtUtil.validateTokenAndUser(token, userId);
  60. if (validateResultMap == null || validateResultMap.isEmpty()) {
  61. throw new PermissionException("token 已经失效");
  62. }
  63. // TODO 将用户信息存放在请求header中传递给下游业务
  64. Route gatewayUrl = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
  65. URI uri = gatewayUrl.getUri();
  66. //表示下游请求对应的服务名如 SPRING-CLOUD-SERVICE SPRING-CLOUD-GATEWAY
  67. String serviceName = uri.getHost();
  68.  
  69. ServerHttpRequest.Builder mutate = request.mutate();
  70. mutate.header("x-user-id", validateResultMap.get("userid"));
  71. mutate.header("x-user-name", validateResultMap.get("user"));
  72. mutate.header("x-user-serviceName", serviceName);
  73. ServerHttpRequest buildReuqest = mutate.build();
  74.  
  75. //todo 如果响应中需要放数据,也可以放在response的header中
  76. //ServerHttpResponse response = exchange.getResponse();
  77. //response.getHeaders().add("new_token","token_value");
  78. return chain.filter(exchange.mutate().request(buildReuqest).build());
  79. }
  80.  
  81. }

4- 编写相关接口API

  1. package spring.cloud.gateway.controller;
  2.  
  3. import org.springframework.web.bind.annotation.*;
  4. import spring.cloud.gateway.common.JwtUtil;
  5.  
  6. import java.util.Map;
  7.  
  8. @RestController
  9. @RequestMapping("/token")
  10. public class TokenController {
  11.  
  12. /**
  13. * 登录接口
  14. * @param user(userID +pwd)
  15. * @return
  16. */
  17. @PostMapping("/userId/pwd")
  18. public String getToken(@RequestBody Map<String,String> user) {
  19. //用户名密码需要加密处理
  20. String result = "";
  21. if (user == null || user.isEmpty()) {
  22. return result;
  23. }
  24. String userId = user.get("userId");
  25. String pwd = user.get("pwd");
  26. if (!doLogin(userId,pwd)) {
  27. return result;
  28. }
  29. String token = JwtUtil.generateToken(userId);
  30. // todo 将token放入redis中,设置超时时间为 2 * t
  31. return token;
  32. }
  33.  
  34. private Boolean doLogin(String userId,String pwd) {
  35. //后续对接user表验证
  36. if ("admin".equals(userId) && "123".equals(pwd)) {
  37. return true;
  38. }
  39. if ("spring".equals(userId) && "123".equals(pwd)) {
  40. return true;
  41. }
  42. if ("gateway".equals(userId) && "123".equals(pwd)) {
  43. return true;
  44. }
  45. return false;
  46. }
  47.  
  48. /**
  49. * 登出接口
  50. */
  51.  
  52. /**
  53. * 刷新token的接口
  54. * 在刷新前校验userId和token是否匹配
  55. */
  56.  
  57. }

gateway + jwt 网关认证的更多相关文章

  1. Spring Cloud Gateway + Jwt + Oauth2 实现网关的鉴权操作

    Spring Cloud Gateway + Jwt + Oauth2 实现网关的鉴权操作 一.背景 二.需求 三.前置条件 四.项目结构 五.网关层代码的编写 1.引入jar包 2.自定义授权管理器 ...

  2. Spring Cloud Gateway 服务网关快速上手

    Spring Cloud Gateway 服务网关 API 主流网关有NGINX.ZUUL.Spring Cloud Gateway.Linkerd等:Spring Cloud Gateway构建于 ...

  3. ASP.NET Core 基于JWT的认证(二)

    ASP.NET Core 基于JWT的认证(二) 上一节我们对 Jwt 的一些基础知识进行了一个简单的介绍,这一节我们将详细的讲解,本次我们将详细的介绍一下 Jwt在 .Net Core 上的实际运用 ...

  4. ASP.NET Core 基于JWT的认证(一)

    ASP.NET Core 基于JWT的认证(一) Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计 ...

  5. SpringCloud初体验:四、API GateWay 服务网关

    网关服务很多,比如:Zuul.Kong.spring cloud gateway ……, 这里不纠结哪种性能好,本次体验是用的 spring cloud gateway 更多网关比较可以了解这篇文章: ...

  6. spring cloud 2.x版本 Gateway路由网关教程

    前言 本文采用Spring cloud本文为2.1.8RELEASE,version=Greenwich.SR3 本文基于前两篇文章eureka-server.eureka-client.eureka ...

  7. ASP.NET Core系列:JWT身份认证

    1. JWT概述 JSON Web Token(JWT)是目前流行的跨域身份验证解决方案. JWT的官网地址:https://jwt.io JWT的实现方式是将用户信息存储在客户端,服务端不进行保存. ...

  8. 【技术博客】JWT的认证机制Django项目中应用

    开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. JWT的认证机制Django项目中应用 这篇技术博客基于软 ...

  9. JWT 身份认证优缺点分析以及常见问题解决方案

    本文转载自:JWT 身份认证优缺点分析以及常见问题解决方案 Token 认证的优势 相比于 Session 认证的方式来说,使用 token 进行身份认证主要有下面三个优势: 1.无状态 token ...

随机推荐

  1. flask wigs 服务器

    Nginx:Hey,WSGI,我刚收到了一个请求,我需要你作些准备,然后由Flask来处理这个请求. WSGI:OK,Nginx.我会设置好环境变量,然后将这个请求传递给Flask处理. Flask: ...

  2. IntelJ idea下lombok 不生效的问题(@Builder等注解不生效的问题)解决,lombok Plugin插件安装

    插件安装方式,在设置setting 中找到plugins.在检索框中检索lom,没有的话点击红框内的search in repositories. 点击install进行安装. 记得安装好了重启ide ...

  3. java中获取两个时间中的每一天

    引入下面方法即可: /** * 获取两个时间中的每一天 * @param bigtimeStr 开始时间 yyyy-MM-dd * @param endTimeStr 结束时间 yyyy-MM-dd ...

  4. eclipse 查看变量或方法在什么地方被调用的快捷键和快速显示方法入参提示信息

    为了用eclipse写代码的时候,不用方向键移动光标,可以设置如下快捷键, Line Up:Alt+i   光标向上 Line Down:Alt+k 光标向下 Line Start:Alt+u  移到 ...

  5. mysql可以远程连接的配置

    由于配置好几次了,老是会忘记命令,所以记录下来 1.修改配置文件 我的配置文件是/etc/mysql/mysql.conf.d/mysqld.cnf 找到 bind-address = 127.0.0 ...

  6. Dubbo,Zookeeper入门

    Zookeeper 功能:分布式应用程序协调服务,集群管理者,监视集群各个节点状态-->提交反馈-->进行下一步合理操作: 机制:目录方式,当目录节点发生变化(数据改变,被删除,子节点增加 ...

  7. SQUAD的rnet复现踩坑记

    在港科大rnet(https://github.com/HKUST-KnowComp/R-Net) 实现的基础上做了复现 采用melt框架训练,原因是港科大实现在工程上不是很完美,包括固定了batch ...

  8. php 实现双向链表

    /** * 链表元素结点类 */ class Node { public $pre = NULL; // 前驱 public $next = NULL; // 后继 public $data = NU ...

  9. 如何看待淘宝二手交易APP“闲鱼”推出的新功能“闲鱼小法庭”?

    转:https://www.zhihu.com/question/55487716?utm_source=qq&utm_medium=social

  10. nodejs electron 创建桌面应用

    //首先安装cnpm npm install -g cnpm --registry=https://registry.npm.taobao.org //使用cnpm进行安装,使用方法和npm相同 cn ...