欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Boot與JWT和Shiro整合實(shí)踐步驟(非常詳細(xì)!)

 更新時間:2025年09月03日 09:03:51   作者:拉米醫(yī)生  
這篇文章主要介紹了Spring?Boot與JWT和Shiro整合的相關(guān)資料,將Shiro、Spring Boot和JWT集成在一起,可以大大提高應(yīng)用程序的安全性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

1. Spring Boot基礎(chǔ)介紹

在現(xiàn)代企業(yè)級應(yīng)用開發(fā)中,Spring Boot憑借其輕量級、快速開發(fā)的特性,已經(jīng)成為構(gòu)建微服務(wù)架構(gòu)項(xiàng)目的首選框架。本章將為讀者提供Spring Boot的入門級介紹,旨在幫助讀者快速掌握Spring Boot的基礎(chǔ)知識,并了解其在項(xiàng)目中的具體應(yīng)用。

1.1 Spring Boot簡介

Spring Boot是Spring的一個模塊,它提供了快速構(gòu)建項(xiàng)目的能力。通過“約定優(yōu)于配置”的原則,Spring Boot旨在簡化Spring應(yīng)用的初始搭建以及開發(fā)過程。它通過提供默認(rèn)配置,幫助開發(fā)者避免繁瑣的配置工作,從而專注于業(yè)務(wù)邏輯的實(shí)現(xiàn)。

1.2 Spring Boot的核心特性

  • 自動配置 :Spring Boot能夠自動配置Spring應(yīng)用,只有在特定情況下才需要手動配置。
  • 起步依賴 :通過提供特定的“starter”依賴,簡化了構(gòu)建配置。
  • 內(nèi)嵌Web服務(wù)器 :如Tomcat、Jetty或Undertow,無需部署WAR文件。
  • 監(jiān)控和管理 :提供了一套生產(chǎn)就緒特性,比如指標(biāo)、健康檢查、外部化配置等。

1.3 入門示例

一個典型的Spring Boot應(yīng)用的入口是一個帶有 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應(yīng)用的搭建過程,接下來的內(nèi)容將深入探討如何將Spring Boot與其他技術(shù)棧整合,以實(shí)現(xiàn)更為復(fù)雜的應(yīng)用場景。

2. JWT認(rèn)證機(jī)制解析

2.1 JWT的基本概念和組成

2.1.1 JWT的定義和作用

JSON Web Token(JWT)是一種開放標(biāo)準(zhǔn)(RFC 7519),用于在互聯(lián)網(wǎng)環(huán)境中安全地傳輸信息。它作為一種緊湊的、自包含的方式,使得雙方可以以JSON對象的形式安全傳遞聲明(claims)。JWT通常用于身份驗(yàn)證和信息交換,特別適用于Web API的認(rèn)證場景。

在Web應(yīng)用中,一旦用戶登錄成功,服務(wù)器會生成一個JWT并返回給客戶端,之后客戶端將該JWT存儲在客戶端的瀏覽器或移動設(shè)備中。客戶端每次向服務(wù)器發(fā)送請求時,都需要在HTTP請求的頭信息中附帶該JWT。服務(wù)器通過解析JWT中的信息,就可以驗(yàn)證用戶的身份和訪問權(quán)限。

2.1.2 JWT的結(jié)構(gòu)和特點(diǎn)

JWT由三部分組成:Header(頭部)、Payload(載荷)和Signature(簽名)。這三部分通過點(diǎn)(.)連接在一起,形成一個完整的JWT字符串。

  • Header(頭部) :頭部用于描述關(guān)于該JWT的最基本的信息,例如其類型(即JWT),以及所使用的簽名算法(如HMAC SHA256或者RSA)。
{
  "alg": "HS256",
  "typ": "JWT"
}
  • Payload(載荷) :載荷就是存放有效信息的地方。這些信息包括但不限于發(fā)行者、過期時間、主題等,可以存放一些聲明(claims)。聲明是關(guān)于實(shí)體(通常是用戶)和其他數(shù)據(jù)的聲明,比如用戶ID、用戶名等。
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
  • Signature(簽名) :為了防止信息篡改,對頭部以及載荷的內(nèi)容進(jìn)行簽名。簽名的方法取決于頭部中指定的算法。使用Header中指定的算法對Header和Payload進(jìn)行加密,生成簽名。
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

