Json web token (JWT), 是為了在網路應用環境間傳遞宣告而執行的一種基於JSON的開放標準((RFC 7519).定義了一種簡潔的,自包含的方法用於通訊雙方之間以JSON物件的形式安全的傳遞資訊。因為數位簽章的存在,這些資訊是可信的,JWT可以使用HMAC演演算法或者是RSA的公私祕鑰對進行簽名。
身份認證在這種場景下,一旦使用者完成了登陸,在接下來的每個請求中包含JWT,可以用來驗證使用者身份以及對路由,服務和資源的存取許可權進行驗證。由於它的開銷非常小,可以輕鬆的在不同域名的系統中傳遞,所有目前在單點登入(SSO)中比較廣泛的使用了該技術。 資訊交換在通訊的雙方之間使用JWT對資料進行編碼是一種非常安全的方式,由於它的資訊是經過簽名的,可以確保傳送者傳送的資訊是沒有經過偽造的。
Header 頭部(標題包含了令牌的後設資料,並且包含簽名和/或加密演演算法的型別)
Payload 負載 (類似於飛機上承載的物品)
Signature 簽名/簽證
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<dependency>
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping(value = "/login")
public String login(@RequestBody User user){
return userService.login(user);
}
}
public class UserServiceImpl implements UserService {
public static final String USERNAME = "admin";
public static final String PASSWORD = "admin";
@Override
public String login(User user) {
//忽略查詢資料庫
if (USERNAME.equals(user.getName()) && PASSWORD.equals(user.getPassword())){
//建立使用者令牌資訊
Map<String, Object> map = new HashMap<>();
map.put("role","USER");
map.put("success","SUCCESS");
map.put("username",user.getName());
//建立使用者Token
String token = JwtUtil.createJWT(UUID.randomUUID().toString(), JSON.toJSONString(map), null);
//現在就可以儲存tonken了,為了方便直接存到cookie裡面去
Cookie cookie = new Cookie("Authoriztion", token);
cookie.setDomain("localhost");
cookie.setPath("/");
return token;
}
return "登入失敗";
}
@Override
public List<User> getUserInfo() {
return null;
}
}
public class JwtUtil {
//令牌有效期 1小時
public static final Long JWT_TTL = 3600000L;
//jwt令牌資訊
public static final String JWT_KEY = "mzjmc";
public static String createJWT(String id, String subject, Long ttlMillis){
//指定簽名演演算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//當前系統時間
long currentTimeMillis = System.currentTimeMillis();
//令牌簽發的時間
Date date = new Date(currentTimeMillis);
//如果令牌的有效期為空則預設一小時
if (ttlMillis == null){
ttlMillis = JWT_TTL;
}
//令牌過期時間
long expMillis = currentTimeMillis + ttlMillis;
Date expDate = new Date(expMillis);
//生成祕鑰
SecretKey secretKey = generalKey();
//封裝jwt資訊
JwtBuilder jwtBuilder = Jwts.builder();
jwtBuilder.setId(id); //唯一ID
jwtBuilder.setSubject(subject); //主題資訊
jwtBuilder.setIssuer("admin"); //簽發者
jwtBuilder.setIssuedAt(date); //簽發時間
jwtBuilder.signWith(SignatureAlgorithm.HS256, secretKey); //演演算法及簽名祕鑰
jwtBuilder.setExpiration(expDate); //過期時間
return jwtBuilder.compact();
}
/**
* 生成祕鑰
* @return
*/
public static SecretKey generalKey(){
byte[] encode = Base64.getEncoder().encode(JWT_KEY.getBytes());
return new SecretKeySpec(encode, 0, encode.length, "AES");
}
}