1. 程式人生 > 其它 >springboot jwt token 登入

springboot jwt token 登入

基本概念:

jwt(json web token):是一種緊湊、URL安全的方法,用於表示雙方之間要傳輸的宣告.
JWT 由 3 部分構成:

  1. Header : 描述 JWT 的元資料,定義了生成簽名的演算法以及 Token 的型別。
  2. Payload : 用來存放實際需要傳遞的資料
  3. Signature(簽名) :伺服器通過Payload、Header和一個金鑰(secret)使用 Header 裡面指定的簽名演算法(預設是 HMAC SHA256)生成。

具體流程

  1. 使用者使用使用者名稱密碼來請求伺服器
  2. 伺服器進行驗證使用者的資訊
  3. 伺服器通過驗證傳送給使用者一個token
  4. 客戶端儲存token(可以放在cookie或者localstorge),並在每次請求時附送上這個token值
  5. 服務端驗證token值,並返回資料

springboot 詳細配置

pom

加一個maven配置

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>

token utils

這裡主要由兩個功能 生成token,和驗證token

生成token

  1. 向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());
    }
}

使用