2023年11月29日发(作者:)

基于SpringBoot使⽤JWT实现Token认证

⽬录

⼀、JWT的介绍

1、什么是JWT

Json web token(JWT)是为了⽹络应⽤环境间传递声明⽽执⾏的⼀种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且

安全的,特别适⽤于分布式站点的单点登陆(SSO)场景。JWT的声明⼀般被⽤来在⾝份提供者和服务提供者间传递被认证的⽤户⾝份信

息,以便于从资源服务器获取资源,也可以增加⼀些额外的其它业务逻辑所必须的声明信息,该token也可直接被⽤于认证,也可被加密。

2、、基于token的鉴权机制

基于token的鉴权机制类似于http协议也是⽆状态的,它不需要在服务端去保留⽤户的认证信息或会话信息。这也就意味着机遇tokent认证

机制的应⽤不需要去考虑⽤户在哪⼀台服务器登陆了,这就为应⽤的扩展提供了便利

流程是这样的

⽤户使⽤⽤户名密码请求服务器

服务器进⾏验证⽤户信息

服务器通过验证发送给⽤户⼀个token

客户端存储token,并在每次请求时附加这个token值

服务器验证token,并返回数据

这个token必须要在每次请求时发送给服务器,它应该保存在请求头中,另外,服务器要⽀持CORS(跨来源资源共享)策略,⼀般我

们在服务端这么做就可以了 Access-Control-Allow-Origin:*

JWT的头部承载的两部分信息:

声明类型,这⾥是jwt

声明加密的算法,通常直接使⽤HMAC SHA256

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

Signature

jwt的第三部分是⼀个签证信息,这个签证信息由三部分组成:

header(base64后的)

payload(base64后的)

secred

这个部分需要base64加密后的header和base64加密后的payload使⽤“.”连接组成的字符串,然后通过header中声明的加密⽅式

进⾏加secret组合加密,然后就构成了jwt的第三部分

var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);

var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

将这三部分⽤“.”连接成⼀个完整的字符串,构成了最终的jwt:

95OrM7E2cBab30RMH

btoken

jjwt

0.9.0

2、⾃定义登录异常处理

UserLoginException

*

* @return property value of errorContext

*/

public ErrorContext getErrorContext() {

return errorContext;

}

/**

* Setter method for property errorContext.

// 过期时间是3600秒,既是1个⼩时

public static final long EXPIRATION = 3600L;

// 选择了记住我之后的过期时间为7

public static final long EXPIRATION_REMEMBER = 604800L;

/**

* 创建token

* 注:如果是根据可变的唯⼀值来⽣成,唯⼀值变化时,需重新⽣成token

* @param username

* @param isRememberMe

* @return

*/

public static String createToken(String id, String username, boolean isRememberMe) {

long expiration = isRememberMe ? EXPIRATION_REMEMBER : EXPIRATION;

//可以将基本不重要的对象信息放到claims中,此处信息不多,见简单直接放到配置内

// HashMap claims = new HashMap();

// ("id", id);

// ("username",username);

//id是重要信息,进⾏加密下

String encryId = _string(id);

return r()

.signWith(512, SECRET)

// 这⾥要早set⼀点,放到后⾯会覆盖别的字段

// .setClaims(claims)

.setIssuer(ISS)

.setId(encryId)

.setSubject(username)

.setIssuedAt(new Date())

.setExpiration(new Date(tTimeMillis() + expiration * 1000))

* 获取token信息,同时也做校验处理

* @param token

* @throws ⾃定义UserLoginException异常处理

* @return

*/

public static Claims getTokenBody(String token){

try{

return ()

.setSigningKey(SECRET)

.parseClaimsJws(token)

.getBody();

}catch(ExpiredJwtException expired){

//过期

throw new UserLoginException(_EXPIRED);

}catch (SignatureException e){

//⽆效

throw new UserLoginException(D_REQUEST);

}catch(MalformedJwtException malformedJwt){

@RestController

@RequestMapping(value = "/admin/adminUser")

public class AdminUserController extends BaseController{

@Autowired

先配置我们的拦截器 JwtInterceptor

/**

* token验证拦截

*/

public class JwtInterceptor implements HandlerInterceptor {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

@Configuration

public class WebConfig implements WebMvcConfigurer {

/**

* 添加拦截器

*/

@Override

public void addInterceptors(InterceptorRegistry registry) {

//拦截路径可⾃⾏配置多个 可⽤ ,分隔开

erceptor(new JwtInterceptor()).addPathPatterns("/admin/adminUser/adminLoginO**");

}

/**

* 跨域⽀持

*

* @param registry

*/

@Override

public void addCorsMappings(CorsRegistry registry) {

ping("/**")

.allowedOrigins("*")

.allowCredentials(true)

.allowedMethods("GET", "POST", "DELETE", "PUT")

.maxAge(3600 * 24);

}

/**

* 配置消息转换器--这⾥⽤的是alibaba 开源的 fastjson

*

* @param converters

*/

@Override

public void configureMessageConverters(List> converters) {

//1.需要定义⼀个convert转换消息的对象;

FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();

再来访问下带之前登录⽣成的token:url同上

到此可⽤看到使⽤JWT进⾏token成功。