Apache Shiro 全面指南:從入門到高級應用

一、Shiro 概述與核心架構

1.1 什么是 Shiro?

Apache Shiro 是一個強大且易用的 Java 安全框架,它提供了認證(Authentication)、授權(Authorization)、加密(Cryptography)和會話管理(Session Management)等功能。與 Spring Security 相比,Shiro 的設計更加直觀和簡單,同時又不失靈活性。

Shiro 的核心優勢

  • 簡單性:API 設計友好,學習曲線平緩
  • 全面性:覆蓋了應用安全的各個方面
  • 靈活性:可以輕松集成到任何應用環境中
  • 可擴展性:所有組件都支持自定義擴展
  • 跨平臺:不僅限于 Web 應用,也可用于非 Web 環境

1.2 Shiro 核心架構

Shiro 的架構遵循了"分而治之"的設計理念,將安全功能劃分為多個獨立的組件:

+---------------------------------------------------+
|                   Application                     |
+---------------------------------------------------+
|                        Shiro                      |
+-------------------+----------------+--------------+
| Authentication    | Authorization  | Session Mgmt |
+-------------------+----------------+--------------+
| Cryptography      | Cache Mgmt     | Concurrency  |
+-------------------+----------------+--------------+
|                   Realms                          |
+---------------------------------------------------+
|               Security Manager                    |
+---------------------------------------------------+

核心組件解析

  1. Subject:當前操作用戶的安全特定"視圖"
  2. SecurityManager:Shiro 的核心,協調各安全組件
  3. Authenticator:負責認證(登錄)操作
  4. Authorizer:負責授權(訪問控制)決策
  5. SessionManager:管理用戶會話
  6. CacheManager:提供緩存支持以提高性能
  7. Cryptography:提供加密/解密功能
  8. Realms:連接安全數據和 Shiro 的橋梁

二、快速入門:第一個 Shiro 應用

2.1 環境準備

2.1.1 添加 Maven 依賴
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.9.0</version>
</dependency>
<!-- 如果需要Web支持 -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>1.9.0</version>
</dependency>
<!-- 如果需要與Spring集成 -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.9.0</version>
</dependency>
2.1.2 基本配置

創建 shiro.ini 配置文件:

[users]
# 格式:username = password, role1, role2, ...
admin = secret, admin
user1 = password, user
user2 = 123456, user[roles]
# 角色權限定義
admin = *
user = user:read,user:write

2.2 第一個 Shiro 示例

public class Quickstart {public static void main(String[] args) {// 1. 創建SecurityManager工廠Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");// 2. 獲取SecurityManager實例SecurityManager securityManager = factory.getInstance();// 3. 綁定SecurityManager到運行環境SecurityUtils.setSecurityManager(securityManager);// 4. 獲取當前用戶(Subject)Subject currentUser = SecurityUtils.getSubject();// 5. 模擬登錄if (!currentUser.isAuthenticated()) {UsernamePasswordToken token = new UsernamePasswordToken("admin", "secret");try {currentUser.login(token);System.out.println("登錄成功!");} catch (AuthenticationException ae) {System.out.println("登錄失敗: " + ae.getMessage());}}// 6. 權限檢查if (currentUser.hasRole("admin")) {System.out.println("您有admin角色");} else {System.out.println("您沒有admin角色");}// 7. 權限檢查if (currentUser.isPermitted("user:create")) {System.out.println("您有創建用戶的權限");} else {System.out.println("您沒有創建用戶的權限");}// 8. 登出currentUser.logout();}
}

三、Shiro 核心概念深入

3.1 Subject 詳解

Subject 是 Shiro 的核心概念,代表當前與應用交互的實體(用戶、第三方服務等)。

關鍵方法

方法描述
getPrincipal()獲取用戶身份(如用戶名)
getSession()獲取關聯的Session
login()/logout()登錄/登出
isAuthenticated()是否已認證
hasRole()檢查角色
isPermitted()檢查權限

多線程環境中的Subject

// 在另一個線程中獲取Subject
Runnable runnable = () -> {Subject subject = SecurityUtils.getSubject();// 執行操作
};
new Thread(runnable).start();

3.2 SecurityManager 解析

SecurityManager 是 Shiro 架構的核心,負責協調各安全組件。

常見實現