2.2 JWT的工作原理和優(yōu)勢

2.2.1 認(rèn)證流程詳解

JWT的認(rèn)證流程一般如下:

  1. 用戶登錄到應(yīng)用系統(tǒng),并提供用戶名和密碼。
  2. 應(yīng)用系統(tǒng)驗(yàn)證用戶信息的正確性。
  3. 驗(yàn)證通過后,應(yīng)用系統(tǒng)創(chuàng)建一個JWT,將用戶的身份信息、權(quán)限信息和其他聲明打包到Payload中。
  4. 應(yīng)用系統(tǒng)對JWT的Header和Payload部分使用Base64Url編碼,并使用密鑰對它們進(jìn)行簽名。
  5. 將生成的JWT返回給用戶,用戶將JWT存儲在本地(例如瀏覽器的localStorage或sessionStorage中)。
  6. 用戶在之后的請求中,將JWT作為Authorization header附帶在每個HTTP請求中。
  7. 服務(wù)器收到請求后,提取JWT并驗(yàn)證其簽名,確認(rèn)其有效性和未被篡改。
  8. 如果JWT驗(yàn)證成功,服務(wù)器根據(jù)其中的聲明信息進(jìn)行用戶身份的識別,并授權(quán)訪問資源。

2.2.2 JWT相較于傳統(tǒng)認(rèn)證的優(yōu)勢

JWT相較于傳統(tǒng)的Session認(rèn)證機(jī)制,具有以下優(yōu)勢:

  • 無狀態(tài) :JWT不依賴服務(wù)器存儲認(rèn)證信息,減輕了服務(wù)器壓力。
  • 跨域性 :JWT是純文本,因此可以跨不同的服務(wù)器使用,非常適合分布式系統(tǒng)。
  • 標(biāo)準(zhǔn)化 :遵循開放標(biāo)準(zhǔn),可以跨不同平臺使用,方便前后端分離的項(xiàng)目。
  • 緊湊性 :由于JWT的緊湊性,它可以作為URL的一部分傳輸。

2.3 JWT的安全性分析

2.3.1 JWT的加密和簽名機(jī)制

JWT通過Header和Payload的Base64Url編碼后與簽名組合而成。簽名是為了確保JWT沒有被篡改,其安全性依賴于密鑰的保密性。

  • 加密 :通常用于JWT的加密是為了保護(hù)數(shù)據(jù)的隱私性,避免載荷信息泄露。
  • 簽名 :使用密鑰對Header和Payload進(jìn)行簽名,可以確保數(shù)據(jù)的完整性和來源的可驗(yàn)證性。

2.3.2 JWT的安全漏洞及防范措施

JWT雖然方便,但也存在一些潛在的安全風(fēng)險:

  • 泄露風(fēng)險 :如果JWT存儲在客戶端是暴露的狀態(tài)下,比如localStorage,它可能被惡意JavaScript訪問。可以通過HttpOnly的Cookie來存儲JWT,以減少泄露風(fēng)險。
  • 過期時間設(shè)置 :為JWT設(shè)置較短的過期時間可以減少令牌被盜用的風(fēng)險。
  • 加密和簽名算法 :使用強(qiáng)加密和簽名算法可以增強(qiáng)JWT的安全性。避免使用已被破解的算法,如HS256如果密鑰泄露的話。使用RSA、ECDSA等非對稱加密算法可以提高安全性。

接下來,我們深入探討JWT的加密和簽名機(jī)制以及如何實(shí)現(xiàn)和優(yōu)化這些機(jī)制,確保系統(tǒng)的安全穩(wěn)定運(yùn)行。

3. Shiro安全框架功能概覽

