JSON Web Token
是一种开放标准,用于在网络上安全传输信息的简洁、自包含的方式。它通常被用于身份验证和授权机制。 JWT 由三部分组成:头部(Header)、载荷(Payload)和签名(Signature)。
- 头部(Header):包含了关于生成该 JWT 的信息以及所使用的算法类型。
- 载荷(Payload):包含了要传递的数据,例如身份信息和其他附属数据。JWT 官方规定了 7 个字段,可供使用:
- iss (Issuer):签发者。
- sub (Subject):主题。
- aud (Audience):接收者。
- exp (Expiration time):过期时间。
- nbf (Not Before):生效时间。
- iat (Issued At):签发时间。
- jti (JWT ID):编号。
- 签名(Signature):使用密钥对头部和载荷进行签名,以验证其完整性。
JWT 官网:https://jwt.io/open in new window
JWT的优点?
JWT 相较于传统的基于会话(Session)的认证机制,具有以下优势:
- 无需服务器存储状态:传统的基于会话的认证机制需要服务器在会话中存储用户的状态信息,包括用户的登录状态、权限等。而使用 JWT,服务器无需存储任何会话状态信息,所有的认证和授权信息都包含在 JWT 中,使得系统可以更容易地进行水平扩展。
- 跨域支持:由于 JWT 包含了完整的认证和授权信息,因此可以轻松地在多个域之间进行传递和使用,实现跨域授权。
- 适应微服务架构:在微服务架构中,很多服务是独立部署并且可以横向扩展的,这就需要保证认证和授权的无状态性。使用 JWT 可以满足这种需求,每次请求携带 JWT 即可实现认证和授权。
- 自包含:JWT 包含了认证和授权信息,以及其他自定义的声明,这些信息都被编码在 JWT 中,在服务端解码后使用。JWT 的自包含性减少了对服务端资源的依赖,并提供了统一的安全机制。
- 扩展性:JWT 可以被扩展和定制,可以按照需求添加自定义的声明和数据,灵活性更高。
总结来说,使用 JWT 相较于传统的基于会话的认证机制,可以减少服务器存储开销和管理复杂性,实现跨域支持和水平扩展,并且更适应无状态和微服务架构。
如下,为admin添加token的JWTUtil类:
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.yyds.news.model.Admin;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* JWT工具类:生成token
*/
public class JWTUtil {
/**
* 根据用户id,账号生成token
* @param u
* @return
*/
public static String getToken(Admin u) {
String token = "";
try {
//过期时间 为1970.1.1 0:0:0 至 过期时间 当前的毫秒值 + 有效时间
Date expireDate = new Date(new Date().getTime() + 3600*1000);
//秘钥及加密算法
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
//设置头部信息
Map<String,Object> header = new HashMap<>();
header.put("typ","JWT");
header.put("alg","HS256");
//携带id,账号信息,生成签名
token = JWT.create()
.withHeader(header)
.withClaim("id",u.getId())
.withClaim("account",u.getAccount())
.withClaim("type",u.getType())
.withExpiresAt(expireDate)
.sign(algorithm);
}catch (Exception e){
e.printStackTrace();
return null;
}
return token;
}
/**
* 验证token是否有效
* @param token
* @return
*/
public static boolean verify(String token){
try {
//验签
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {//当传过来的token如果有问题,抛出异常
return false;
}
}
/**
* 获得token 中playload部分数据,按需使用
* @param token
* @return
*/
public static DecodedJWT getTokenInfo(String token){
return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
}
public static Admin getOperAdminByToken(String token){
DecodedJWT tokenInfo = getTokenInfo(token);
Admin operAdmin = new Admin();
operAdmin.setId(tokenInfo.getClaim("id").asInt());
return operAdmin;
}
}
在项目中使用:
加密:
Web层:
Service层
前端:存储在浏览器的sessionStorage中