Java | 分布式——JWT加密
一、分布式Session共享
Session是服务器用来保存用户操作的一系列会话信息,由Web容器进行管理。单机情况下,不存在Session共享的情况,分布式情况下,如果不进行Session共享会出现请求落到不同机器要重复登录的情况:在一些需要用户登录的网站下,如果因为用提交的请求给到了不同的服务器进行处理,而需要让用户重复登录,这是一件非常扯蛋的操作。所以必须让所有服务器都能准确判断请求属于哪个用户。
一般来说解决Session共享有以下几种方案:
-
Tomcat广播风暴(占用资源,不推荐)
-
redis统一存储token(推荐)
-
JWT加密
二、JWT简介
本文主要介绍JWT加密的方法,JWT(Json web token)是通过HMAC算法或者RSA的公钥密钥签名生成携带用户信息的token,将token存放在客户端中(可以存储在cookie,localstorage和sessionStorage中),客户端每次发送请求,都携带token,服务端通过解密来获取用户信息。
-
优点:
-
token包含用户的基本信息,避免再次查库;
-
token存储在客户端,不占用服务器资源。
-
-
缺点:
-
token经过base64编码,可以被解码,因此不能包含用户敏感信息(用户权限、密码等);
-
服务器无存储,因此不能做登录失效处理,除非更改服务器密钥。
-
JWT格式包括3类,下面是一段JWT:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
-
头部:主要是描述签名算法;
-
负载:主要是描述加密对象的信息,主要描述是加密对象的信息,如用户的id等,也可以加些规范里面的东西,如iss 签发者,exp 过期时间,sub 面向的用户;
-
签名:主要是把前面两部分进行加密,防⽌别⼈拿到token进行base解密后篡改token。
三、JWT使用
在SSM框架中,JWT的使用方法:
-
添加依赖(POM.xml)
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency> -
添加工具类,开发:生产token方法、校验token方法
/**
* JWT工具类
* 1、生成的token,是可以通过base64解密出明文信息的
* 2、base65解密出文明信息,修改后编码,则会解密失败
* 3、无法作废已颁布的token,除非改密钥
*/
public class JWTUtils {
/***
* 过期时间,一周
*/
private static final long EXPIRE = 60000*60*24*7;
/**
* 加密密钥
*/
private static final String SECRET = "dsaclass.net168";
/**
* 令牌前缀
*/
private static final String TOKEN_PREFIX = "dsaclass";
/**
* subject
*/
private static final String SUBJECT = "dsaclass";
/**
* 根据用户信息,生成令牌
* @param user
* @return
*/
public static String geneJsonWebToken(User user){
String token = Jwts.builder().setSubject(SUBJECT)
.claim("head_img", user.getHeadImg())
.claim("id", user.getId())
.claim("name", user.getName())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
.signWith(SignatureAlgorithm.HS256, SECRET).compact();
token = TOKEN_PREFIX + token;
return token;
}
/**
* 校验token
* @param token
* @return
*/
public static Claims checkJWT(String token){
try{
final Claims claims = Jwts.parser().setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody();
return claims;
}catch (Exception e){
return null;
}
}
} -
相关类中调用
public String findByPhoneAndPwd(String phone, String pwd) {
User user = userMapper.findByPhoneAndPwd(phone,CommonUtils.MD5(pwd));
if(user == null){
return null;
}
return JWTUtils.geneJsonWebToken(user);
}2、私有网页,拦截器拦截验证(不包括登录和注册页面请求)。
public class LoginInterceptor implements HandlerInterceptor {
/**
* controller前登录拦截
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
-

浙公网安备 33010602011771号