Shiro是Apache軟件基金會的一個開源安全框架,為應(yīng)用程序提供認(rèn)證、授權(quán)、加密和會話管理功能。本章節(jié)將深入探討Shiro的核心架構(gòu)和組件,以及其在企業(yè)級應(yīng)用中的實(shí)踐。

3.1 Shiro核心架構(gòu)和組件

3.1.1 Shiro的架構(gòu)組成

Shiro的架構(gòu)設(shè)計(jì)簡潔而靈活,由三個主要部分組成:Subject、SecurityManager和Realms。

  • Subject : 代表當(dāng)前的用戶,它與當(dāng)前用戶進(jìn)行交互。在應(yīng)用代碼中,Subject通常是指當(dāng)前正在執(zhí)行操作的用戶,或者代表當(dāng)前用戶的線程。
  • SecurityManager : 是Shiro框架的心臟,負(fù)責(zé)處理所有Subject的請求。它管理所有的Subject和其它內(nèi)部安全組件。
  • Realms : 連接外部數(shù)據(jù)源,比如應(yīng)用的數(shù)據(jù)庫。Shiro通過Realms獲取安全相關(guān)的數(shù)據(jù),如用戶角色、權(quán)限等。

3.1.2 主要組件功能解析

Shiro框架還包含其他組件,如 Authentication , Authorization , Session Management , Cryptography 等。這里我們將對每個組件的功能進(jìn)行分析。

  • Authentication (認(rèn)證) : 驗(yàn)證用戶身份的過程。通常通過用戶名和密碼完成。
  • Authorization (授權(quán)) : 確定一個用戶是否有操作某個資源的權(quán)限。
  • Session Management (會話管理) : Shiro提供了完備的會話管理功能,包括創(chuàng)建會話、銷毀會話、會話存儲、并發(fā)性控制等。
  • Cryptography (加密) : 提供加密、哈希和編碼的功能。Shiro通過它來保護(hù)數(shù)據(jù)的安全性。

3.2 Shiro的認(rèn)證與授權(quán)機(jī)制

3.2.1 用戶認(rèn)證流程和策略

Shiro提供了多種認(rèn)證策略,其中基于表單的認(rèn)證是最常見的。用戶輸入用戶名和密碼,Shiro會對這些信息進(jìn)行驗(yàn)證。下面是Shiro的認(rèn)證流程:

  1. 用戶提交用戶名和密碼。
  2. Shiro的 Subject 將認(rèn)證請求提交給 SecurityManager 。
  3. SecurityManager 將請求委托給 AuthenticationStrategy (認(rèn)證策略)。
  4. AuthenticationStrategy 可以進(jìn)行多個Realm認(rèn)證(即多重認(rèn)證)。
  5. 每個Realm將認(rèn)證請求轉(zhuǎn)換成領(lǐng)域?qū)ο螅鬟f給相應(yīng)的用戶數(shù)據(jù)源。
  6. 如果所有Realm的認(rèn)證通過,則認(rèn)證成功,否則失敗。

3.2.2 權(quán)限管理原理和實(shí)踐

權(quán)限管理是Shiro的核心功能之一,它負(fù)責(zé)控制用戶訪問資源的能力。Shiro使用 Roles (角色)和 Permissions (權(quán)限)概念來控制用戶訪問。

  • Role-Based Access Control (RBAC) : 基于角色的訪問控制是Shiro中最常用的一種授權(quán)機(jī)制。
  • Permission-Based Access Control : 基于權(quán)限的訪問控制允許你直接控制用戶對特定操作的權(quán)限,這比RBAC更靈活。

Shiro中的權(quán)限表示可以非常細(xì)粒度,例如:

String permission = "user:create"; // 創(chuàng)建用戶的權(quán)限

通過在應(yīng)用程序中設(shè)置相應(yīng)的角色和權(quán)限,Shiro的授權(quán)機(jī)制能夠有效地管理用戶訪問。

3.3 Shiro在企業(yè)級應(yīng)用中的實(shí)踐

3.3.1 Shiro與Spring Boot的整合

