Jwt和Token

简介: Jwt和Token的认识

1、什么是 JWT?


JSON Web Token,通过数字签名的方式,以 JSON 对象为载体,在不同的服务终端之间安全的传输信息。




2、JWT 有什么用?


JWT 最常见的场景就是授权认证,一旦用户登录,后续每个请求都将包含JWT,系统在每次处理用户请求的之前,都要先进行 JWT 安全校验,通过之后再进行处理。




3、JWT 的组成


JWT 由 3 部分组成,用.拼接



eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXRlc3QiLCJleHAiOjE2MjMyMjM2NzUsImp0aSI6ImQ2MTJjZjcxLWI5ZmUtNGMwNy04MzQwLTViOWViZmMyNjExNyJ9.FOS9Y7rYNdc2AOidnSPrgg2XTYePU0yGZ598h2gtabE



这三部分分别是:


  • Header


{
'typ': 'JWT',
'alg': 'HS256'  }


  • Payload



{
"sub": '1234567890',
"name": 'xmp',
"admin":true  }



  • Signature




varencodedString=base64UrlEncode(header) +'.'+base64UrlEncode(payload);
varsignature=HMACSHA256(encodedString, 'secret');

4、优缺点

优点


  • 简洁: 可以通过URL、POST参数或者在HTTP header发送,因为数据量小,传输速度也很快;
  • 自包含:负载中可以包含用户所需要的信息,避免了多次查询数据库;
  • 因为Token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持;
  • 不需要在服务端保存会话信息,特别适用于分布式微服务。

缺点

  • 无法作废已颁布的令牌;
  • 不易应对数据过期。


5、测试

pom.xml    jwt依赖坐标


<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.13.0</version></dependency>


token登录,浏览器f12可以观察到token信息

image.png


6、SpringBoot集成JWT实现token验证

1、pom.xml

jwt坐标

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.13.0</version><!--版本号可以根据自己的--></dependency>

工具类坐标

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.20</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>4.1.2</version></dependency>

2、代码


生成token


packagecom.example.boot.utils;
importcn.hutool.core.date.DateUtil;
importcn.hutool.core.util.StrUtil;
importcom.auth0.jwt.JWT;
importcom.auth0.jwt.algorithms.Algorithm;
importcom.example.boot.entity.User;
importcom.example.boot.service.IUserService;
importorg.springframework.stereotype.Component;
importorg.springframework.web.context.request.RequestContextHolder;
importorg.springframework.web.context.request.ServletRequestAttributes;
importjavax.annotation.PostConstruct;
importjavax.annotation.Resource;
importjavax.servlet.http.HttpServletRequest;
importjava.util.Date;
@ComponentpublicclassTokenUtils {
privatestaticIUserServicestaticUserService;
@ResourceprivateIUserServiceuserService;
@PostConstructpublicvoidsetUserService() {
staticUserService=userService;
    }
/*** 生成token* author: xmp* date: 2022/5/12* @return*/publicstaticStringgenToken(StringuserId, Stringsign) {
returnJWT.create().withAudience(userId)                                            // 将 user id 保存到 token 里面,作为载荷                .withExpiresAt(DateUtil.offsetHour(newDate(), 2))                    // 2小时后token过期 ===>当前日期加2小时                .sign(Algorithm.HMAC256(sign));                                             // 以 password 作为 token 的密钥    }
/*** 获取当前登录的用户信息** @return user对象*/publicstaticUsergetCurrentUser() {
try {
HttpServletRequestrequest= ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Stringtoken=request.getHeader("token");
if (StrUtil.isNotBlank(token)) {
StringuserId=JWT.decode(token).getAudience().get(0);
returnstaticUserService.getById(Integer.valueOf(userId));
            }
        } catch (Exceptione) {
returnnull;
        }
returnnull;
    }
}

jwt

packagecom.example.boot.config.interceptor;
importcn.hutool.core.util.StrUtil;
importcom.auth0.jwt.JWT;
importcom.auth0.jwt.JWTVerifier;
importcom.auth0.jwt.algorithms.Algorithm;
importcom.auth0.jwt.exceptions.JWTDecodeException;
importcom.auth0.jwt.exceptions.JWTVerificationException;
importcom.example.boot.common.Constants;
importcom.example.boot.entity.User;
importcom.example.boot.exception.ServiceException;
importcom.example.boot.service.IUserService;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.method.HandlerMethod;
importorg.springframework.web.servlet.HandlerInterceptor;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
publicclassJwtInterceptorimplementsHandlerInterceptor {
@AutowiredprivateIUserServiceuserService;
@OverridepublicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler) {
Stringtoken=request.getHeader("token");
// 如果不是映射到方法直接通过if(!(handlerinstanceofHandlerMethod)){
returntrue;
        }
// 执行认证if (StrUtil.isBlank(token)) {
thrownewServiceException(Constants.CODE_401, "无token,请重新登录");
        }
