JWT token 用户验证
传统 session 验证
过程 : 服务端验证 浏览器 携带的 用户名 密码 , 验证通过 生成 session 存在
服务端
,
浏览器再次访问,服务端查询 session 实验登录状态保持。
缺点 :用户增多,服务器压力增大,访问量过大的时候,内存暴增。
cookie 被攻击拦截、容易受到跨站请求伪造攻击。
分布式下扩展性不强 **存在不同服务器上 进程不共享 **。(目前未接触分布式)。
token 登录验证
过程 : 服务端验证 浏览器 携带的 用户名 密码 , 验证通过 生成 token (用户令牌) 返回给 浏览器,存在
localstore
里面, 浏览器再次访问 要携带 token ,服务器端 校验
token
并返回相关数据。
相比于 session 优点 :
-
存在 非 cookie 中安全性高。
-
不存储在服务器端,服务器压力减小。
-
分布式下扩展性强,并不是存在某个服务器上。
jwt 组成 优点
优点 : 跨语言优势、便于传输、易于扩展。
组成 :
header : 声明类型,声明的加密算法。
最重点 有用
payload : 存放有效信息 数据 定制化强。 一般包含 签发者 ,过期时间,接受方,签发时间,唯一身份标识符
一定要包含
唯一身份标识符
signature :头部 载荷 和 密钥 组合加密而成
使用 demo 示例
引入 jwt token 依赖 简化开发
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.11.0</version>
</dependency>
jwt token 签名 密钥 部分
密钥使用算法生成 基于 rsa256
Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(),RSAUtil.getPrivateKey());
官方
RSAPublicKey publicKey = //Get the key instance
RSAPrivateKey privateKey = //Get the key instance
try {
Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
String token = JWT.create()
.withIssuer("auth0")
.sign(algorithm);
} catch (JWTCreationException exception){
//Invalid Signing configuration / Couldn't convert Claims.
}
jwt
过期时间
这里选择 calender 类 calender 常用方法 这里就不说了
calendar.setTime(new Date());
calendar.add(Calendar.SECOND,30);
组成 jwt token 加密
return JWT.create().withKeyId(String.valueOf(userId))
.withIssuer(ISSUER)
.withExpiresAt(calendar.getTime())
.sign(algorithm);
sign
对头部信息和 负载信息做一个统一的 加密。
登录 逻辑
public String login(User user) {
// 数据有效验证 省略
return TokenUtil.generateToken(userByPhone.getId());
}
jwt token 解密
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE";
RSAPublicKey publicKey = //Get the key instance
RSAPrivateKey privateKey = //Get the key instance
try {
// 签名算法一直
Algorithm algorithm = Algorithm.RSA256(publicKey, privateKey);
JWTVerifier verifier = JWT.require(algorithm)
.withIssuer("auth0")
.build(); //Reusable verifier instance
// 可以获取任何信息。
DecodedJWT jwt = verifier.verify(token);
} catch (JWTVerificationException exception){
//Invalid signature/claims
}
public static Long verifyToken(String token) {
try {
Algorithm algorithm = Algorithm.RSA256(RSAUtil.getPublicKey(),RSAUtil.getPrivateKey());
JWTVerifier jwtVerifier = JWT.require(algorithm).withIssuer(ISSUER).build();
DecodedJWT verify = jwtVerifier.verify(token);
String keyId = verify.getKeyId();
return Long.valueOf(keyId);
} catch (TokenExpiredException e) {
throw new ConditonException("token 过期 啦 重新登陆 ");
}catch (Exception e) {
throw new ConditonException("你不是有效用户~~");
}
}
接下来 token 登录 最主要的已经写完 在 登录 带了有效token 或者 请求访问 携带了 相关的token参数 服务器端就可以通过解析 jwt-token 令牌 来获取 用户的各种信息。perfect。
可以写一个 通用方法来获取 用户信息 减少代码重复。至此 简单登陆验证完成。
参考附录 :
使用auth0构建JWT