  • DefaultSecurityManager:默認實現
  • DefaultWebSecurityManager:Web應用專用

配置示例

// 創建Realm
Realm realm = new IniRealm("classpath:shiro.ini");// 創建SecurityManager
SecurityManager securityManager = new DefaultSecurityManager(realm);// 配置SecurityManager
SecurityUtils.setSecurityManager(securityManager);

3.3 Realm 深入

Realm 是 Shiro 與應用安全數據的橋梁,負責獲取認證和授權信息。

內置Realm實現

  • IniRealm:從INI文件讀取用戶信息
  • JdbcRealm:從數據庫讀取用戶信息
  • TextConfigurationRealm:內存配置
  • LdapRealm:連接LDAP服務器
  • ActiveDirectoryRealm:連接Active Directory

自定義Realm示例

public class MyRealm extends AuthorizingRealm {// 授權@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {String username = (String) principals.getPrimaryPrincipal();SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();// 添加角色info.addRoles(getRolesFromDB(username));// 添加權限info.addStringPermissions(getPermissionsFromDB(username));return info;}// 認證@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {UsernamePasswordToken upToken = (UsernamePasswordToken) token;String username = upToken.getUsername();// 從數據庫獲取用戶信息User user = getUserFromDB(username);if (user == null) {throw new UnknownAccountException("用戶不存在");}// 返回認證信息return new SimpleAuthenticationInfo(user.getUsername(), // 身份user.getPassword(),  // 憑證getName()           // realm名稱);}// 模擬從數據庫獲取角色private Set<String> getRolesFromDB(String username) {// 實際應用中應從數據庫查詢Set<String> roles = new HashSet<>();if ("admin".equals(username)) {roles.add("admin");roles.add("user");} else {roles.add("user");}return roles;}// 模擬從數據庫獲取權限private Set<String> getPermissionsFromDB(String username) {Set<String> permissions = new HashSet<>();if ("admin".equals(username)) {permissions.add("user:create");permissions.add("user:update");permissions.add("user:delete");permissions.add("user:view");} else {permissions.add("user:view");}return permissions;}// 模擬從數據庫獲取用戶private User getUserFromDB(String username) {if ("admin".equals(username)) {return new User("admin", "secret");} else if ("user".equals(username)) {return new User("user", "password");}return null;}// 簡單的User類private static class User {private String username;private String password;public User(String username, String password) {this.username = username;this.password = password;}public String getUsername() { return username; }public String getPassword() { return password; }}
}

四、Shiro 認證機制

4.1 認證流程詳解

Shiro 的認證流程可以分為以下幾個步驟:

  1. 收集用戶身份/憑證:通常是用戶名/密碼
  2. 提交認證:調用 Subject.login() 方法
  3. Realm 認證:SecurityManager 委托 Realm 進行認證
  4. 成功/失敗處理:返回認證結果

認證流程圖

+---------------+     +----------------+     +-------------------+
|   Subject     | --> | SecurityManager| --> | Authenticator     |
+---------------+     +----------------+     +-------------------+|v+-------------------+|     Realm(s)      |+-------------------+

4.2 多種認證方式

4.2.1 用戶名/密碼認證
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true); // 記住我功能try {currentUser.login(token);// 認證成功
} catch (UnknownAccountException uae) {// 用戶名不存在
} catch (IncorrectCredentialsException ice) {// 密碼錯誤
} catch (LockedAccountException lae) {// 賬戶鎖定
} catch (AuthenticationException ae) {// 其他認證錯誤
}
4.2.2 多Realm認證

配置多個Realm:

[main]
# 定義多個Realm
realm1 = com.example.MyRealm1
realm2 = com.example.MyRealm2# 配置認證策略
authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy# 配置SecurityManager
securityManager.realms = $realm1, $realm2
securityManager.authenticator.authenticationStrategy = $authcStrategy

認證策略

  • FirstSuccessfulStrategy:第一個成功認證的Realm即返回
  • AtLeastOneSuccessfulStrategy:至少一個Realm認證成功
  • AllSuccessfulStrategy:所有Realm都必須認證成功

4.3 記住我功能

Shiro 提供了開箱即用的"記住我"功能:

token.setRememberMe(true);

配置RememberMe

[main]
# Cookie配置
rememberMeManager = org.apache.shiro.web.mgt.CookieRememberMeManager
rememberMeManager.cookie.name = rememberMe
rememberMeManager.cookie.maxAge = 2592000 # 30天securityManager.rememberMeManager = $rememberMeManager

五、Shiro 授權機制

