一、Token優勢
山東掌趣網絡科技
?
1.1 與cookie相比較的優勢
1、支持跨域訪問,將token置于請求頭中,而cookie是不支持跨域訪問的;
2、無狀態化,服務端無需存儲token,只需要驗證token信息是否正確即可,而session需要在服務端存儲,一般是通過cookie中的sessionID在服務端查找對應的session;
3、無需綁定到一個特殊的身份驗證方案(傳統的用戶名密碼登陸),只需要生成的token是符合我們預期設定的即可;
4、更適用于移動端(Android,IOS,小程序等等),像這種原生平臺不支持cookie,比如說微信小程序,每一次請求都是一次會話,當然我們可以每次去手動為他添加cookie,詳情請查看博主另一篇博客;
5、避免CSRF跨站偽造攻擊,還是因為不依賴cookie;
6、非常適用于RESTful API,這樣可以輕易與各種后端(JAVA,.net,Python......)相結合,去耦合
還有一些優勢這里就不一一列舉了。
1.2 基于JWT的token認證實現
JWT:JSON Web Token,其實token就是一段字符串,由三部分組成:Header,Payload,Signature。詳細情況請自行百度,現在,上代碼。
二、加密解密
山東掌趣網絡科技
?
2.1 pom.xml
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
2.2 加密
//加密的數據
int userId = 51;
//加密的簽名
Algorithm algorithm = Algorithm.Hmac256("eyJhbGciO");
//加密頭
Map<String, Object> header = new HashMap<String, Object>();
header.put("typ", "JWT");
header.put("alg", "HS256");
try {
//超時時間
Date date = new Date(System.currentTimeMillis() + 30 * 1000);
//令牌token
String token = JWT.create().withHeader(header).withClaim("userId", userId).withExpiresAt(date)
.sign(algorithm);
System.out.println(token);
} catch (Exception e) {
// TODO: handle exception
}
2.3 解密
//前端傳過來的令牌
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzg1NTEyOTgsInVzZXJJZCI6ImhlbGxvIn0.mVXwBkBMO-Sr3FJPZSVLezUuxdvMwNsGgRqTCVufH8o";
//和上面一樣的簽名
Algorithm algorithm = Algorithm.HMAC256("eyJhbGciO");
JWTVerifier verifier = JWT.require(algorithm).build();
//開始解密,失敗的話會出現異常
DecodedJWT jwt = verifier.verify(token);
System.out.println(jwt.getClaim("userId").asInt());
三、封裝工具類JWTUtil
山東掌趣網絡科技
?
public class JWTUtil {
private static final String TOKEN_SECRET = "eyJhbGciO";
private static final String CLAIM_NAME = "sign";
private static final long EXPIRE_TIME = 15 * 60 * 1000;
public static String sign(String sign) {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
Map<String, Object> header = new HashMap<String, Object>();
header.put("typ", "JWT");
header.put("alg", "HS256");
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
String token = JWT.create().withHeader(header).withClaim(CLAIM_NAME, sign).withExpiresAt(date)
.sign(algorithm);
return token;
} catch (Exception e) {
return null;
}
}
public static String verify(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return jwt.getClaim(CLAIM_NAME).asString();
} catch (Exception e) {
return null;
}
}
}
山東掌趣網絡科技