SpringBoot實現基於token的登錄驗證

一.SpringBoot實現基於token的登錄驗證

基於token的登錄驗證實現原理:客戶端通過用戶名和密碼調用登錄介面,當驗證資料庫中存在該用戶後,將用戶的資訊按照token的生成規則,生成一個字元串token,返回給客戶端,客戶端在調用其他介面的時候,需要在請求頭上帶上token,來驗證登錄資訊。

二.Demo實現程式碼如下:

(因為除登錄介面外,其他介面每次都需要驗證token資訊,所以將驗證token資訊的部分放在了過濾器裡面)

1.導入JWT(JSON WEB TOKEN)依賴

 

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.6.0</version>
</dependency>

 

2.Jwt工具類,包括token的生成和驗證(加密秘鑰先自己隨便寫了一個)

 

@Component
public class JwtUitls {
    
    @Autowired
    private UserService userService;
    /**
     * 過期時間5分鐘
     */
     private static final long EXPIRE_TIME=5*60*1000;
    /**
     * 加密密鑰
     */
    private static final String KEY = "liuhongfei";

    /**
     * 生成token
     * @param id    用戶id
     * @param userName  用戶名
     * @return
     */
    public String createToken(String id,String userName){
        Map<String,Object>  header = new HashMap();
        header.put("typ","JWT");
        header.put("alg","HS256");
        //setID:用戶ID
        //setExpiration:token過期時間  當前時間+有效時間
        //setSubject:用戶名
        //setIssuedAt:token創建時間
        //signWith:加密方式
        JwtBuilder builder = Jwts.builder().setHeader(header)
                           .setId(id)
                           .setExpiration(new Date(System.currentTimeMillis()+EXPIRE_TIME))
                           .setSubject(userName)
                           .setIssuedAt(new Date())
                           .signWith(SignatureAlgorithm.HS256,KEY);
        return builder.compact();
    }

    /**
     * 驗證token是否有效
     * @param token  請求頭中攜帶的token
     * @return  token驗證結果  2-token過期;1-token認證通過;0-token認證失敗
     */
    public int verify(String token){
        Claims claims = null;
        try {
            //token過期後,會拋出ExpiredJwtException 異常,通過這個來判定token過期,
            claims = Jwts.parser().setSigningKey(KEY).parseClaimsJws(token).getBody();
        }catch (ExpiredJwtException e){
          return 2;
        }
        //從token中獲取用戶id,查詢該Id的用戶是否存在,存在則token驗證通過
        String id = claims.getId();
        User user = userService.selectUserById(id);
        if(user != null){
            return 1;
        }else{
            return 0;
        }
    }
}

 

3.過濾器,實現filter介面

 

/**
* @description:
* @author: hwx
* @date: 2022/05/23
**/
@Order(1)
//如果我們有多個過濾器,那這個Order就可以指定優先順序
@Component
//這裡可以使用@Compent,也可以不加這個@Component,而是在@SpringBootApplication入口類上新增註解@ServletComponentScan。@Component也可以替換成@Configration
@WebFilter(urlPatterns = "/*",filterName = "myFilter")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("我是過濾器的初始化方法init");
}

@Override
public void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException {
System.out.println("我是過濾器的真正的執行方法doFilter,serverlet的請求,you are wanted one");
HttpServletResponse httpServletResponse=(HttpServletResponse)var2;
//允許的請求頭欄位
httpServletResponse.setHeader("Access-Control-Allow-Headers","Origin, X-Requested-With, Content-Type, Accept");
//是否允許後續請求攜帶認證資訊(cookies),該值只能是true,否則不返回
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
//指定允許其他域名訪問
httpServletResponse.setHeader("Access-Control-Allow-Origin", "//127.0.0.1:8070");
//參數 chain 為代表當前 Filter 鏈的對象。
var3.doFilter(var1,httpServletResponse);
System.out.println("我是過濾器的真正的執行方法doFilter,serverlet的請求,you are wanted two");
}

@Override
public void destroy() {
System.out.println("不行了,我要被銷毀了");
}
}

 

4.使用postman測試結果如下
(1)調用login介面,返回token

 

 (2)調用查詢用戶介面,在請求頭中加入token

 

 (3)不攜帶token,調用查詢介面

 

 

 

 (4)token過期後,調用查詢介面

 

 以上就是一個簡單的token登錄機制
token登錄機制的好處:不需要將登錄資訊保存在資料庫或session中
token中還可以攜帶更多的用戶資訊,包括許可權等