5.1 授權基礎

Shiro 支持三種授權方式:

  1. 編程式:在代碼中檢查權限

    if (subject.hasRole("admin")) {// 有admin角色
    }
    if (subject.isPermitted("user:create")) {// 有創建用戶的權限
    }
    
  2. 注解式:使用Java注解

    @RequiresRoles("admin")
    public void deleteUser() {// 需要admin角色才能執行
    }@RequiresPermissions("user:create")
    public void createUser() {// 需要user:create權限才能執行
    }
    
  3. 標簽式(JSP/GSP):

    <shiro:hasRole name="admin"><!-- 只有admin角色能看到的內容 -->
    </shiro:hasRole><shiro:hasPermission name="user:create"><!-- 有user:create權限能看到的內容 -->
    </shiro:hasPermission>
    

5.2 權限字符串詳解

Shiro 的權限字符串支持通配符和多種格式:

  1. 簡單格式printer:query

    • 第一部分:資源類型(如printer)
    • 第二部分:操作(如query)
  2. 多級格式printer:query:lp7200

    • 第三部分:資源實例ID
  3. 通配符

    • printer:*:對printer的所有操作
    • printer:query:*:查詢所有printer實例
    • *:query:對所有資源的查詢操作

5.3 自定義授權

5.3.1 自定義Permission
public class MyPermission implements Permission {private String resource;private String action;private String instance;public MyPermission(String permissionString) {String[] parts = permissionString.split(":");this.resource = parts.length > 0 ? parts[0] : null;this.action = parts.length > 1 ? parts[1] : null;this.instance = parts.length > 2 ? parts[2] : null;}@Overridepublic boolean implies(Permission p) {if (!(p instanceof MyPermission)) {return false;}MyPermission mp = (MyPermission) p;// 檢查資源是否匹配if (resource != null && !resource.equals(mp.resource)) {return false;}// 檢查操作是否匹配if (action != null && !action.equals(mp.action)) {return false;}// 檢查實例是否匹配if (instance != null && !instance.equals(mp.instance)) {return false;}return true;}
}
5.3.2 自定義RolePermissionResolver
public class MyRolePermissionResolver implements RolePermissionResolver {@Overridepublic Collection<Permission> resolvePermissionsInRole(String roleString) {Set<Permission> permissions = new HashSet<>();if ("admin".equals(roleString)) {permissions.add(new WildcardPermission("user:*"));permissions.add(new WildcardPermission("system:*"));} else if ("user".equals(roleString)) {permissions.add(new WildcardPermission("user:read,update"));}return permissions;}
}

六、Shiro 與 Web 集成

6.1 Shiro Filter 詳解

Shiro 為 Web 應用提供了一系列 Filter:

Filter Name描述
anon匿名訪問,不需要認證
authc需要認證才能訪問
authcBasic基本HTTP認證
logout退出登錄
noSession不創建會話
perms需要特定權限
port需要特定端口
restREST風格權限檢查
roles需要特定角色
ssl需要HTTPS
user需要已認證或記住我

配置示例(web.xml)

<filter><filter-name>ShiroFilter</filter-name><filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter><filter-mapping><filter-name>ShiroFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

配置示例(shiro.ini)

[urls]
/login = authc
/logout = logout
/static/** = anon
/admin/** = authc, roles[admin]
/user/** = authc, perms["user:read"]
/** = user

6.2 會話管理

Shiro 提供了強大的會話管理功能,可以獨立于容器:

Subject currentUser = SecurityUtils.getSubject();
Session session = currentUser.getSession();
session.setAttribute("key", "value");
String value = (String) session.getAttribute("key");

會話配置

[main]
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager# 會話超時時間(毫秒)
sessionManager.globalSessionTimeout = 1800000 # 30分鐘# 會話驗證間隔
sessionManager.sessionValidationInterval = 1800000 # 30分鐘securityManager.sessionManager = $sessionManager

6.3 記住我與SSO

記住我配置

[main]
rememberMeManager = org.apache.shiro.web.mgt.CookieRememberMeManager
rememberMeManager.cipherKey = base64:abc123...= # 加密密鑰
securityManager.rememberMeManager = $rememberMeManager

SSO集成(以CAS為例):

[main]
casRealm = org.apache.shiro.cas.CasRealm
casRealm.casServerUrlPrefix = https://cas.example.org/cas
casRealm.applicationUrl = https://myapp.example.orgsecurityManager.realms = $casRealm

七、Shiro 高級主題

7.1 緩存集成

Shiro 支持多種緩存實現(EhCache、Redis等):

[main]
cacheManager = org.apache.shiro.cache.ehcache.EhCacheManager
cacheManager.cacheManagerConfigFile = classpath:ehcache.xmlsecurityManager.cacheManager = $cacheManager

7.2 加密與哈希

Shiro 提供了強大的加密工具:

// 使用MD5哈希
String hashed = new Md5Hash("password", "salt", 2).toHex();// 使用SHA-256哈希
String hashed = new Sha256Hash("password", "salt", 1024).toBase64();// 使用BCrypt
String hashed = new BCryptPasswordEncoder().encode("password");

配置密碼服務

[main]
credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
credentialsMatcher.hashIterations = 1024
credentialsMatcher.storedCredentialsHexEncoded = truemyRealm = com.example.MyRealm
myRealm.credentialsMatcher = $credentialsMatchersecurityManager.realms = $myRealm

7.3 并發控制

Shiro 可以控制并發登錄:

[main]
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionManager.sessionDAO = $sessionDAO# 配置并發控制
concurrencyFilter = org.apache.shiro.web.filter.session.ConcurrentSessionFilter
concurrencyFilter.sessionManager = $sessionManager
concurrencyFilter.kickoutUrl = /login?kickout=1securityManager.sessionManager = $sessionManager

八、Shiro 與 Spring/Spring Boot 集成

8.1 與 Spring 集成

配置示例

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><property name="loginUrl" value="/login.jsp"/><property name="successUrl" value="/home.jsp"/><property name="unauthorizedUrl" value="/unauthorized.jsp"/><property name="filterChainDefinitions"><value>/static/** = anon/login = authc/logout = logout/** = user</value></property>
</bean><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="myRealm"/>
</bean><bean id="myRealm" class="com.example.MyRealm"><property name="credentialsMatcher" ref="credentialsMatcher"/>
</bean><bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.Sha256CredentialsMatcher"><property name="hashIterations" value="1024"/>
</bean><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

8.2 與 Spring Boot 集成

依賴配置

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-web-starter</artifactId><version>1.9.0</version>
</dependency>

配置類

@Configuration
public class ShiroConfig {@Beanpublic ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();factoryBean.setSecurityManager(securityManager);Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();filterChainDefinitionMap.put("/static/**", "anon");filterChainDefinitionMap.put("/login", "authc");filterChainDefinitionMap.put("/logout", "logout");filterChainDefinitionMap.put("/**", "user");factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);factoryBean.setLoginUrl("/login");factoryBean.setSuccessUrl("/home");factoryBean.setUnauthorizedUrl("/unauthorized");return factoryBean;}@Beanpublic SecurityManager securityManager(Realm realm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(realm);return securityManager;}@Beanpublic Realm realm() {MyRealm realm = new MyRealm();realm.setCredentialsMatcher(credentialsMatcher());return realm;}@Beanpublic CredentialsMatcher credentialsMatcher() {return new Sha256CredentialsMatcher();}@Beanpublic static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}
}

九、Shiro 最佳實踐

9.1 安全最佳實踐

  1. 密碼安全

    • 始終使用加鹽哈希
    • 使用強哈希算法(如SHA-256、BCrypt)
    • 避免使用弱密碼
  2. 會話安全

    • 使用HTTPS保護會話
    • 設置合理的會話超時
    • 防止會話固定攻擊
  3. 權限設計

    • 遵循最小權限原則
    • 使用RBAC(基于角色的訪問控制)模型
    • 定期審查權限分配

9.2 性能優化

  1. 緩存策略

    • 緩存認證和授權信息
    • 使用分布式緩存(如Redis)用于集群環境
  2. 會話管理

    • 對于無狀態API,考慮禁用會話
    • 優化會話持久化策略
  3. Realm優化

    • 批量獲取權限信息
    • 避免重復查詢數據庫

9.3 常見問題解決

  1. ClassCastException

    • 確保Subject綁定到正確的線程
    • 檢查類加載器問題
  2. 權限不生效

    • 檢查權限字符串格式
    • 確認Realm正確配置
    • 檢查緩存是否過期
  3. 會話丟失

    • 檢查集群配置
    • 確認會話持久化配置正確

十、總結

Apache Shiro 作為一個功能全面而又簡單易用的安全框架,為Java應用提供了強大的安全保障。通過本文的學習,我們了解了:

  1. Shiro 的核心概念和架構設計
  2. 認證和授權的實現原理
  3. Web集成和會話管理
  4. 與Spring/Spring Boot的集成
  5. 高級特性和最佳實踐

無論是簡單的Web應用還是復雜的企業級系統,Shiro都能提供合適的安全解決方案。希望本文能成為你Shiro學習之旅的有力參考,幫助你在實際項目中構建更加安全可靠的系統。


PS:如果你在學習過程中遇到問題,別擔心!歡迎在評論區留言,我會盡力幫你解決!😄

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76340.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76340.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76340.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

es 3期 第28節-深入掌握集群組建與集群設置

#### 1.Elasticsearch是數據庫&#xff0c;不是普通的Java應用程序&#xff0c;傳統數據庫需要的硬件資源同樣需要&#xff0c;提升性能最有效的就是升級硬件。 #### 2.Elasticsearch是文檔型數據庫&#xff0c;不是關系型數據庫&#xff0c;不具備嚴格的ACID事務特性&#xff…

Android學習總結之通信篇

一、Binder跨進程通信的底層實現細節&#xff08;掛科率35%&#xff09; 高頻問題&#xff1a;“Binder如何實現一次跨進程方法調用&#xff1f;”   候選人常見錯誤&#xff1a;   僅回答“通過Binder驅動傳輸數據”&#xff0c;缺乏對內存映射和線程調度的描述混淆Binde…

數據結構C語言練習(兩個棧實現隊列)

一、引言 在數據結構的學習中&#xff0c;我們經常會遇到一些有趣的問題&#xff0c;比如如何用一種數據結構去實現另一種數據結構的功能。本文將深入探討 “用棧實現隊列” 這一經典問題&#xff0c;詳細解析解題思路、代碼實現以及每個函數的作用&#xff0c;幫助讀者更好地…

前端如何導入谷歌字體庫

#谷歌字體庫內容豐富&#xff0c;涵蓋上千種多語言支持的字體&#xff0c;學習導入谷歌字體庫來增加網站的閱讀性&#xff0c;是必不可少的一項技能# 1&#xff0c;前往谷歌字體網站 要會魔法&#xff0c;裸連很卡 2&#xff0c; 尋找心儀字體 Googles Fonts下面的filters可…

SnapdragonCamera驍龍相機源碼解析

驍龍相機是高通開發的一個測試系統攝像頭的demo&#xff0c;代碼完善&#xff0c;功能強大。可以配合Camera驅動進行功能聯調。 很多邏輯代碼在CaptureModule.java里。 CaptureModule有8000多行&#xff0c;包羅萬象。 涉及到界面顯示要結合CaptureUI.java 一起來實現。 Ca…

多線程猜數問題

題目&#xff1a;線程 A 生成隨機數&#xff0c;另外兩個線程來猜數&#xff0c;線程 A 可以告訴猜的結果是大還是小&#xff0c;兩個線程都猜對后&#xff0c;游戲結束&#xff0c;編寫代碼完成。 一、Semaphore 多個線程可以同時操作同一信號量&#xff0c;由此實現線程同步…

seq2seq

理解 transformer 中的 encoder decoder 詳細的 transformer 教程見&#xff1a;【極速版 – 大模型入門到進階】Transformer 文章目錄 &#x1f30a; Encoder: 給一排向量輸出另外一排向量&#x1f30a; Encoder vs. Decoder: multi-head attention vs. masked multi-head at…

Proxmox pct 部署ubuntu

pct 前言 PCT(Proxmox Container Tool)是 PVE 中用于管理 Linux 容器(LXC)的命令行工具。通過 PCT,用戶可以執行各種容器管理任務,例如創建新的容器、啟動和停止容器、更新容器、安裝軟件包、導出和導入容器等。PCT 提供了與 Web 界面相同的功能,但通過命令行進行操作,…

Google Play關鍵字優化:關鍵排名因素與實戰策略

如果您準備發布應用程序或開始專注于關鍵字優化&#xff0c;您可能想知道如何向Google Play上的應用程序添加關鍵字。Google Play上的搜索量和排名與App Store不同&#xff0c;而且被索引排名的關鍵字也不同。在此文中&#xff0c;我們將確定Google Play上的關鍵排名因素&#…

Kafka延遲隊列實現分級重試

技術方案 方案背景 Kafka隊列消息消費處理過程中&#xff0c;發生處理異常&#xff0c;需要實現重試機制&#xff0c;并基于重試次數實現不同延遲時間重試方案。 方案介紹 通過實現Kafka延遲隊列來實現消息重試機制。 目標&#xff1a; 支持所有業務場景的延遲重試支持多…

Maven核心配置文件深度解析:pom.xml完全指南

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、全棧領域優質創作者、高級開發工程師、高級信息系統項目管理師、系統架構師&#xff0c;數學與應用數學專業&#xff0c;10年以上多種混合語言開發經驗&#xff0c;從事DICOM醫學影像開發領域多年&#xff0c;熟悉DICOM協議及…

MSTP多域生成樹

協議信息 MSTP 兼容 STP 和 RSTP&#xff0c;既可以快速收斂&#xff0c;又提供了數據轉發的多個冗余路徑&#xff0c;在數據轉發過程中實現 VLAN 數據的負載均衡。 MSTP 可以將一個或多個 VLAN 映射到一個 Instance&#xff08;實例&#xff09;&#xff08;一個或多個 VLAN…

MQTT 服務器(emqx)搭建及使用(一)

一. EMQX 服務器搭建 1.下載EMQX 下載鏈接&#xff1a;Windows | EMQX 文檔 官方手冊 2.下載內容解壓至盤符根目錄 3.進入bin文件夾&#xff0c;在地址欄輸入cmd 4.依次輸入下面命令安裝服務 .\emqx.cmd install .\emqx.cmd console 5.設置自啟動 創建批處理文件&#x…

在Thinkphp中使用JWT 包括JWT是什么,JWT的優勢

首先了解一下什么是JWT JWT 是一種開放標準&#xff08;RFC 7519&#xff09;&#xff0c;用于在各方之間以 JSON 對象形式安全傳輸信息4。其核心特點包括&#xff1a; 結構&#xff1a;由三部分組成&#xff08;Header、Payload、Signature&#xff09;&#xff0c;通過點號…

hackmyvn-casino

arp-scan -l nmap -sS -v 192.168.255.205 目錄掃描 dirsearch -u http://192.168.255.205/ -e * gobuster dir -u http://192.168.255.205 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php -b 301,401,403,404 80端口 隨便注冊一個賬號 玩游戲時的…

圖表配置表增加分析指標字段

在設計報表圖表配置表時&#xff0c;為存儲 同比、環比 這類分析指標&#xff0c;建議通過以下方式定義字段結構和命名&#xff1a; 一、字段設計方案 // 配置表示例結構 interface ChartConfig {id: string; // 唯一標識name: string; // 圖表…

廣州SMT貼片加工廠精密制造工藝解析

內容概要 在電子制造領域&#xff0c;SMT貼片加工技術已成為現代電子產品精密組裝的核心環節。廣州作為華南地區電子產業的重要樞紐&#xff0c;其SMT貼片加工廠通過融合自動化設備與嚴格工藝標準&#xff0c;構建起高效可靠的制造體系。 對于電子產品制造商而言&#xff0c;…

RK3568-適配ov5647攝像頭

硬件原理圖 CAM_GPIO是攝像頭電源控制引腳,連接芯片GPIO4_C2 CAM_LEDON是攝像頭led燈控制引腳,連接芯片GPIO4_C3編寫設備樹 / {ext_cam_clk: external-camera-clock {compatible = "fixed-clock";clock-frequency = <25000000>;clock-output-names = "…

關于 @Autowired 和 @Value 使用 private 字段的警告問題分析與解決方案

問題背景 在使用 Spring 框架進行開發時&#xff0c;我們經常會使用 Autowired 和 Value 注解來進行依賴注入和屬性值注入。然而&#xff0c;當我們將這些注解應用于 private 字段時&#xff0c;IDE&#xff08;如 IntelliJ IDEA&#xff09;可能會顯示警告信息&#xff0c;提…

Flutter 開發環境配置--宇宙級教學!

目錄 一、安裝環境&#xff08;Windows&#xff09;二、Android 創建Flutter項目三、VSCode 搭建環境四、補充 一、安裝環境&#xff08;Windows&#xff09; Flutter SDK 下載 推薦使用中國鏡像站點下載 Flutter SDK&#xff0c;速度更快&#xff1a;中國環境 或者從官網下載…