JWT
2026-02-06 13:42:21 0 举报
AI智能生成
jwt知识
作者其他创作
大纲/内容
常见jwt框架
jose4j
nimbus-jose
fusionauth
vertx
依赖
<groupId>io.jsonwebtoken</groupId><br><artifctId>jjwt</artifactId><br><version>0.9.1</version>
主要类
Jwts.builder() // 用于创建和解析 JWT 的主要类
Jwts.parser() // 用于解析并验证 JWT 是否有效的接口
使用
获取令牌
<font color="#7bd144">private static String secret = "@abc#abc"; // 密钥,随便写<br>private static Date expire = new Date(System.currentTimeMillis() + (1000 * 60 * 60 * 24)); // 设置token有效时间为1天</font><br><br>// 创建token<br>public static String createToken(Map<String, Object> claims) {<br> String jwtToken = Jwts.builder()<br> <font color="#7985ec">.setHeaderParam("typ", "JWT") // 设置头部<br> .setHeaderParam("alg", "HS256")<br></font> <font color="#7bd144">.addClaims(claims) // 设置载荷,可以用map集合</font><br> <font color="#7f8b98">// .claim("username", "tom") // 设置载荷,自定义内容,可以一个一个写<br> // .claim("role", "admin")</font><br><font color="#7bd144"> .setExpiration(expire) // 设置token有效时间</font><br> <font color="#4dd0e1">.signWith(SignatureAlgorithm.HS256, secret) // 设置签名算法</font><br> .compact(); // 将上面的数据变成字符串<br> return jwtToken;<br>}
令牌验证
// 验证token<br>public static Claims parseToken(String token) {<br> Claims claims = Jwts.parser()<br> <font color="#7bd144">.setSigningKey(secret) // 设置验证需要的密钥,必须和上面生成token使用的密钥一致<br> .parseClaimsJws(token) // token是从前端携带过来的<br> .getBody(); // 获取载荷部分的数据</font><br> return claims;<br>}
验证正确就会返回载荷部分的数据<br>验证不正确就会抛出异常
jjwt-api是jjwt的轻量级版本,它去掉了jwt的签名和验证功能,仅保留了创建jwt令牌的功能。<br>jjwt提供了jwt令牌的构建、签名和验证功能。
依赖
<groupId>com.auth0</groupId><br><artifctId>java-jwt</artifactId>
主要类
JWT.create() // 用于创建和解析 JWT 的主要类
JWT.require() // 用于解析并验证 JWT 是否有效的接口
使用
获取令牌
public static void createToken() {<br> String token = JWT.create()<br> .withClaim("userid", 12)<br> .withClaim("username", "admin")<br> .withClaim("role", "管理员")<br> .sign(Algorithm.HMAC256("@hello"));<br> System.out.println(token);<br> }
令牌验证
public static void verifyToke() {<br> JWTVerifier build = JWT.require(Algorithm.HMAC256("@hello")).build();<br> DecodedJWT verify = build.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoi566h55CG5ZGYIiwidXNlcmlkIjoxMiwidXNlcm5hbWUiOiJhZG1pbiJ9.W4MprAIYnVN47D9cYKmAGiSWUIoKOq3frEnzJf3abEw");<br> System.out.println(verify.getClaim("userid").asInt());<br> System.out.println(verify.getClaim("username").asString());<br><br> }
为什么使用token?
早期我们使用session(客户端使用cookie)来存储登录信息来实现验证的,但相比于session,基于token的认证有以下优点
使用token
支持跨域访问:cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题<br>
无状态:token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力
更适用CDN:可以通过内容分发网络请求服务端的所有资料
更适用于移动端:当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多<br>
无需考虑CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御
认证
你是谁
授权
你有权限干什么
定义
JWT(Json Web Token),Json格式的互联网令牌
由3部分组成
Header(头部)
{<br> "typ": "JWT", // 令牌类型<br> "alg": "HS256" // 签名算法(HMAC,SHA256,RSA)<br>}
Payload(载荷)
{<br> "sub": "12345678",<br> "name": "John",<br> "admin": true<br>}
Signature(签名)
var encodeString = base64UrlEncode(header) + "." + base64UrlEncode(payload);<br>var signature = HMACSHA256(encodeString, "secret");
类似于这种形式
xxxxx.yyyyy.zzzzz
Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的,它并不是一种加密过程
原理
Header原本是一个json对象:{"typ": "JWT", "alg": "HS256"},使用base64算法将json对象转成字符串,该字符串就是token的第一部分
Payload原本是一个json对象:{"sub": "12345678", "name": "John", "admin": true},使用base64算法将json对象转成字符串,该字符串就是token的第二部分
载荷部分,JWT制定了7个默认字段供选择,还可以自定义字段<br>iss: jwt签发者<br>sub: jwt所面向,使用jwt的用户<br>aud: 接收jwt的一方<br>exp: jwt的过期时间,这个过期时间必须大于签发时间<br>nbf: 定义在指定时间之前,该jwt都是不可用的.<br>iat: jwt的签发时间<br>jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
签名是等于HS256(Base64(header) + "." + Base64(payload), secret),经过base64编码的头部拼接上经过base64编码的载荷,再通过密钥,再通过HS256算法变成一个字符串,该字符串就是token的第三部分
过程
客户端第一次登录服务器,服务器会创建token,然后服务器将token响应给客户端;
客户端第二次登录服务器时携带着token信息,服务器从客户端传过来的token中拿到头部,载荷,和服务器上面存储的密钥经过HS256算法得到签名,拿服务器新生成的签名和客户端传过来的token中的签名做比对,如果一致,说明是同一个用户。
RSA数字签名算法
公钥和私钥通过RSA算法得到
文件通过哈希算法得到文件哈希值,使用私钥根据RSA解密公式对文件哈希值进行签名运算得到数字签名
0 条评论
下一页