在企業(yè)級應(yīng)用中,Shiro與Spring Boot的整合是常見的需求。以下為整合步驟的簡介:

  1. 添加依賴 : 在pom.xml文件中添加Spring Boot和Shiro的依賴。

    xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency>
  2. 創(chuàng)建配置類 : 創(chuàng)建一個配置類來配置Shiro的Bean。

    java @Configuration public class ShiroConfig { @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 配置Realms等... return securityManager; } // 其他Bean配置... }
  3. 創(chuàng)建Realm : 自定義一個Realm來連接你的用戶數(shù)據(jù)源。

    java @Service public class MyRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 授權(quán)邏輯... } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 認(rèn)證邏輯... } }

3.3.2 Shiro在微服務(wù)架構(gòu)中的應(yīng)用案例

Shiro可以與Spring Cloud微服務(wù)架構(gòu)很好地協(xié)同工作。以下是在微服務(wù)架構(gòu)中應(yīng)用Shiro的一個案例:

  • 服務(wù)網(wǎng)關(guān)集成 : 在服務(wù)網(wǎng)關(guān)層集成Shiro,統(tǒng)一進(jìn)行安全認(rèn)證和授權(quán),可以使用Zuul或Spring Cloud Gateway。
  • 服務(wù)間通信 : 在服務(wù)間通信時,通過Shiro進(jìn)行調(diào)用者身份的認(rèn)證。
  • 分布式會話管理 : Shiro支持分布式會話,可以通過Redis等存儲機(jī)制實(shí)現(xiàn)微服務(wù)間的會話共享。

通過這些實(shí)踐,Shiro能夠支持從單體應(yīng)用到分布式微服務(wù)架構(gòu)中的企業(yè)級應(yīng)用需求。在下一章中,我們將詳細(xì)探討如何配置依賴、如何使用JWT工具類以及如何設(shè)置過濾器鏈和異常處理策略。

4. 整合步驟詳述

4.1 配置依賴和Shiro配置

4.1.1 添加Spring Boot和Shiro的依賴

在Spring Boot項(xiàng)目中整合Shiro和JWT認(rèn)證機(jī)制,首先需要在 pom.xml 文件中添加相關(guān)的依賴。對于Spring Boot項(xiàng)目,通常還需要添加Spring Boot Starter的依賴,以方便項(xiàng)目的構(gòu)建和管理。以下是添加Shiro和JWT相關(guān)依賴的示例代碼:

<!-- 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ù)項(xiàng)目需要選擇合適的JWT庫版本。

4.1.2 Shiro的配置文件詳解

application.properties application.yml 配置文件中,可以進(jìn)行Shiro的配置。下面是一個簡單的配置示例:

# Shiro 配置
shiro.ini=classpath:shiro.ini

對于更復(fù)雜的配置,我們可能需要定義 shiro.ini 文件或使用Spring配置類來配置Shiro。例如,在 shiro.ini 中定義安全策略和認(rèn)證信息:

[main]
# 配置自定義的Realm
myRealm=com.example.MyRealm

# 設(shè)置SecurityManager的Realm
securityManager.realms=$myRealm

# 配置會話管理器
sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager=$sessionManager

# JWT認(rèn)證過濾器配置
authc=org.apache.shiro.web.filter.authc.FormAuthenticationFilter
jwtAuthc=org.example.MyJWTFilter

