springboot jwt token 登入
阿新 • • 發佈:2022-03-29
基本概念:
jwt(json web token):是一種緊湊、URL安全的方法,用於表示雙方之間要傳輸的宣告.
JWT 由 3 部分構成:
- Header : 描述 JWT 的元資料,定義了生成簽名的演算法以及 Token 的型別。
- Payload : 用來存放實際需要傳遞的資料
- Signature(簽名) :伺服器通過Payload、Header和一個金鑰(secret)使用 Header 裡面指定的簽名演算法(預設是 HMAC SHA256)生成。
具體流程
- 使用者使用使用者名稱密碼來請求伺服器
- 伺服器進行驗證使用者的資訊
- 伺服器通過驗證傳送給使用者一個token
- 客戶端儲存token(可以放在cookie或者localstorge),並在每次請求時附送上這個token值
- 服務端驗證token值,並返回資料
springboot 詳細配置
pom
加一個maven配置
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
token utils
這裡主要由兩個功能 生成token,和驗證token
生成token
- 向token新增資料 2.設定過期時間 3.新增加密演算法
token一般新增的資料 (建議但不強制使用) :
iss: jwt簽發者
sub: jwt所面向的使用者
aud: 接收jwt的一方
exp: jwt的過期時間,這個過期時間必須要大於簽發時間
nbf: 定義在什麼時間之前,該jwt都是不可用的.
iat: jwt的簽發時間
jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。
驗證token
1.通過解密方法解密
@Component public class TokenUtil { private static final long EXPIRE_TIME= 15*60*1000; private static final String TOKEN_SECRET="token123"; //金鑰鹽 /** * 簽名生成 * @return */ public static String sign(String name){ String token = null; try { Date expiresAt = new Date(System.currentTimeMillis() + EXPIRE_TIME); token = JWT.create() .withIssuer("auth0").withClaim("id","id") .withClaim("username", name) .withExpiresAt(expiresAt) // 使用了HMAC256加密演算法。 .sign(Algorithm.HMAC256(TOKEN_SECRET)); } catch (Exception e){ e.printStackTrace(); } return token; } /** * 簽名驗證 * @param token * @return */ public static boolean verify(String token){ try { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build(); DecodedJWT jwt = verifier.verify(token); System.out.println("認證通過:"); System.out.println("issuer: " + jwt.getIssuer()); System.out.println("username: " + jwt.getClaim("username").asString()); System.out.println("id"+jwt.getClaim("id").asString()); System.out.println("過期時間: " + jwt.getExpiresAt()); return true; } catch (Exception e){ return false; } } }
controller
@RestController
public class LoginController {
@RequestMapping("/login")
public String login(HttpSession session, String name, String password){
System.out.println(name);
System.out.println(password);
// 這個需要查資料庫判斷使用者名稱和密碼是否正確
if(Objects.equals(name, "xx") && Objects.equals(password, "xx"))
{
String res = TokenUtil.sign("xx");
System.out.println(res);
return "成功:"+res;
}
return "失敗";
}
@RequestMapping("/index")
public String index(){
return "登入";
}
}
@RestController
public class TestController {
@RequestMapping("/hello")
public String helloWorld(){
return "hello world";
}
@RequestMapping("/hello02")
public String helloWorld02(){
return "hello world 02";
}
}
過濾器
得到ajax傳過來的header,驗證token是否正確
public class LoginInterceptor implements HandlerInterceptor {
// 這裡我們也可以放在redis
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 如果我們的map有瀏覽器存過來的sessionid我們就任務他是已經登入了。
String token = request.getHeader("admin-token");
if(TokenUtil.verify(token)){
return true;
}
// 失敗我們跳轉新的頁面
request.setAttribute("msg","登入出錯");
request.getRemoteHost();
request.getRequestDispatcher("/index").forward(request,response);
return false;
}
}
過濾器配置
@Configuration
public class InterceptorConfig {
@Bean
public MappedInterceptor loginInterceptor(){
// 設定攔截器的作用域
return new MappedInterceptor(new String[]{"/**"},new String[]{"/login","/index"},new LoginInterceptor());
}
}