一.JWT認證流程

認證流程如下:
1.用戶使用賬號和密碼發出post請求;
2.服務器使用私鑰創建一個jwt;
3.服務器回傳這個jwt給瀏覽器;
4.瀏覽器將該jwt串在請求頭中像服務器發送請求;
5.服務器驗證該jwt;
6.回傳回應的資源給瀏覽器
二.SpringBoot整合JWT
新建一個spring boot專案spring-boot-jwt,按照下面步驟操作,
1.pom.xml引入jar包
<!-- 引入jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
2.新建Jwt工具類
Jwt工具類進行token的生成和認證,工具類代碼如下:
/**
* @description: Jwt工具類,生成JWT和認證
* @author: Java碎碎念
*/
public class JwtUtil {
private static final Logger logger = LoggerFactory.getLogger(JwtUtil.class);
/**
* 密鑰
*/
private static final String SECRET = "my_secret";
/**
* 過期時間
**/
private static final long EXPIRATION = 1800L;//單位為秒
/**
* 生成用戶token,設定token超時時間
*/
public static String createToken(User user) {
//過期時間
Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
Map<String, Object> map = new HashMap<>();
map.put("alg", "HS256");
map.put("typ", "JWT");
String token = JWT.create()
.withHeader(map)// 添加頭部
//可以將基本資訊放到claims中
.withClaim("id", user.getId())//userId
.withClaim("userName", user.getUserName())//userName
.withClaim("name", user.getName())//name
.withExpiresAt(expireDate) //超時設定,設定過期的日期
.withIssuedAt(new Date()) //簽發時間
.sign(Algorithm.HMAC256(SECRET)); //SECRET加密
return token;
}
/**
* 校驗token并決議token
*/
public static Map<String, Claim> verifyToken(String token) {
DecodedJWT jwt = null;
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
jwt = verifier.verify(token);
} catch (Exception e) {
logger.error(e.getMessage());
logger.error("token解碼例外");
//解碼例外則拋出例外
return null;
}
return jwt.getClaims();
}
}
3.添加JWT過濾器
JWT過濾器中進行token的校驗和判斷,,token不合法直接回傳,合法則解密資料并把資料放到request中供后續使用,
為了使過濾器生效,需要在啟動類添加注解@ServletComponentScan(basePackages = “com.example.springbootjwt.filter”),
JWT過濾器代碼如下:
/**
* JWT過濾器,攔截 /secure的請求
*/
@Slf4j
@WebFilter(filterName = "JwtFilter", urlPatterns = "/secure/*")
public class JwtFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse response = (HttpServletResponse) res;
response.setCharacterEncoding("UTF-8");
//獲取 header里的token
final String token = request.getHeader("authorization");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
chain.doFilter(request, response);
}
// Except OPTIONS, other request should be checked by JWT
else {
if (token == null) {
response.getWriter().write("沒有token!");
return;
}
Map<String, Claim> userData = JwtUtil.verifyToken(token);
if (userData == null) {
response.getWriter().write("token不合法!");
return;
}
Integer id = userData.get("id").asInt();
String name = userData.get("name").asString();
String userName = userData.get("userName").asString();
//攔截器 拿到用戶資訊,放到request中
request.setAttribute("id", id);
request.setAttribute("name", name);
request.setAttribute("userName", userName);
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
}
}
4.添加登錄Controller
登錄Controller進行登錄操作,登錄成功后生產token并回傳,
登錄Controller代碼如下:
/**
* 登錄Controller
*/
@Slf4j
@RestController
public class LoginController {
static Map<Integer, User> userMap = new HashMap<>();
static {
//模擬資料庫
User user1 = new User(1, "zhangsan", "張三", "123456");
userMap.put(1, user1);
User user2 = new User(2, "lisi", "李四", "123123");
userMap.put(2, user2);
}
/**
* 模擬用戶 登錄
*/
@RequestMapping("/login")
public String login(User user) {
for (User dbUser : userMap.values()) {
if (dbUser.getUserName().equals(user.getUserName()) && dbUser.getPassword().equals(user.getPassword())) {
log.info("登錄成功!生成token!");
String token = JwtUtil.createToken(dbUser);
return token;
}
}
return "";
}
}
5.添加SecureController
SecureController中的請求會被JWT過濾器攔截,合法后才能訪問,
SecureController代碼如下:
/**
* 需要登錄后才能訪問
*/
@Slf4j
@RestController
public class SecureController {
/**
* 查詢 用戶資訊,登錄后才能訪問
*/
@RequestMapping("/secure/getUserInfo")
public String login(HttpServletRequest request) {
Integer id = (Integer) request.getAttribute("id");
String name = request.getAttribute("name").toString();
String userName = request.getAttribute("userName").toString();
return "當前用戶資訊id=" + id + ",name=" + name + ",userName=" + userName;
}
}
三.測驗
測驗分兩步,首先訪問登錄介面,登錄成功后獲取token,然后拿著token在訪問查詢用戶資訊介面,
1.訪問登錄介面
打開PostMan,訪問http://localhost:8080/login?userName=zhangsan&password=123456,登錄成功后介面回傳token,請求成功截圖如下:

2.訪問用戶資訊介面
打開PostMan,訪問http://localhost:8080/secure/getUserInfo,header里需要攜帶token,請求成功截圖如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/286893.html
標籤:其他
上一篇:【JS逆向】之HOOK代碼怎么寫