// 获取 token 中的 user idStringuserId;
try {
userId=JWT.decode(token).getAudience().get(0);
        } catch (JWTDecodeExceptionj) {
thrownewServiceException(Constants.CODE_401, "token验证失败,请重新登录");
        }
// 根据token中的userid查询数据库Useruser=userService.getById(userId);
if (user==null) {
thrownewServiceException(Constants.CODE_401, "用户不存在,请重新登录");
        }
// 用户密码加签验证 tokenJWTVerifierjwtVerifier=JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token); // 验证token        } catch (JWTVerificationExceptione) {
thrownewServiceException(Constants.CODE_401, "token验证失败,请重新登录");
        }
returntrue;
    }
}

拦截,通过判断token是否合法来决定是否需要登录

packagecom.example.boot.config;
importcom.example.boot.config.interceptor.JwtInterceptor;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.web.servlet.config.annotation.InterceptorRegistry;
importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ConfigurationpublicclassInterceptorConfigimplementsWebMvcConfigurer {
@OverridepublicvoidaddInterceptors(InterceptorRegistryregistry) {
registry.addInterceptor(jwtInterceptor())
                .addPathPatterns("/**")                                             // 拦截所有请求,通过判断token是否合法来决定是否需要登录                .excludePathPatterns("/user/login", "/user/register", "/**/export", "/**/import");
    }
@BeanpublicJwtInterceptorjwtInterceptor() {
returnnewJwtInterceptor();
    }
}

service层,接口实现类的登录逻辑

@OverridepublicUserDtologin(UserDtouserDTO) {
Userone=getUserInfo(userDTO);
if (one!=null) {
BeanUtil.copyProperties(one, userDTO, true);
//设置tokenStringtoken=TokenUtils.genToken(one.getId().toString(), one.getPassword());
userDTO.setToken(token);
returnuserDTO;
    } else {
thrownewServiceException(Constants.CODE_600, "用户名或密码错误");
    }
}
相关文章
|
3月前
|
存储 NoSQL 前端开发
jwt与redis,把生成的token放入redis中进行临时存储
jwt与redis,把生成的token放入redis中进行临时存储
67 0
|
6月前
|
存储 JSON 安全
解锁互联网安全的新钥匙:JWT(JSON Web Token)
解锁互联网安全的新钥匙:JWT(JSON Web Token)
77 0
|
6月前
|
存储 算法 NoSQL
还分不清 Cookie、Session、Token、JWT?看这一篇就够了
Cookie、Session、Token 和 JWT(JSON Web Token)都是用于在网络应用中进行身份验证和状态管理的机制。虽然它们有一些相似之处,但在实际应用中有着不同的作用和特点,接下来就让我们一起看看吧,本文转载至http://juejin.im/post/5e055d9ef265da33997a42cc
|
6月前
|
JSON 算法 Go
Golang语言使用 jwt-go 库生成和解析 token
Golang语言使用 jwt-go 库生成和解析 token
177 0
|
5月前
|
存储 安全 测试技术
快速教你如何使用postman工具进行接口测试?(配置全局token、JWT可用)
快速教你如何使用postman工具进行接口测试?(配置全局token、JWT可用)
141 0
|
3月前
|
SQL Java 数据库连接
Spring-Security & JWT 实现 token
Spring-Security & JWT 实现 token
34 0
|
3月前
|
JSON 安全 算法
JSON Web Token(缩写 JWT) 目前最流行、最常见的跨域认证解决方案
JSON Web Token(缩写 JWT) 目前最流行、最常见的跨域认证解决方案
129 0
|
8月前
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
139 0
|
4月前
|
存储 JSON 中间件
JWT json web token
JWT json web token
39 0
|
4月前
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
通过jwt基于token实现登陆认证通过jwt基于token实现登陆认证
20 0