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

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

1- 引入相关jar

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>

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


package spring.cloud.gateway.common;

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; 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; 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;
} 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;
} /**
* 移到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;
} }


3- 编写过滤器类

package spring.cloud.gateway.filter;

import java.net.URI;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.PathContainer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import spring.cloud.gateway.common.JwtUtil;
import spring.cloud.gateway.exception.PermissionException; /**
* 参数参考 https://blog.csdn.net/tianyaleixiaowu/article/details/83375246
* response参考 https://bbs.csdn.net/topics/392412604?list=11074255
*/
@Component
public class AuthFilter implements GlobalFilter { @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
HttpHeaders header = request.getHeaders();
HttpMethod method = request.getMethod();
String token = header.getFirst(JwtUtil.HEADER_AUTH);
String userId = header.getFirst(JwtUtil.HEADER_USERID);
PathContainer pathContainer = request.getPath().pathWithinApplication();
String path = pathContainer.value(); //2- 处理登录请求
if (StringUtils.isBlank(token)) {
//是登录接口则放行,否则返回异常
if (path.contains(JwtUtil.LOGIN_URL) && HttpMethod.POST.equals(method)) {
throw new PermissionException("please login");
}
return chain.filter(exchange);
} //3- 处理刷新token请求
if (path.indexOf("refresh") >= 0) {
//放行去掉刷新接口(在刷新前校验userId和token是否匹配)
return chain.filter(exchange);
} //4- 处理刷新token请求
if (path.contains(JwtUtil.LOGOUT_URL) && HttpMethod.DELETE.equals(method)) {
//放行去掉登出接口(在刷新前校验userId和token是否匹配)
return chain.filter(exchange);
} //5- 携带token请求其他业务接口
Map<String, String> validateResultMap = JwtUtil.validateTokenAndUser(token, userId);
if (validateResultMap == null || validateResultMap.isEmpty()) {
throw new PermissionException("token 已经失效");
}
// TODO 将用户信息存放在请求header中传递给下游业务
Route gatewayUrl = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
URI uri = gatewayUrl.getUri();
//表示下游请求对应的服务名如 SPRING-CLOUD-SERVICE SPRING-CLOUD-GATEWAY
String serviceName = uri.getHost(); ServerHttpRequest.Builder mutate = request.mutate();
mutate.header("x-user-id", validateResultMap.get("userid"));
mutate.header("x-user-name", validateResultMap.get("user"));
mutate.header("x-user-serviceName", serviceName);
ServerHttpRequest buildReuqest = mutate.build(); //todo 如果响应中需要放数据,也可以放在response的header中
//ServerHttpResponse response = exchange.getResponse();
//response.getHeaders().add("new_token","token_value");
return chain.filter(exchange.mutate().request(buildReuqest).build());
} }

4- 编写相关接口API

package spring.cloud.gateway.controller;

import org.springframework.web.bind.annotation.*;
import spring.cloud.gateway.common.JwtUtil; import java.util.Map; @RestController
@RequestMapping("/token")
public class TokenController { /**
* 登录接口
* @param user(userID +pwd)
* @return
*/
@PostMapping("/userId/pwd")
public String getToken(@RequestBody Map<String,String> user) {
//用户名密码需要加密处理
String result = "";
if (user == null || user.isEmpty()) {
return result;
}
String userId = user.get("userId");
String pwd = user.get("pwd");
if (!doLogin(userId,pwd)) {
return result;
}
String token = JwtUtil.generateToken(userId);
// todo 将token放入redis中,设置超时时间为 2 * t
return token;
} private Boolean doLogin(String userId,String pwd) {
//后续对接user表验证
if ("admin".equals(userId) && "123".equals(pwd)) {
return true;
}
if ("spring".equals(userId) && "123".equals(pwd)) {
return true;
}
if ("gateway".equals(userId) && "123".equals(pwd)) {
return true;
}
return false;
} /**
* 登出接口
*/ /**
* 刷新token的接口
* 在刷新前校验userId和token是否匹配
*/ }

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. win10下安装基于caffe的 Faster-Rcnn

    安装教程   本篇博客将会教会你在Windows下配置py-faster-rcnn,请细心仔细阅读.说白了,Windows下配置这些东西就是一个坑. 安装配置Anaconda   由于py-faste ...

  2. Vue .Net 前后端分离框架搭建

    [参考]IntellIJ IDEA 配置 Vue 支持 打开Vue项目 一.前端开发环境搭建 1.零基础 Vue 开发环境搭建 打开运行Vue项目 2.nodejs http-proxy-middle ...

  3. C#项目”XXXXX”针对的是”.NETFramework,Version=v4.7.1”但此计算机没有安装它

    遇到这样一个问题:C#项目”XXXXX”针对的是”.NETFramework,Version=v4.7.1”但此计算机没有安装它 就是我在打开别人的项目,发现别人的项目.Net Framework的版 ...

  4. java生成txt文件,读txt文件

    1.方法1 public static void main(String[] args) { try { FileWriter fileWriter = new FileWriter("c: ...

  5. IntelliJ IDEA License Server 安装使用 Mac篇

    一.下载 IntelliJ IDEA 是Java开发利器,用社区版不爽,干催就用旗舰版,这个是收费的,需要licence.  IntelliJ IDEA下载地址:https://www.jetbrai ...

  6. 机器人学 —— 机器人感知(Location)

    终于完成了Robotic SLAM 所有的内容了.说实话,课程的内容比较一般,但是作业还是挺有挑战性的.最后一章的内容是 Location. Location 是 Mapping 的逆过程.在给定ma ...

  7. Elasticsearch学习之有用博客

    推荐阅读:1.阿里:https://elasticsearch.cn/article/61712.滴滴:http://t.cn/EUNLkNU3.腾讯:http://t.cn/E4y9ylL4.携程: ...

  8. cs231n笔记(二) 最优化方法

    回顾上一节中,介绍了图像分类任务中的两个要点: 假设函数.该函数将原始图像像素映射为分类评分值. 损失函数.该函数根据分类评分和训练集图像数据实际分类的一致性,衡量某个具体参数集的质量好坏. 现在介绍 ...

  9. B - Assignment

    Tom owns a company and he is the boss. There are n staffs which are numbered from 1 to n in this com ...

  10. Galera Cluster mysql+keepalived集群部署

    1.卸载mysql 查找本机安装的mysqlrpm -qa | grep -i mysql --nodeps --force rpm -ev MySQL-server-5.6.15-1.el6.x86 ...