gateway和jwt网关认证实现过程解析

这篇文章主要介绍了gateway和jwt网关认证实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

思路: 全局过滤器对所有的请求拦截(生成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是否匹配
   */
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Spring Boot实战之Filter实现使用JWT进行接口认证

    本文介绍了spring Boot实战之Filter实现使用JWT进行接口认证,分享给大家 jwt(json web token) 用户发送按照约定,向服务端发送 Header.Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api jwt使用流程 本文示例接上面几篇文章中的代码进行编写,请阅读本文的同时可以参考前面几篇文章 1.添加依赖库jjwt,本文中构造jwt及解析jwt都使用了jjwt库

  • 在Angular中使用JWT认证方法示例

    本文介绍了在Angular中使用JWT认证方法示例,分享给大家,具体如下: 项目地址: grading-system 基于session的认证和基于token的认证的方式已经被广泛使用.在session认证中,服务端会存储一份用户登录信息,这份登录信息会在响应时传递给浏览器并保存为Cookie,在下次请求时,会带上这份登录信息,这样就能识别请求来自哪个用户. 在基于session的认证中,每个用户都要生成一份session,这份session通常保存在内存中,随着用户量的增加,服务端的开销会增大

  • 详解用JWT对SpringCloud进行认证和鉴权

    JWT(JSON WEB TOKEN)是基于RFC 7519标准定义的一种可以安全传输的小巧和自包含的JSON对象.由于数据是使用数字签名的,所以是可信任的和安全的.JWT可以使用HMAC算法对secret进行加密或者使用RSA的公钥私钥对来进行签名. JWT通常由头部(Header),负载(Payload),签名(Signature)三个部分组成,中间以.号分隔,其格式为Header.Payload.Signature Header:声明令牌的类型和使用的算法 alg:签名的算法 typ:to

  • Asp.Net Core基于JWT认证的数据接口网关实例代码

    前言 近日,应一位朋友的邀请写了个Asp.Net Core基于JWT认证的数据接口网关Demo.朋友自己开了个公司,接到的一个升级项目,客户要求用Aps.Net Core做数据网关服务且基于JWT认证实现对前后端分离的数据服务支持,于是想到我一直做.Net开发,问我是否对.Net Core有所了解?能不能做个简单Demo出来看看?我说,分道扬镳之后我不是调用别人的接口就是提供接口给别人调用,于是便有了以下示例代码. 示例要求能演示获取Token及如何使用该Token访问数据资源,在Demo中实现

  • 详解SpringCloud服务认证(JWT)

     - JWT JWT(JSON Web Token), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景.JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密. - JWT与其它的区别 通常情况下,把API直接暴露出去是风险很大的,不说别的

  • Django JWT Token RestfulAPI用户认证详解

    一般情况下我们Django默认的用户系统是满足不了我们的需求的,那么我们会对他做一定的扩展 创建用户项目 python manage.py startapp users 添加项目apps settings.py INSTALLED_APPS = [ ... 'users.apps.UsersConfig', ] 添加AUTH_USRE_MODEL 替换默认的user AUTH_USER_MODEL = 'users.UserProfile' 如果说想用全局认证需要在配置文件中添加 # 全局认证f

  • php 后端实现JWT认证方法示例

    JWT是什么 JWT是json web token缩写.它将用户信息加密到token里,服务器不保存任何用户信息.服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证.基于token的身份验证可以替代传统的cookie+session身份验证方法. 它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法.JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名.它具备两个特点: 简洁(Compact):可以通过URL, POST 参数或

  • gateway和jwt网关认证实现过程解析

    这篇文章主要介绍了gateway和jwt网关认证实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 思路: 全局过滤器对所有的请求拦截(生成token有效期30分钟,放入redis设置有效期3天.3天之类可以通过刷新接口自动刷新,超过3天需要重新登录.) 前端在调用接口之前先判断token是否过期(3o分钟),过期则先调刷新接口,换取新token, 1引入相关jar <dependency> <groupId>org.sp

  • Python 基于jwt实现认证机制流程解析

    1.jwt的优缺点 jwt的优点: 1. 实现分布式的单点登陆非常方便 2. 数据实际保存在客户端,所以我们可以分担数据库或服务器的存储压力 jwt的缺点: 1. 数据保存在了客户端,我们服务端只认jwt,不识别客户端. 2. jwt可以设置过期时间,但是因为数据保存在了客户端,所以对于过期时间不好调整. 2.安装jwt pip install djangorestframework-jwt -i https://pypi.douban.com/simple 3.在settings.dev中 R

  • SpringCLoud搭建Zuul网关集群过程解析

    1.使用技术 Springboot,SpringCloud,Zuul,Nignx 2.目的 使用Zuul搭建微服务高可用的网关 3.项目创建 3.1 创建注册中心(略) 3.2 创建一个hello-service的服务工程 3.3 创建springcloud-zuul-ha网关服务 3.3.1 创建工程(略) 3.3.2 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&q

  • 基于springboot+jwt实现刷新token过程解析

    前一段时间讲过了springboot+jwt的整合,但是因为一些原因(个人比较懒)并没有更新关于token的刷新问题,今天跟别人闲聊,聊到了关于业务中token的刷新方式,所以在这里我把我知道的一些点记录一下,也希望能帮到一些有需要的朋友,同时也希望给我一些建议,话不多说,上代码! 1:这种方式为在线刷新,比方说设定的token有效期为30min,那么每次访问资源时,都会在拦截器中去判断一下token是否过期,如果没有过期就刷新token的时间为30min,反之则会重新登录,需要注意的是这种方式

  • 基于springboot实现整合shiro实现登录认证以及授权过程解析

    这篇文章主要介绍了基于springboot实现整合shiro实现登录认证以及授权过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.添加shiro的依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web- starter</artifactId> <version&g

  • Spring Cloud基于zuul实现网关过程解析

    这篇文章主要介绍了Spring Cloud基于zuul实现网关过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 利用zuul网关统一向外暴露接口 1.新建项目 spring-zuul 2.引入pom <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuu

  • ASP.NET Core框架探索之Authentication的权限认证过程解析

    今天我们来探索一下ASP.NET Core中关于权限认证,所谓权限认证,就是通过某些方式获取到用户的信息. 需要开启权限认证,我们首先需要在容器中注入认证服务,使用services.AddAuthentication.进入该方法的源码,最重要的其实就是AddAuthenticationCore方法,他向容器中注入了认证体系中很重要的对象:IAuthenticationService.IAuthenticationHandlerProvider.IAuthenticationSchemeProvi

  • JWT登录认证实战模拟过程全纪录

    目录 Token 认证流程 Token 认证优点 JWT 结构 JWT 基本使用 实战:使用 JWT 登录认证 附:为什么使用jwt而不使用session 总结 Token 认证流程 作为目前最流行的跨域认证解决方案,JWT(JSON Web Token) 深受开发者的喜爱,主要流程如下: 客户端发送账号和密码请求登录 服务端收到请求,验证账号密码是否通过 验证成功后,服务端会生成唯一的 token,并将其返回给客户端 客户端接受到 token,将其存储在 cookie 或者 localStro

  • Node.js的Koa实现JWT用户认证方法

    本文介绍了Node.js的Koa实现JWT用户认证方法,分享给大家,具体如下: 一.前置知识 基于Token的身份验证 Koajs 中文文档 Koa 框架教程 二.环境 Microsoft Visual Studio 2017集成开发环境 Node.js v8.9.4Javascript运行环境 三.开始动手,一步步来完善 1.创建基础的静态资源服务器.基础架构 以下是基本的代码,实现静态服务器,以及一个当token验证异常时候的处理. 下面我们将在这个基本代码下逐步增加注册.登录.信息的功能.

  • Spring boot2X负载均衡和反向代理实现过程解析

    这篇文章主要介绍了Spring boot2X负载均衡和反向代理实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 zuul 是netflix开源的一个API Gateway 服务器 所有从设备或网站来的请求都会经过Zuul到达后端的Netflix应用程序. 作为一个边界性质的应用程序,Zuul提供了动态路由.监控.弹性负载和安全功能. 实现反向代理 1.服务注册发现中心Consul 启动 consul agent -dev 2.服务端

随机推荐