Spring Boot整合JWT實(shí)現(xiàn)認(rèn)證與授權(quán)的項(xiàng)目實(shí)踐
概述
JSON Web Token (JWT) 是一種開放標(biāo)準(zhǔn) (RFC 7519),它定義了一種緊湊且自包含的方式,用于在各方之間安全地傳輸信息。在Web應(yīng)用中,JWT常用于身份驗(yàn)證和信息交換。
依賴配置
首先需要在項(xiàng)目中添加JWT依賴:
<!-- JWT依賴 --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>
JWT工具類封裝
我們創(chuàng)建一個(gè)JwtUtil
工具類來封裝JWT的生成、解析和驗(yàn)證邏輯:
package com.bookstore.utils; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; @Component public class JwtUtil { private static final String SECRET_KEY = "bookstore_secret_key"; private static final long EXPIRATION_TIME = 24 * 60 * 60 * 1000; // 24小時(shí) // 生成JWT令牌 public String generateToken(Integer userId, String role) { Map<String, Object> claims = new HashMap<>(); claims.put("userId", userId); claims.put("role", role); return Jwts.builder() .setClaims(claims) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } // 解析JWT令牌 public Claims parseToken(String token) { return Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); } // 驗(yàn)證JWT令牌 public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } }
JWT攔截器實(shí)現(xiàn)
創(chuàng)建攔截器來驗(yàn)證請求中的JWT令牌:
package com.bookstore.config; import com.bookstore.utils.JwtUtil; import io.jsonwebtoken.Claims; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class JwtInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { // 放行OPTIONS請求 if ("OPTIONS".equals(request.getMethod())) { return true; } // 從請求頭獲取token String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { token = token.substring(7); if (jwtUtil.validateToken(token)) { Claims claims = jwtUtil.parseToken(token); // 將用戶信息存入request屬性中 request.setAttribute("userId", claims.get("userId")); request.setAttribute("role", claims.get("role")); return true; } } response.setStatus(401); return false; } }
MVC配置
配置攔截器并設(shè)置攔截路徑:
package com.bookstore.config; 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 { @Autowired private JwtInterceptor jwtInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor) .addPathPatterns("/**") // 攔截所有路徑 .excludePathPatterns( // 排除路徑 "/login", "/register", "/swagger-resources/**", "/webjars/**", "/v3/api-docs/**", "/swagger-ui.html/**", "/error", "/favicon.ico", "doc.html", "/logout", "/static/**", "/carousel/list", "/book/new", "/v2/api-docs" ); } }
使用示例
登錄時(shí)生成令牌
在登錄成功后生成JWT令牌并返回給客戶端:
String token = jwtUtil.generateToken(foundUser.getId(), foundUser.getRole());
基礎(chǔ)控制器
創(chuàng)建基礎(chǔ)控制器方便獲取已認(rèn)證的用戶信息:
import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; public class BaseController { @Autowired protected HttpServletRequest request; // 獲取當(dāng)前用戶ID protected Integer getCurrentUserId() { return (Integer) request.getAttribute("userId"); } // 獲取當(dāng)前用戶角色 protected String getCurrentUserRole() { return (String) request.getAttribute("role"); } // 檢查是否是管理員 protected boolean isAdmin() { return "admin".equals(getCurrentUserRole()); } // 檢查是否是普通用戶 protected boolean isUser() { return "user".equals(getCurrentUserRole()); } }
其他控制器可以繼承BaseController
來方便地獲取用戶信息:
@RestController @RequestMapping("/api/books") public class BookController extends BaseController { @GetMapping("/{id}") public ResponseEntity<Book> getBook(@PathVariable Integer id) { if (isAdmin()) { // 管理員特有邏輯 } // 其他邏輯... } }
總結(jié)
- JWT工具類:封裝了令牌的生成、解析和驗(yàn)證邏輯
- 攔截器:自動(dòng)驗(yàn)證請求中的JWT令牌并提取用戶信息
- MVC配置:靈活配置需要攔截和放行的路徑
- 基礎(chǔ)控制器:提供便捷的方法獲取當(dāng)前用戶信息
這種實(shí)現(xiàn)方式具有以下優(yōu)點(diǎn):
- 無狀態(tài)認(rèn)證,服務(wù)端不需要存儲會話信息
- 跨域支持良好
- 可以方便地?cái)y帶用戶信息
- 適合分布式系統(tǒng)
在實(shí)際項(xiàng)目中,可以根據(jù)需求調(diào)整令牌的有效期、密鑰的存儲方式(如從配置中心獲?。┮约案?xì)的權(quán)限控制邏輯。
到此這篇關(guān)于Spring Boot整合JWT實(shí)現(xiàn)認(rèn)證與授權(quán)的項(xiàng)目實(shí)踐的文章就介紹到這了,更多相關(guān)Spring Boot JWT認(rèn)證與授權(quán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Spring Boot實(shí)戰(zhàn)之Filter實(shí)現(xiàn)使用JWT進(jìn)行接口認(rèn)證
- Vue+Jwt+SpringBoot+Ldap完成登錄認(rèn)證的示例代碼
- Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解
- SpringBoot整合SpringSecurity和JWT和Redis實(shí)現(xiàn)統(tǒng)一鑒權(quán)認(rèn)證
- SpringBoot使用Jwt處理跨域認(rèn)證問題的教程詳解
- 詳解SpringBoot如何使用JWT實(shí)現(xiàn)身份認(rèn)證和授權(quán)
- 利用Springboot實(shí)現(xiàn)Jwt認(rèn)證的示例代碼
- springboot+jwt實(shí)現(xiàn)token登陸權(quán)限認(rèn)證的實(shí)現(xiàn)
- SpringBoot整合SpringSecurity實(shí)現(xiàn)JWT認(rèn)證的項(xiàng)目實(shí)踐
相關(guān)文章
MyBatis-Plus詳解(環(huán)境搭建、關(guān)聯(lián)操作)
MyBatis-Plus 是一個(gè) MyBatis 的增強(qiáng)工具,在 MyBatis 的基礎(chǔ)上只做增強(qiáng)不做改變,為簡化開發(fā)、提高效率而生,今天通過本文給大家介紹MyBatis-Plus環(huán)境搭建及關(guān)聯(lián)操作,需要的朋友參考下吧2022-09-09如何解決freemarker靜態(tài)化生成html頁面亂碼的問題
這篇文章主要介紹了如何解決freemarker靜態(tài)化生成html頁面亂碼的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01SpringBoot項(xiàng)目中定時(shí)器的實(shí)現(xiàn)示例
在Spring?Boot項(xiàng)目中,你可以使用Spring框架提供的@Scheduled注解來編寫定時(shí)任務(wù),本文就來介紹一下SpringBoot項(xiàng)目中定時(shí)器的實(shí)現(xiàn),感興趣的可以了解一下2023-11-11java中建立0-10m的消息(字符串)實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava中建立0-10m的消息(字符串)實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05SpringBoot集成Solr實(shí)現(xiàn)全文檢索功能
solr是一個(gè)現(xiàn)成的全文檢索引擎系統(tǒng), 放入tomcat下可以獨(dú)立運(yùn)行, 對外通過http協(xié)議提供全文檢索服務(wù),這篇文章給大家介紹了SpringBoot集成Solr實(shí)現(xiàn)全文檢索功能,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-03-03Java實(shí)現(xiàn)十進(jìn)制與二進(jìn)制互轉(zhuǎn)的示例詳解
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)十進(jìn)制與二進(jìn)制的互轉(zhuǎn),文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Java有一定幫助,需要的可以參考一下2022-11-11@Value設(shè)置默認(rèn)值后,獲取不到配置值的原因分析
這篇文章主要介紹了@Value設(shè)置默認(rèn)值后,獲取不到配置值的原因,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07