Spring?Boot與JWT和Shiro整合實踐步驟(非常詳細!)
1. Spring Boot基礎介紹
在現(xiàn)代企業(yè)級應用開發(fā)中,Spring Boot憑借其輕量級、快速開發(fā)的特性,已經(jīng)成為構建微服務架構項目的首選框架。本章將為讀者提供Spring Boot的入門級介紹,旨在幫助讀者快速掌握Spring Boot的基礎知識,并了解其在項目中的具體應用。
1.1 Spring Boot簡介
Spring Boot是Spring的一個模塊,它提供了快速構建項目的能力。通過“約定優(yōu)于配置”的原則,Spring Boot旨在簡化Spring應用的初始搭建以及開發(fā)過程。它通過提供默認配置,幫助開發(fā)者避免繁瑣的配置工作,從而專注于業(yè)務邏輯的實現(xiàn)。
1.2 Spring Boot的核心特性
- 自動配置 :Spring Boot能夠自動配置Spring應用,只有在特定情況下才需要手動配置。
- 起步依賴 :通過提供特定的“starter”依賴,簡化了構建配置。
- 內(nèi)嵌Web服務器 :如Tomcat、Jetty或Undertow,無需部署WAR文件。
- 監(jiān)控和管理 :提供了一套生產(chǎn)就緒特性,比如指標、健康檢查、外部化配置等。
1.3 入門示例
一個典型的Spring Boot應用的入口是一個帶有 main 方法的類,通常包含 SpringApplication.run 調(diào)用:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
在 pom.xml 文件中添加Spring Boot的依賴,可以快速開始:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
以上是一個簡單的Spring Boot應用的搭建過程,接下來的內(nèi)容將深入探討如何將Spring Boot與其他技術棧整合,以實現(xiàn)更為復雜的應用場景。
2. JWT認證機制解析
2.1 JWT的基本概念和組成
2.1.1 JWT的定義和作用
JSON Web Token(JWT)是一種開放標準(RFC 7519),用于在互聯(lián)網(wǎng)環(huán)境中安全地傳輸信息。它作為一種緊湊的、自包含的方式,使得雙方可以以JSON對象的形式安全傳遞聲明(claims)。JWT通常用于身份驗證和信息交換,特別適用于Web API的認證場景。
在Web應用中,一旦用戶登錄成功,服務器會生成一個JWT并返回給客戶端,之后客戶端將該JWT存儲在客戶端的瀏覽器或移動設備中??蛻舳嗣看蜗蚍掌靼l(fā)送請求時,都需要在HTTP請求的頭信息中附帶該JWT。服務器通過解析JWT中的信息,就可以驗證用戶的身份和訪問權限。
2.1.2 JWT的結構和特點
JWT由三部分組成:Header(頭部)、Payload(載荷)和Signature(簽名)。這三部分通過點(.)連接在一起,形成一個完整的JWT字符串。
- Header(頭部) :頭部用于描述關于該JWT的最基本的信息,例如其類型(即JWT),以及所使用的簽名算法(如HMAC SHA256或者RSA)。
{
"alg": "HS256",
"typ": "JWT"
}
- Payload(載荷) :載荷就是存放有效信息的地方。這些信息包括但不限于發(fā)行者、過期時間、主題等,可以存放一些聲明(claims)。聲明是關于實體(通常是用戶)和其他數(shù)據(jù)的聲明,比如用戶ID、用戶名等。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
- Signature(簽名) :為了防止信息篡改,對頭部以及載荷的內(nèi)容進行簽名。簽名的方法取決于頭部中指定的算法。使用Header中指定的算法對Header和Payload進行加密,生成簽名。
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
2.2 JWT的工作原理和優(yōu)勢
2.2.1 認證流程詳解
JWT的認證流程一般如下:
- 用戶登錄到應用系統(tǒng),并提供用戶名和密碼。
- 應用系統(tǒng)驗證用戶信息的正確性。
- 驗證通過后,應用系統(tǒng)創(chuàng)建一個JWT,將用戶的身份信息、權限信息和其他聲明打包到Payload中。
- 應用系統(tǒng)對JWT的Header和Payload部分使用Base64Url編碼,并使用密鑰對它們進行簽名。
- 將生成的JWT返回給用戶,用戶將JWT存儲在本地(例如瀏覽器的localStorage或sessionStorage中)。
- 用戶在之后的請求中,將JWT作為Authorization header附帶在每個HTTP請求中。
- 服務器收到請求后,提取JWT并驗證其簽名,確認其有效性和未被篡改。
- 如果JWT驗證成功,服務器根據(jù)其中的聲明信息進行用戶身份的識別,并授權訪問資源。
2.2.2 JWT相較于傳統(tǒng)認證的優(yōu)勢
JWT相較于傳統(tǒng)的Session認證機制,具有以下優(yōu)勢:
- 無狀態(tài) :JWT不依賴服務器存儲認證信息,減輕了服務器壓力。
- 跨域性 :JWT是純文本,因此可以跨不同的服務器使用,非常適合分布式系統(tǒng)。
- 標準化 :遵循開放標準,可以跨不同平臺使用,方便前后端分離的項目。
- 緊湊性 :由于JWT的緊湊性,它可以作為URL的一部分傳輸。
2.3 JWT的安全性分析
2.3.1 JWT的加密和簽名機制
JWT通過Header和Payload的Base64Url編碼后與簽名組合而成。簽名是為了確保JWT沒有被篡改,其安全性依賴于密鑰的保密性。
- 加密 :通常用于JWT的加密是為了保護數(shù)據(jù)的隱私性,避免載荷信息泄露。
- 簽名 :使用密鑰對Header和Payload進行簽名,可以確保數(shù)據(jù)的完整性和來源的可驗證性。
2.3.2 JWT的安全漏洞及防范措施
JWT雖然方便,但也存在一些潛在的安全風險:
- 泄露風險 :如果JWT存儲在客戶端是暴露的狀態(tài)下,比如localStorage,它可能被惡意JavaScript訪問。可以通過HttpOnly的Cookie來存儲JWT,以減少泄露風險。
- 過期時間設置 :為JWT設置較短的過期時間可以減少令牌被盜用的風險。
- 加密和簽名算法 :使用強加密和簽名算法可以增強JWT的安全性。避免使用已被破解的算法,如HS256如果密鑰泄露的話。使用RSA、ECDSA等非對稱加密算法可以提高安全性。
接下來,我們深入探討JWT的加密和簽名機制以及如何實現(xiàn)和優(yōu)化這些機制,確保系統(tǒng)的安全穩(wěn)定運行。
3. Shiro安全框架功能概覽
Shiro是Apache軟件基金會的一個開源安全框架,為應用程序提供認證、授權、加密和會話管理功能。本章節(jié)將深入探討Shiro的核心架構和組件,以及其在企業(yè)級應用中的實踐。
3.1 Shiro核心架構和組件
3.1.1 Shiro的架構組成
Shiro的架構設計簡潔而靈活,由三個主要部分組成:Subject、SecurityManager和Realms。
- Subject : 代表當前的用戶,它與當前用戶進行交互。在應用代碼中,Subject通常是指當前正在執(zhí)行操作的用戶,或者代表當前用戶的線程。
- SecurityManager : 是Shiro框架的心臟,負責處理所有Subject的請求。它管理所有的Subject和其它內(nèi)部安全組件。
- Realms : 連接外部數(shù)據(jù)源,比如應用的數(shù)據(jù)庫。Shiro通過Realms獲取安全相關的數(shù)據(jù),如用戶角色、權限等。
3.1.2 主要組件功能解析
Shiro框架還包含其他組件,如 Authentication , Authorization , Session Management , Cryptography 等。這里我們將對每個組件的功能進行分析。
- Authentication (認證) : 驗證用戶身份的過程。通常通過用戶名和密碼完成。
- Authorization (授權) : 確定一個用戶是否有操作某個資源的權限。
- Session Management (會話管理) : Shiro提供了完備的會話管理功能,包括創(chuàng)建會話、銷毀會話、會話存儲、并發(fā)性控制等。
- Cryptography (加密) : 提供加密、哈希和編碼的功能。Shiro通過它來保護數(shù)據(jù)的安全性。
3.2 Shiro的認證與授權機制
3.2.1 用戶認證流程和策略
Shiro提供了多種認證策略,其中基于表單的認證是最常見的。用戶輸入用戶名和密碼,Shiro會對這些信息進行驗證。下面是Shiro的認證流程:
- 用戶提交用戶名和密碼。
- Shiro的
Subject將認證請求提交給SecurityManager。 SecurityManager將請求委托給AuthenticationStrategy(認證策略)。AuthenticationStrategy可以進行多個Realm認證(即多重認證)。- 每個Realm將認證請求轉換成領域對象,并傳遞給相應的用戶數(shù)據(jù)源。
- 如果所有Realm的認證通過,則認證成功,否則失敗。
3.2.2 權限管理原理和實踐
權限管理是Shiro的核心功能之一,它負責控制用戶訪問資源的能力。Shiro使用 Roles (角色)和 Permissions (權限)概念來控制用戶訪問。
- Role-Based Access Control (RBAC) : 基于角色的訪問控制是Shiro中最常用的一種授權機制。
- Permission-Based Access Control : 基于權限的訪問控制允許你直接控制用戶對特定操作的權限,這比RBAC更靈活。
Shiro中的權限表示可以非常細粒度,例如:
String permission = "user:create"; // 創(chuàng)建用戶的權限
通過在應用程序中設置相應的角色和權限,Shiro的授權機制能夠有效地管理用戶訪問。
3.3 Shiro在企業(yè)級應用中的實踐
3.3.1 Shiro與Spring Boot的整合
在企業(yè)級應用中,Shiro與Spring Boot的整合是常見的需求。以下為整合步驟的簡介:
添加依賴 : 在pom.xml文件中添加Spring Boot和Shiro的依賴。
xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency>
創(chuàng)建配置類 : 創(chuàng)建一個配置類來配置Shiro的Bean。
java @Configuration public class ShiroConfig { @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 配置Realms等... return securityManager; } // 其他Bean配置... }創(chuàng)建Realm : 自定義一個Realm來連接你的用戶數(shù)據(jù)源。
java @Service public class MyRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 授權邏輯... } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 認證邏輯... } }
3.3.2 Shiro在微服務架構中的應用案例
Shiro可以與Spring Cloud微服務架構很好地協(xié)同工作。以下是在微服務架構中應用Shiro的一個案例:
- 服務網(wǎng)關集成 : 在服務網(wǎng)關層集成Shiro,統(tǒng)一進行安全認證和授權,可以使用Zuul或Spring Cloud Gateway。
- 服務間通信 : 在服務間通信時,通過Shiro進行調(diào)用者身份的認證。
- 分布式會話管理 : Shiro支持分布式會話,可以通過Redis等存儲機制實現(xiàn)微服務間的會話共享。
通過這些實踐,Shiro能夠支持從單體應用到分布式微服務架構中的企業(yè)級應用需求。在下一章中,我們將詳細探討如何配置依賴、如何使用JWT工具類以及如何設置過濾器鏈和異常處理策略。
4. 整合步驟詳述
4.1 配置依賴和Shiro配置
4.1.1 添加Spring Boot和Shiro的依賴
在Spring Boot項目中整合Shiro和JWT認證機制,首先需要在 pom.xml 文件中添加相關的依賴。對于Spring Boot項目,通常還需要添加Spring Boot Starter的依賴,以方便項目的構建和管理。以下是添加Shiro和JWT相關依賴的示例代碼:
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.1</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
確保所添加的Shiro版本與Spring Boot版本兼容,并根據(jù)項目需要選擇合適的JWT庫版本。
4.1.2 Shiro的配置文件詳解
在 application.properties 或 application.yml 配置文件中,可以進行Shiro的配置。下面是一個簡單的配置示例:
# Shiro 配置 shiro.ini=classpath:shiro.ini
對于更復雜的配置,我們可能需要定義 shiro.ini 文件或使用Spring配置類來配置Shiro。例如,在 shiro.ini 中定義安全策略和認證信息:
[main] # 配置自定義的Realm myRealm=com.example.MyRealm # 設置SecurityManager的Realm securityManager.realms=$myRealm # 配置會話管理器 sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager securityManager.sessionManager=$sessionManager # JWT認證過濾器配置 authc=org.apache.shiro.web.filter.authc.FormAuthenticationFilter jwtAuthc=org.example.MyJWTFilter # 將自定義的JWT認證過濾器加入Shiro過濾器鏈 [urls] # 登錄請求不攔截 /login=authc # 其他請求需要通過JWT認證 /**=jwtAuthc
對于安全性要求更高的場景,可以使用Java配置類來替代 shiro.ini 文件:
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm());
securityManager.setSessionManager(sessionManager());
return securityManager;
}
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
// 自定義會話ID生成器
sessionManager.setSessionIdGenerator(sessionIdGenerator());
return sessionManager;
}
@Bean
public MyJWTFilter jwtFilter() {
return new MyJWTFilter();
}
在配置過程中,要注意權限管理和認證策略的匹配,以及會話管理的合理設置。對JWT的處理則更多依賴于自定義的過濾器來實現(xiàn)。
4.2 JWT工具類實現(xiàn)
4.2.1 JWT的生成和解析
JWT的生成和解析是實現(xiàn)JWT認證機制的核心步驟。我們需要創(chuàng)建一個工具類來處理這些操作。以下是一個簡單的JWT工具類實現(xiàn)示例:
public class JWTUtil {
private static final SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS256;
private static final String ISSUE_ON_KEY = "issueOn";
private static final String EXP_KEY = "exp";
public static String createJWT(String subject, String issuer, String secret, long ttlMillis) {
// 獲取當前時間
Date now = new Date();
// 獲取過期時間
Date expTime = new Date(now.getTime() + ttlMillis);
// 獲取JWT ID
String jwtId = IdUtils.simpleUUID();
// 創(chuàng)建JWT
JwtBuilder builder = Jwts.builder()
.setId(jwtId)
.setIssuedAt(now)
.setSubject(subject)
.setIssuer(issuer)
.signWith(SIGNATURE_ALGORITHM, secret);
// 添加過期時間
if (expTime != null) {
builder.setExpiration(expTime);
}
return builder.compact();
}
public static Claims parseJWT(String jwt, String secret) {
return Jwts.parser()
.setSigningKey(secret.getBytes())
.parseClaimsJws(jwt)
.getBody();
}
}
在這個工具類中, createJWT 方法用于生成JWT, parseJWT 方法用于解析JWT。 SIGNATURE_ALGORITHM 定義了簽名算法,確保了JWT的安全性。在實際使用中,應根據(jù)實際業(yè)務需求對JWT的內(nèi)容和過期時間進行定制。
4.2.2 JWT工具類的封裝
為了提高工具類的可用性和安全性,我們還需要對其進行適當?shù)姆庋b,使其易于在應用程序中使用。以下是一個封裝示例:
public class JWTUtil {
// ... JWT的生成和解析方法
// 獲取當前用戶的方法
public static String getCurrentUser(String jwt, String secret) {
Claims claims = parseJWT(jwt, secret);
return claims.getSubject();
}
}
在這里,我們添加了 getCurrentUser 方法,該方法通過解析JWT獲取當前用戶信息。這樣在業(yè)務邏輯中,我們就可以通過JWT直接獲取當前登錄用戶的信息,而無需每次都解析JWT。
4.3 過濾器鏈設置和異常處理
4.3.1 Shiro的Filter鏈配置
Shiro的過濾器鏈(Filter Chain)允許我們以聲明式的方式配置過濾器,攔截特定請求并進行相應的處理。通過配置Shiro的 [urls] 部分,可以設置哪些請求需要進行認證或授權。這里是一個配置示例:
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "authc"); // 登錄請求,不進行JWT認證
filterChainDefinitionMap.put("/**", "jwtAuthc"); // 其他請求進行JWT認證
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
配置完成后,所有進入 /** 的請求都需要通過名為 jwtAuthc 的過濾器進行處理,此過濾器為自定義的JWT認證過濾器。
4.3.2 常見異常處理策略
在使用Shiro進行認證和授權時,可能會遇到各種異常情況,比如無效的認證信息、未授權訪問等。Shiro提供了默認的異常處理器 DefaultWebSecurityManager ,但通常我們會自定義異常處理策略來提供更好的用戶體驗。以下是一個異常處理器的示例:
public class MyExceptionHandler implements ExceptionMapper<Exception> {
@Override
public String toHTML(Exception e) {
// 根據(jù)異常類型返回不同的錯誤信息
if (e instanceof AuthorizationException) {
return "<p>您沒有權限訪問此資源。</p>";
} else if (e instanceof AuthenticationException) {
return "<p>認證失敗,請重新登錄。</p>";
} else {
return "<p>服務器異常,請稍后再試。</p>";
}
}
}
通過實現(xiàn) ExceptionMapper 接口,我們可以在自定義的JWT認證過濾器中使用這個異常處理器來返回給用戶更加友好的錯誤提示。
4.4 權限控制的實現(xiàn)細節(jié)
4.4.1 自定義權限驗證
在實際項目中,通常需要根據(jù)不同的業(yè)務需求實現(xiàn)自定義的權限驗證邏輯。在Shiro中,這通常是通過實現(xiàn) Authorizer 接口或使用 Realm 來完成的。以下是一個簡單的 Realm 實現(xiàn)示例:
public class MyRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 從principals中獲取當前用戶的principal信息
String username = (String) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 根據(jù)用戶名查詢用戶權限信息,然后添加到authorizationInfo中
List<String> permissions = getPermissionsByUsername(username);
authorizationInfo.addStringPermissions(permissions);
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 這里實現(xiàn)用戶的登錄驗證邏輯,通常會根據(jù)token信息查詢數(shù)據(jù)庫驗證用戶名和密碼
// 如果驗證通過,返回一個SimpleAuthenticationInfo對象
// 如果驗證失敗,可以拋出相應的AuthenticationException異常
}
}
在 doGetAuthorizationInfo 方法中,我們根據(jù)用戶的身份信息(通常是用戶名)來查詢用戶所擁有的權限,并將其封裝到 AuthorizationInfo 對象中。然后,Shiro會根據(jù)這些權限信息進行授權。
4.4.2 權限控制與用戶界面的結合
實現(xiàn)權限控制后,還需要在用戶界面中正確地展示或限制用戶權限。這通常在控制器層或者服務層通過調(diào)用Shiro的API來完成。以下是一個簡單的權限控制示例:
@Controller
public class MyController {
@RequestMapping("/admin")
public String adminPage(Principal principal) {
// 只有擁有admin權限的用戶才能訪問此頁面
if (SecurityUtils.getSubject().isPermitted("admin")) {
return "admin";
} else {
return "accessDenied";
}
}
}
在這個示例中,只有當用戶擁有 admin 權限時,才能訪問 admin 頁面,否則會跳轉到 accessDenied 頁面。通過調(diào)用 SecurityUtils.getSubject().isPermitted() 方法,我們可以檢查用戶是否擁有特定的權限。
以上內(nèi)容為第四章整合步驟的詳述,從配置Shiro和JWT,到權限控制和用戶界面的結合,為讀者提供了一個整合這些技術點的細致指南。在下一章節(jié),我們將通過實際項目的代碼演示整合過程,使讀者更易理解和應用這些技術。
5. 通過實際項目代碼演示整合過程
5.1 項目結構和代碼概覽
5.1.1 項目整體結構布局
在進行實際項目整合的演示之前,我們首先需要了解項目的基本結構。假設我們已經(jīng)有了一個基于Spring Boot和Maven的項目結構,如下所示:
. ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── example │ │ │ └── myproject │ │ │ ├── MyProjectApplication.java │ │ │ ├── config │ │ │ │ ├── SecurityConfig.java │ │ │ │ └── ShiroConfig.java │ │ │ ├── controller │ │ │ │ ├── UserController.java │ │ │ │ └── ResourceController.java │ │ │ ├── service │ │ │ │ ├── UserService.java │ │ │ │ └── ResourceService.java │ │ │ ├── model │ │ │ │ ├── User.java │ │ │ │ └── Resource.java │ │ │ └── repository │ │ │ ├── UserRepository.java │ │ │ └── ResourceRepository.java │ │ └── resources │ │ ├── application.properties │ │ └── static │ └── test │ └── java │ └── com │ └── example │ └── myproject │ └── MyProjectApplicationTests.java └── pom.xml
5.1.2 關鍵代碼片段解讀
在 ShiroConfig.java 中,我們將配置Shiro的默認安全策略,包括設置自定義的Realm和啟用注解支持:
@Configuration
public class ShiroConfig {
@Bean
public SecurityManager securityManager(Realm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
@Bean
public Realm realm() {
return new CustomRealm();
}
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
shiroFilter.setLoginUrl("/login");
shiroFilter.setUnauthorizedUrl("/403");
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "authc");
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilter;
}
// Other beans and configurations...
}
5.2 功能模塊的實現(xiàn)
5.2.1 用戶登錄模塊
在 UserController.java 中,我們將編寫處理用戶登錄請求的邏輯:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
// Authenticate user
User user = userService.authenticateUser(loginRequest.getUsername(), loginRequest.getPassword());
if (user != null) {
// Create JWT token and send it back to the user
String token = JwtUtil.createToken(user);
return ResponseEntity.ok(new JwtResponse(token));
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Invalid credentials");
}
}
}
5.2.2 資源訪問控制模塊
在 ResourceController.java 中,我們將演示如何使用Shiro注解來控制資源訪問權限:
@RestController
@RequestMapping("/resources")
public class ResourceController {
@GetMapping("/{id}")
@RequiresPermissions("resource:view")
public ResponseEntity<?> viewResource(@PathVariable Long id) {
// Fetch the resource and return it
Resource resource = resourceService.findById(id);
return ResponseEntity.ok(resource);
}
@PostMapping("/create")
@RequiresRoles("admin")
public ResponseEntity<?> createResource(@RequestBody Resource resource) {
// Create a new resource
Resource createdResource = resourceService.createResource(resource);
return ResponseEntity.ok(createdResource);
}
}
5.3 測試和調(diào)試
5.3.1 單元測試的編寫與執(zhí)行
為了確保我們的整合工作正常運行,編寫單元測試是至關重要的。在 MyProjectApplicationTests.java 中,我們可以使用Mockito來模擬服務層的行為,確保我們的控制器層邏輯正確:
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyProjectApplicationTests {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
public void testLoginSuccess() throws Exception {
User mockUser = new User(...);
when(userService.authenticateUser(anyString(), anyString())).thenReturn(mockUser);
mockMvc.perform(post("/user/login")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"username\":\"user\", \"password\":\"pass\"}"))
.andExpect(status().isOk());
}
}
5.3.2 調(diào)試過程中遇到的問題及解決方案
在測試過程中,我們可能遇到了 JwtUtil.createToken 方法無法調(diào)用的情況,原因可能是依賴注入沒有正確配置。在 JwtUtil 類上添加 @Component 注解,并確保JWT相關的配置類已經(jīng)注冊到Spring容器中,可以解決這個問題。
5.4 安全性和性能優(yōu)化
5.4.1 常見安全問題排查與加固
為了加固安全性,我們需要排查和解決以下問題:
- 確保敏感信息如密鑰不會暴露在日志或配置文件中。
- 使用HTTPS來保護數(shù)據(jù)傳輸過程中的安全。
- 對輸入數(shù)據(jù)進行驗證,防止SQL注入或跨站腳本攻擊(XSS)。
- 對JWT進行過期時間設置和刷新機制,以減少被盜用的風險。
5.4.2 性能優(yōu)化策略及實施
對于性能優(yōu)化,我們可以采取以下策略:
- 使用Redis或其他緩存機制來存儲JWT的黑名單,減少數(shù)據(jù)庫的訪問頻率。
- 對數(shù)據(jù)庫查詢進行優(yōu)化,使用合適的索引和查詢條件。
- 通過Shiro的會話管理,合理設置會話的生命周期,減少會話的存儲開銷。
- 如果系統(tǒng)訪問量較大,考慮引入Shiro的集群支持和會話復制功能。
通過這些策略,我們能夠確保我們的應用在安全性得到保障的同時,也能夠應對高并發(fā)場景的需求。
總結
到此這篇關于Spring Boot與JWT和Shiro整合實踐的文章就介紹到這了,更多相關SpringBoot與JWT和Shiro整合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring?AI借助全局參數(shù)實現(xiàn)智能數(shù)據(jù)庫操作與個性化待辦管理
這篇文章主要介紹了Spring?AI借助全局參數(shù)實現(xiàn)智能數(shù)據(jù)庫操作與個性化待辦管理,本文給大家介紹的非常詳細,需要的朋友可以參考下2024-11-11
SpringBoot application.yml和bootstrap.yml的區(qū)別
本文主要介紹了SpringBoot application.yml和bootstrap.yml的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04
詳解Springboot如何通過注解實現(xiàn)接口防刷
本文主要為大家介紹一種極簡潔、靈活通用接口防刷實現(xiàn)方式、通過在需要防刷的方法加上@Prevent?注解即可實現(xiàn)短信防刷,感興趣的可以了解一下2022-09-09
Mybatis-plus數(shù)據(jù)權限DataPermissionInterceptor實現(xiàn)
本文主要介紹了Mybatis-plus數(shù)據(jù)權限DataPermissionInterceptor實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07
Struts2返回json格式數(shù)據(jù)代碼實例
這篇文章主要介紹了Struts2返回json格式數(shù)據(jù)代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-04-04