# 將自定義的JWT認(rèn)證過濾器加入Shiro過濾器鏈
[urls]
# 登錄請求不攔截
/login=authc
# 其他請求需要通過JWT認(rèn)證
/**=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();
}

在配置過程中,要注意權(quán)限管理和認(rèn)證策略的匹配,以及會話管理的合理設(shè)置。對JWT的處理則更多依賴于自定義的過濾器來實(shí)現(xiàn)。

4.2 JWT工具類實(shí)現(xiàn)

4.2.1 JWT的生成和解析

JWT的生成和解析是實(shí)現(xiàn)JWT認(rèn)證機(jī)制的核心步驟。我們需要創(chuàng)建一個工具類來處理這些操作。以下是一個簡單的JWT工具類實(shí)現(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) {
        // 獲取當(dāng)前時間
        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的安全性。在實(shí)際使用中,應(yīng)根據(jù)實(shí)際業(yè)務(wù)需求對JWT的內(nèi)容和過期時間進(jìn)行定制。

4.2.2 JWT工具類的封裝

為了提高工具類的可用性和安全性,我們還需要對其進(jìn)行適當(dāng)?shù)姆庋b,使其易于在應(yīng)用程序中使用。以下是一個封裝示例:

public class JWTUtil {
    // ... JWT的生成和解析方法

    // 獲取當(dāng)前用戶的方法
    public static String getCurrentUser(String jwt, String secret) {
        Claims claims = parseJWT(jwt, secret);
        return claims.getSubject();
    }
}

在這里,我們添加了 getCurrentUser 方法,該方法通過解析JWT獲取當(dāng)前用戶信息。這樣在業(yè)務(wù)邏輯中,我們就可以通過JWT直接獲取當(dāng)前登錄用戶的信息,而無需每次都解析JWT。

4.3 過濾器鏈設(shè)置和異常處理

4.3.1 Shiro的Filter鏈配置

Shiro的過濾器鏈(Filter Chain)允許我們以聲明式的方式配置過濾器,攔截特定請求并進(jìn)行相應(yīng)的處理。通過配置Shiro的 [urls] 部分,可以設(shè)置哪些請求需要進(jìn)行認(rèn)證或授權(quán)。這里是一個配置示例:

@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    shiroFilterFactoryBean.setSecurityManager(securityManager);

    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
    filterChainDefinitionMap.put("/login", "authc"); // 登錄請求,不進(jìn)行JWT認(rèn)證
    filterChainDefinitionMap.put("/**", "jwtAuthc"); // 其他請求進(jìn)行JWT認(rèn)證
    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

    return shiroFilterFactoryBean;
}

配置完成后,所有進(jìn)入 /** 的請求都需要通過名為 jwtAuthc 的過濾器進(jìn)行處理,此過濾器為自定義的JWT認(rèn)證過濾器。

4.3.2 常見異常處理策略

在使用Shiro進(jìn)行認(rèn)證和授權(quán)時,可能會遇到各種異常情況,比如無效的認(rèn)證信息、未授權(quán)訪問等。Shiro提供了默認(rèn)的異常處理器 DefaultWebSecurityManager ,但通常我們會自定義異常處理策略來提供更好的用戶體驗(yàn)。以下是一個異常處理器的示例:

public class MyExceptionHandler implements ExceptionMapper<Exception> {
    @Override
    public String toHTML(Exception e) {
        // 根據(jù)異常類型返回不同的錯誤信息
        if (e instanceof AuthorizationException) {
            return "<p>您沒有權(quán)限訪問此資源。</p>";
        } else if (e instanceof AuthenticationException) {
            return "<p>認(rèn)證失敗,請重新登錄。</p>";
        } else {
            return "<p>服務(wù)器異常,請稍后再試。</p>";
        }
    }
}

通過實(shí)現(xiàn) ExceptionMapper 接口,我們可以在自定義的JWT認(rèn)證過濾器中使用這個異常處理器來返回給用戶更加友好的錯誤提示。

4.4 權(quán)限控制的實(shí)現(xiàn)細(xì)節(jié)

4.4.1 自定義權(quán)限驗(yàn)證

在實(shí)際項(xiàng)目中,通常需要根據(jù)不同的業(yè)務(wù)需求實(shí)現(xiàn)自定義的權(quán)限驗(yàn)證邏輯。在Shiro中,這通常是通過實(shí)現(xiàn) Authorizer 接口或使用 Realm 來完成的。以下是一個簡單的 Realm 實(shí)現(xiàn)示例:

public class MyRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 從principals中獲取當(dāng)前用戶的principal信息
        String username = (String) principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 根據(jù)用戶名查詢用戶權(quán)限信息,然后添加到authorizationInfo中
        List<String> permissions = getPermissionsByUsername(username);
        authorizationInfo.addStringPermissions(permissions);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 這里實(shí)現(xiàn)用戶的登錄驗(yàn)證邏輯,通常會根據(jù)token信息查詢數(shù)據(jù)庫驗(yàn)證用戶名和密碼
        // 如果驗(yàn)證通過,返回一個SimpleAuthenticationInfo對象
        // 如果驗(yàn)證失敗,可以拋出相應(yīng)的AuthenticationException異常
    }
}

doGetAuthorizationInfo 方法中,我們根據(jù)用戶的身份信息(通常是用戶名)來查詢用戶所擁有的權(quán)限,并將其封裝到 AuthorizationInfo 對象中。然后,Shiro會根據(jù)這些權(quán)限信息進(jìn)行授權(quán)。

4.4.2 權(quán)限控制與用戶界面的結(jié)合

實(shí)現(xiàn)權(quán)限控制后,還需要在用戶界面中正確地展示或限制用戶權(quán)限。這通常在控制器層或者服務(wù)層通過調(diào)用Shiro的API來完成。以下是一個簡單的權(quán)限控制示例:

@Controller
public class MyController {
    @RequestMapping("/admin")
    public String adminPage(Principal principal) {
        // 只有擁有admin權(quán)限的用戶才能訪問此頁面
        if (SecurityUtils.getSubject().isPermitted("admin")) {
            return "admin";
        } else {
            return "accessDenied";
        }
    }
}

在這個示例中,只有當(dāng)用戶擁有 admin 權(quán)限時,才能訪問 admin 頁面,否則會跳轉(zhuǎn)到 accessDenied 頁面。通過調(diào)用 SecurityUtils.getSubject().isPermitted() 方法,我們可以檢查用戶是否擁有特定的權(quán)限。

以上內(nèi)容為第四章整合步驟的詳述,從配置Shiro和JWT,到權(quán)限控制和用戶界面的結(jié)合,為讀者提供了一個整合這些技術(shù)點(diǎn)的細(xì)致指南。在下一章節(jié),我們將通過實(shí)際項(xiàng)目的代碼演示整合過程,使讀者更易理解和應(yīng)用這些技術(shù)。

5. 通過實(shí)際項(xiàng)目代碼演示整合過程

5.1 項(xiàng)目結(jié)構(gòu)和代碼概覽

5.1.1 項(xiàng)目整體結(jié)構(gòu)布局

在進(jìn)行實(shí)際項(xiàng)目整合的演示之前,我們首先需要了解項(xiàng)目的基本結(jié)構(gòu)。假設(shè)我們已經(jīng)有了一個基于Spring Boot和Maven的項(xiàng)目結(jié)構(gòu),如下所示:

.
├── 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 關(guān)鍵代碼片段解讀

ShiroConfig.java 中,我們將配置Shiro的默認(rèn)安全策略,包括設(shè)置自定義的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 功能模塊的實(shí)現(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注解來控制資源訪問權(quán)限:

@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í)行

為了確保我們的整合工作正常運(yùn)行,編寫單元測試是至關(guān)重要的。在 MyProjectApplicationTests.java 中,我們可以使用Mockito來模擬服務(wù)層的行為,確保我們的控制器層邏輯正確:

@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相關(guān)的配置類已經(jīng)注冊到Spring容器中,可以解決這個問題。

5.4 安全性和性能優(yōu)化

5.4.1 常見安全問題排查與加固

為了加固安全性,我們需要排查和解決以下問題:

  • 確保敏感信息如密鑰不會暴露在日志或配置文件中。
  • 使用HTTPS來保護(hù)數(shù)據(jù)傳輸過程中的安全。
  • 對輸入數(shù)據(jù)進(jìn)行驗(yàn)證,防止SQL注入或跨站腳本攻擊(XSS)。
  • 對JWT進(jìn)行過期時間設(shè)置和刷新機(jī)制,以減少被盜用的風(fēng)險。

5.4.2 性能優(yōu)化策略及實(shí)施

對于性能優(yōu)化,我們可以采取以下策略:

  • 使用Redis或其他緩存機(jī)制來存儲JWT的黑名單,減少數(shù)據(jù)庫的訪問頻率。
  • 對數(shù)據(jù)庫查詢進(jìn)行優(yōu)化,使用合適的索引和查詢條件。
  • 通過Shiro的會話管理,合理設(shè)置會話的生命周期,減少會話的存儲開銷。
  • 如果系統(tǒng)訪問量較大,考慮引入Shiro的集群支持和會話復(fù)制功能。

通過這些策略,我們能夠確保我們的應(yīng)用在安全性得到保障的同時,也能夠應(yīng)對高并發(fā)場景的需求。

總結(jié)

到此這篇關(guān)于Spring Boot與JWT和Shiro整合實(shí)踐的文章就介紹到這了,更多相關(guān)SpringBoot與JWT和Shiro整合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC獲取HTTP中元素的實(shí)現(xiàn)示例

    SpringMVC獲取HTTP中元素的實(shí)現(xiàn)示例

    本文主要介紹了SpringMVC獲取HTTP中的元素,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • Java線程安全之volatile詳解

    Java線程安全之volatile詳解

    這篇文章主要介紹了Java線程安全之volatile詳解,volatile 的存在,解決了不同內(nèi)存間拷貝的同步問題,在每一次使用或者修改時候,都去原持有內(nèi)存中去拿最新的狀態(tài),需要的朋友可以參考下
    2023-08-08
  • Spring?AI借助全局參數(shù)實(shí)現(xiàn)智能數(shù)據(jù)庫操作與個性化待辦管理

    Spring?AI借助全局參數(shù)實(shí)現(xiàn)智能數(shù)據(jù)庫操作與個性化待辦管理

    這篇文章主要介紹了Spring?AI借助全局參數(shù)實(shí)現(xiàn)智能數(shù)據(jù)庫操作與個性化待辦管理,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-11-11
  • Springboot項(xiàng)目中kaptcha驗(yàn)證碼的使用方式

    Springboot項(xiàng)目中kaptcha驗(yàn)證碼的使用方式

    這篇文章主要介紹了Springboot項(xiàng)目中kaptcha驗(yàn)證碼的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot application.yml和bootstrap.yml的區(qū)別

    SpringBoot application.yml和bootstrap.yml的區(qū)別

    本文主要介紹了SpringBoot application.yml和bootstrap.yml的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • 詳解Springboot如何通過注解實(shí)現(xiàn)接口防刷

    詳解Springboot如何通過注解實(shí)現(xiàn)接口防刷

    本文主要為大家介紹一種極簡潔、靈活通用接口防刷實(shí)現(xiàn)方式、通過在需要防刷的方法加上@Prevent?注解即可實(shí)現(xiàn)短信防刷,感興趣的可以了解一下
    2022-09-09
  • Mybatis-plus數(shù)據(jù)權(quán)限D(zhuǎn)ataPermissionInterceptor實(shí)現(xiàn)

    Mybatis-plus數(shù)據(jù)權(quán)限D(zhuǎn)ataPermissionInterceptor實(shí)現(xiàn)

    本文主要介紹了Mybatis-plus數(shù)據(jù)權(quán)限D(zhuǎn)ataPermissionInterceptor實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Struts2返回json格式數(shù)據(jù)代碼實(shí)例

    Struts2返回json格式數(shù)據(jù)代碼實(shí)例

    這篇文章主要介紹了Struts2返回json格式數(shù)據(jù)代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • 淺談Spring bean 生命周期驗(yàn)證

    淺談Spring bean 生命周期驗(yàn)證

    本篇文章主要介紹了淺談Spring bean 生命周期驗(yàn)證,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • java線程池ExecutorService超時處理小結(jié)

    java線程池ExecutorService超時處理小結(jié)

    使用ExecutorService時,設(shè)置子線程執(zhí)行超時是一個常見需求,本文就來詳細(xì)的介紹一下ExecutorService超時的三種方法,感興趣的可以了解一下
    2024-09-09

最新評論