分布式应用的用户信息检验方案JWT
作者:互联网
目录
jwt简介
Json web token(JWT):使用HMAC或RSA算法加密用户信息生成token,存储在客户端(浏览器),客户端请求服务端时携带上token,服务端解密token获取用户信息。
优缺点
- 优点:token包含了用户的id、昵称、头像等基本信息,避免了再次查库;使用json交换数据,通用、轻量;token存储在客户端,适合分布式应用、单点登录,不占用服务端的内存资源。
- 缺点:token存储在客户端,获取到token后可直接使用他人身份进行操作,有一定的安全风险;尽量使用https协议,避免传输token到服务器时被他人窃取。
jwt的组成
- header:头部,主要描述签名算法。
- payload:负载,主要是加密的数据,也可以设置token过期时间等一些说明信息。payload中的数据可以被客户端解码,不要在token中存储密码、用户权限等敏感信息。
- signature:签名,把header、payload进行加密,防止别人窃取token后进行解密篡改。
token使用2个小数点分隔这三部分。
支持多种加密算法,最常用的是 HMAC SHA256。
token可以存储在浏览器的Cookie、Local Storage、Session Storage中,一般存储在Cookie中。
jwt有多种实现方式,java常用的2种jwt实现类库是jjwt、java-jwt。
jjwt实现jwt
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
import com.example.demo.entity.User;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
/**
* JWT工具类
*/
public class JWTUtil {
/**
* token颁布方
*/
public static final String ISSUER = "chy.com";
/**
* token过期时间,7天
*/
private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;
/**
* 秘钥
*/
public static final String SECRET = "chy.com";
/**
* token前缀
*/
public static final String TOKEN_PREFIX = "chy";
/**
* 生成token
*/
public static String generateToken(User user) {
String token = Jwts.builder()
//用户信息
.claim("id", user.getId())
.claim("username", user.getUsername())
.claim("head_img", user.getHeadImg())
//token颁布方
.setIssuer(ISSUER)
//token颁发时间
.setIssuedAt(new Date())
//token过期时间
.setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
//签名算法、秘钥
.signWith(SignatureAlgorithm.HS256, SECRET)
.compact();
//拼接前缀,可选
return TOKEN_PREFIX + token;
}
/**
* 解密token得到用户信息
*
* Claims中包含了token中存储的数据,可通过get方法获取,返回值是Object
* eg. String username = claims.get("username").toString();
*/
public static Claims checkToken(String token) {
try {
final Claims claims = Jwts.parser().setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody();
return claims;
} catch (Exception e) {
return null;
}
}
}
官方github地址:https://github.com/jwtk/jjwt
java-jwt实现jwt
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.13.0</version>
</dependency>
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.demo.entity.User;
import java.util.Date;
/**
* JWT工具类
*/
public class JWTUtil {
/**
* token颁布方
*/
public static final String ISSUER = "chy.com";
/**
* token过期时间,7天
*/
private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7;
/**
* 秘钥
*/
public static final String SECRET = "chy.com";
/**
* token前缀
*/
public static final String TOKEN_PREFIX = "chy";
/**
* 生成token
*/
public static String generateToken(User user) {
try {
//签名算法、秘钥
Algorithm algorithm = Algorithm.HMAC256(SECRET);
String token = JWT.create()
//用户信息
.withClaim("id", user.getId())
.withClaim("username", user.getUsername())
.withClaim("head_img", user.getHeadImg())
//token颁布方
.withIssuer(ISSUER)
//token颁发时间
.withIssuedAt(new Date())
//token过期时间
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE))
.sign(algorithm);
return token;
} catch (JWTCreationException exception) {
//Invalid Signing configuration | Couldn't convert Claims.
return null;
}
}
/**
* 解密token得到用户信息
*
* //获取token中所有的claim(封装的用户信息)
* Map<String, Claim> claims = decodedJWT.getClaims();
* //get()获取到的是Claim类型,需要用asXxx()转一下
* String string = claims.get("username").asString();
*/
public static DecodedJWT checkToken(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer(ISSUER)
.build();
DecodedJWT decodedJWT = verifier.verify(token);
return decodedJWT;
} catch (JWTVerificationException exception) {
//Invalid signature|claims
return null;
}
}
}
官方github地址:https://github.com/auth0/java-jwt
说明
1、可以加入一些额外的加密操作,增加被被人破解的难度,比如拼接前缀、使用其它加密算法再次加密等。
2、用户登录成功后,后端生成token,可以由后端操作HttpServletResponse把token添加到cookie中;也可以直接把token传给前端,由前端添加到cookie中。不管哪种,都需要手动设置cookie的过期时间。
3、在网关拦截器处,从HttpServletRequest对象中解析token获取用户信息
String token = httpServletRequest.getHeader("token");
标签:String,JWT,jwt,分布式应用,检验,token,static,import,com 来源: https://blog.csdn.net/chy_18883701161/article/details/113790388