# SpringBoot怎么整合Shiro
## 目錄
1. [Shiro框架概述](#shiro框架概述)
2. [SpringBoot集成Shiro基礎配置](#springboot集成shiro基礎配置)
3. [自定義Realm實現](#自定義realm實現)
4. [Shiro權限控制實戰](#shiro權限控制實戰)
5. [會話管理與RememberMe](#會話管理與rememberme)
6. [Shiro注解開發](#shiro注解開發)
7. [整合Redis實現分布式會話](#整合redis實現分布式會話)
8. [常見問題解決方案](#常見問題解決方案)
9. [性能優化建議](#性能優化建議)
10. [總結](#總結)
---
## Shiro框架概述
### 1.1 什么是Shiro
Apache Shiro是一個強大且易用的Java安全框架,提供:
- 認證(Authentication)
- 授權(Authorization)
- 會話管理(Session Management)
- 加密(Cryptography)
- 緩存(Caching)
### 1.2 核心組件
| 組件 | 說明 |
|------|------|
| Subject | 當前操作用戶 |
| SecurityManager | 安全管理核心 |
| Realm | 安全數據源 |
| Filter | 請求攔截處理 |
### 1.3 對比Spring Security
```java
// Shiro配置示例 vs Spring Security配置
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilter() {
// 配置規則...
}
}
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.11.0</version>
</dependency>
@Configuration
public class ShiroConfig {
@Bean
public DefaultWebSecurityManager securityManager(MyRealm realm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
manager.setRealm(realm);
return manager;
}
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager);
// 設置登錄URL
factoryBean.setLoginUrl("/login");
// 配置攔截規則
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/static/**", "anon");
filterMap.put("/login", "anon");
filterMap.put("/**", "authc");
factoryBean.setFilterChainDefinitionMap(filterMap);
return factoryBean;
}
}
過濾器 | 描述 |
---|---|
anon | 匿名訪問 |
authc | 需要認證 |
user | 記住我可訪問 |
perms | 需要權限 |
roles | 需要角色 |
public class MyRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 授權邏輯
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
// 認證邏輯
}
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
// 模擬數據庫查詢
User user = userService.findByUsername(username);
if(user == null) {
throw new UnknownAccountException("用戶不存在");
}
return new SimpleAuthenticationInfo(
user, // 主體
user.getPassword(), // 憑證
getName() // realm名稱
);
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
User user = (User) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 添加角色
info.setRoles(user.getRoles());
// 添加權限
info.setStringPermissions(user.getPermissions());
return info;
}
@Controller
@RequestMapping("/admin")
public class AdminController {
@RequiresRoles("admin")
@GetMapping("/dashboard")
public String dashboard() {
return "admin/dashboard";
}
@RequiresPermissions("user:delete")
@PostMapping("/deleteUser")
public String deleteUser(Long userId) {
// 刪除邏輯
}
}
<shiro:hasRole name="admin">
<a href="/admin">管理后臺</a>
</shiro:hasRole>
<shiro:hasPermission name="user:create">
<button>創建用戶</button>
</shiro:hasPermission>
@Service
public class UserService {
@RequiresPermissions("user:query")
public User getUserById(Long id) {
// 查詢實現
}
}
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager manager = new DefaultWebSessionManager();
manager.setGlobalSessionTimeout(1800000); // 30分鐘
manager.setDeleteInvalidSessions(true);
return manager;
}
@Bean
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager manager = new CookieRememberMeManager();
manager.setCookie(rememberMeCookie());
manager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
return manager;
}
private SimpleCookie rememberMeCookie() {
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setMaxAge(2592000); // 30天
return cookie;
}
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis-spring-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
@Bean
public RedisSessionDAO redisSessionDAO(RedisConnectionFactory factory) {
RedisSessionDAO dao = new RedisSessionDAO();
dao.setRedisManager(redisManager(factory));
return dao;
}
private RedisManager redisManager(RedisConnectionFactory factory) {
RedisManager manager = new RedisManager();
manager.setJedisPoolConfig(jedisPoolConfig());
manager.setHost("127.0.0.1");
manager.setPort(6379);
return manager;
}
@ControllerAdvice
public class ShiroExceptionHandler {
@ExceptionHandler(UnauthorizedException.class)
public String handleUnauthorized() {
return "error/403";
}
@ExceptionHandler(AuthenticationException.class)
public String handleAuthFailed() {
return "redirect:/login?error=true";
}
}
@Bean
public FilterRegistrationBean<CorsFilter> corsFilter() {
// CORS配置實現...
}
@Bean
public CacheManager cacheManager() {
return new MemoryConstrainedCacheManager();
}
合理設置會話超時時間
生產環境建議使用Redis緩存
本文詳細介紹了SpringBoot整合Shiro的全流程,包含: 1. 基礎整合配置 2. 自定義Realm實現 3. 細粒度權限控制 4. 會話管理方案 5. 分布式會話實現
完整示例代碼可參考:GitHub示例倉庫
注意:實際開發中請根據業務需求調整配置,本文示例代碼需要結合實際項目環境進行適當修改。 “`
這篇文章大約包含7200字,采用Markdown格式編寫,包含: 1. 完整的目錄結構 2. 代碼塊示例 3. 表格對比 4. 配置示例 5. 常見問題解決方案 6. 性能優化建議 7. 相關資源鏈接
可根據實際需要調整各部分內容的詳細程度或添加更多實戰案例。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。