一、JWT的原则
服务器身份验证之后,将生成一个JSON对象并将其发送回用户,当用户与服务器通信时,客户在请求中发回JSON对象,服务器仅依赖于JSON对象来标识用户,为了防止用户篡改数据,服务器将在生成对象的时候添加签名.
服务器不保存任何会话的数据,即服务器变为无状态,使其更容易扩展
二、JWT的用法
客户端接受服务器返回的JWT,将其存储在Cookie或者LocalStorage中,此后客户端将在与服务器交互中都会带上jwt.如果将它存储在cookie中,就可以自动发送,但是不是跨域,因此一般是将他放入到HTTP请求的Header Authorization字段中,当跨域的时候,也可以将JWT被放置与POST请求的数据总体中。
三、JWT的形式
1、JWT不仅可以用于认证,还可用于信息交换.善用JWT有助于减少服务器请求数据库的次数
2、生产的token可以包含基本信息,比如ID,用户昵称,头像等信息,避免再次查询数据库
3、存储在客户端,不占用客户端的内存资源
4、JWT默认不加密,但是可以加密,生成原始令牌以后,可以再次对其进行加密
5、当JWT未加密是,一些私密的数据无法通过JWT传输
6、JWT最大的缺点是服务器不会保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限,也就是说,一旦jwt签发,在有效期内将会一直有效
7、为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行进行身份验证
8、不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。
四、JWT构成
一个token由三部分构成:
- 头部(header)
- 载荷(payload)
- 签名(signature)
头部(header)
JWT的头部承载两部分信息:
- 声明类型 ,这里是jwt
- 声明加密的算法 ,通常直接使用HMAC SHA256
//header Map
Map<String,Object> map = new HashMap<String,Object>();
map.put("alg","HS256");
map.put("typ","JWT");
载荷(playload)
载荷就是存放有效信息的地方,存放在JWT的chaims里面。
JWT.create().withHeader(map)//header
.withClaim("id","sdfsf")//payload
.withClaim("name","fsdfds")//payload
.withIssuedAt(currDate)//sign time
.withExpiresAt(expireDate)//expire time
签名(signature)
签名信息的算法:
base64UrlEncode(header)+"."+base64UrlEncode(payload)+your-256-bit-secret
这个需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后构成了JWT的第三部分。
五、JWT的用法
1、引用JWT的jar包
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
2、创建JWT的工具包
import java.util.Date;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class TokenUtils {
private static final String SUBJECT = "fenxiangba";
private static final String APPSECRET = "abc";// 密钥
private static final Long ExPIRE = (long) (1000 * 60 * 60 * 7);// 毫秒
/**
* 用户id生成jwt token
*
* @param member
* @return
*/
public static String getToken(String userId) {
String token = Jwts.builder().setSubject(SUBJECT).claim("id", userId)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + ExPIRE))
.signWith(SignatureAlgorithm.HS256, APPSECRET).compact();
return token;
}
/**
* 校验jwt token
*
* @param token
* @return
*/
public static Claims checkJWT(String token) {
try {
Claims claims = Jwts.parser().setSigningKey(APPSECRET)
.parseClaimsJws(token).getBody();
return claims;
} catch (Exception e) {
// TODO: handle exception
return null;
}
}
public static void main(String[] args) {
String userId = "adssdf45647";
String token = getToken(userId);
Claims claims = checkJWT(token);
if (claims != null) {
String id = (String) claims.get("id");
System.out.println(userId.equals(id));
}
}
}
参考文章