開發之前我們先看一下接口文檔的要求:
開發思路:
開發實操:
因為我們之前開發注冊的時候,就有了一些相關的操作,所以在這里我們只需要定義登錄的controller即可:
//用戶登錄@PostMapping("/login")public Result login(@Pattern(regexp = "^\\S{5,16}$")String username,@Pattern(regexp = "^\\S{5,16}$") String password) {//根據用戶名查詢用戶User loginUser = userService.findUserByUsername(username);//判斷用戶是否存在if(loginUser == null){return Result.error("用戶不存在");}//判斷密碼是否正確//因為之前是加密后存儲的密碼,所以我們也應該加密后再判斷是否相同if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){//登錄成功return Result.success("jwt token 令牌");}return Result.error("密碼錯誤");}
測試:
我們將密碼打錯:
我們將密碼打對:
認證登錄【重點】:
為什么會有登錄認證呢?
因為你登錄用戶之后會有很多的對應的操作接口,那么你不登錄就無法使用到這些接口,所以,我們就會有“登錄認證”,首先我們會借助令牌這個東西去校驗我們的登錄是否合理.....
令牌:
令牌是什么:
令牌的作用:
意思就是通過令牌才能夠去訪問登陸后的所有資源
JWT令牌:
我們這里使用JWT令牌(由“頭”、“有效載荷”、“簽名”)
JWT令牌具體有生成步驟和驗證步驟:
生成令牌:
?
引入坐標:
<!--JWT令牌坐標--><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency><!--單元測試依賴--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
測試類中測試:
package org.huangyingyuan;import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;//測試生成的JWT令牌
public class JwtTest {@Testpublic void test() {Map<String, Object> claims = new HashMap<>();claims.put("id", 1);claims.put("username","張三");//生成jwt的代碼String token = JWT.create().withClaim("user",claims)//添加載荷.withExpiresAt(new Date(System.currentTimeMillis() + 1000*60*60*12))//設置過期時間(為12小時).sign(Algorithm.HMAC256("huangyingyuan"));//指定算法,配置秘鑰System.out.println(token);}
}
測試結果為:
驗證令牌:
?
在測試類中測試:
//驗證jwt令牌@Testpublic void testParse(){//定義字符串token,模擬用戶傳過來的tokenString token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +".eyJ1c2VyIjp7ImlkIjoxLCJ1c2VybmFtZSI6IuW8oOS4iSJ9LCJleHAiOjE3NDMzNTc5NTB9" +".ipTTySrl3HwtkmcqUfMyp_os_M9cJIqa2kG01qNPYxo";JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("huangyingyuan")).build(); //構建驗證器DecodedJWT decodedJWT = jwtVerifier.verify(token); //驗證tokenMap<String, Claim>claims=decodedJWT.getClaims(); //獲取載荷System.out.println(claims.get("user"));}
測試的結果如下:
幾種測試失敗的可能:
1.篡改了頭部和載荷部分的數據,那么驗證失敗
2.密鑰改了,驗證失敗
3.token設置的時間過期
正片開始:
生成JWT令牌:
1.導入Jwt的Util的工具類
省略
2.在controller類下去生成token,返回數據
//用戶登錄@PostMapping("/login")public Result login(@Pattern(regexp = "^\\S{5,16}$")String username,@Pattern(regexp = "^\\S{5,16}$") String password) {//根據用戶名查詢用戶User loginUser = userService.findUserByUsername(username);//判斷用戶是否存在if(loginUser == null){return Result.error("用戶不存在");}//判斷密碼是否正確//因為之前是加密后存儲的密碼,所以我們也應該加密后再判斷是否相同if(Md5Util.getMD5String(password).equals(loginUser.getPassword())){//生成token(JWT令牌)Map<String, Object>claims=new HashMap<String, Object>();claims.put("id",loginUser.getId());claims.put("username",loginUser.getUsername());JwtUtil.genToken(claims);String token = JwtUtil.genToken(claims);//登錄成功return Result.success(token);}return Result.error("密碼錯誤");}
3.測試
驗證JWT令牌:
?
我們先看一下接口文檔的要求:
需要在請求頭獲取令牌,并定義了請求頭名的是什么
若錯誤,定義響應碼為401
攔截器:
設置攔截器后的登錄驗證流程:
注意!
1.@RequestHeader("Authorization")設置請求頭
2.傳入HttpServletResponse參數,提供響應碼
package org.huangyingyuan.controller;import jakarta.servlet.http.HttpServletResponse;
import org.huangyingyuan.pojo.Result;
import org.huangyingyuan.utils.JwtUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;//模擬在用戶登陸后才能使用的功能(在學習JWT令牌的作用)
@RestController
@RequestMapping("/article")
public class ArticleController {@GetMapping("/list")public Result<String> list(@RequestHeader("Authorization") String token, HttpServletResponse response) {//如果接受成功則解析token,失敗則修改狀態碼為401try{//模擬token驗證Map<String, Object> claims = JwtUtil.parseToken(token);return Result.success("所有的文章數據....");}catch (Exception e){//http響應狀態碼為401response.setStatus(401);return Result.error("未登錄");}}
}
我們在測試接口的時候,要注意先登錄,然后復制令牌過來后,設置Heager請求頭再加入value的值為令牌,再發送數據請求即可登錄使用成功
多功能:
咱們前面是登陸后的一個功能,那么登陸后有多個功能呢?怎么辦?
答案是 使用攔截器:
使用攔截器后:
我們使用了攔截器的話,就不用controller類下的攔截了,要注釋掉這些攔截功能
編寫攔截器接口:
創建一個interceptors攔截器包,下創建一個LoginInterceptor類,編寫關于登錄的攔截器:
package org.huangyingyuan.interceptors;import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.huangyingyuan.pojo.Result;
import org.huangyingyuan.utils.JwtUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Map;//攔截器(登錄攔截器)@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//令牌驗證String token =request.getHeader("Autorization");//驗證tokentry{//模擬token驗證Map<String, Object> claims = JwtUtil.parseToken(token);//放行return true;}catch (Exception e){//http響應狀態碼為401response.setStatus(401);//不放行return false;}}
}
注冊攔截器接口:
?
在config包下,創建一個WebConfig類【注冊攔截器】:
package org.huangyingyuan.config;import org.huangyingyuan.interceptors.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {//登錄接口(/user/login)和注冊類接口(/user/register)不攔截registry.addInterceptor(loginInterceptor).excludePathPatterns("/user/login", "/user/register");}
}
結果:
1.沒勾選令牌參數配置:
2.勾選了令牌配置:
這樣子就實現了“驗證令牌headers”的相關操作,實現了多頁面跳轉的攔截器操作!
干貨滿滿,點個關注,下期更精彩