1. 整体架构概览

2. 核心概念详解
Subject(主体)- “用户的代理人”
简单理解: Subject就是当前用户在Shiro中的”代理人”,你通过它来操作用户的认证、授权、会话等。
/**
* Subject = 当前用户的操作界面
* 就像银行柜台的工作人员,你告诉他要做什么,他帮你去办
*/
public interface Subject {
// 认证相关
void login(AuthenticationToken token); // 登录
void logout(); // 登出
boolean isAuthenticated(); // 是否已认证
// 授权相关
boolean hasRole(String role); // 是否有角色
boolean isPermitted(String permission); // 是否有权限
// 会话相关
Session getSession(); // 获取会话
// 身份相关
Object getPrincipal(); // 获取身份标识
PrincipalCollection getPrincipals(); // 获取所有身份
}
// 使用示例
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
currentUser.login(new UsernamePasswordToken("admin", "123456"));
}
if (currentUser.hasRole("admin")) {
// 执行管理员操作
}
if (currentUser.isPermitted("user:create")) {
// 执行创建用户操作
}
SecurityManager(安全管理器)- “总指挥官”
简单理解: SecurityManager是Shiro的大脑,协调所有安全相关的操作。
/**
* SecurityManager = 安全系统的总管
* 就像公司的CEO,不直接干活,但协调各部门工作
*/
public interface SecurityManager {
// 认证管理
Subject login(Subject subject, AuthenticationToken token);
void logout(Subject subject);
// 会话管理
Session start(SessionContext context);
// 创建Subject
Subject createSubject(SubjectContext context);
}
// 配置示例
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm()); // 设置数据源
securityManager.setSessionManager(sessionManager()); // 设置会话管理
securityManager.setCacheManager(cacheManager()); // 设置缓存
return securityManager;
}
Realm(域/领域)- “数据翻译官”
简单理解: Realm是连接Shiro和你的数据源的桥梁,告诉Shiro去哪里找用户信息。
/**
* Realm = 数据源适配器
* 就像翻译官,把你的数据库语言翻译给Shiro听
*/
public abstract class AuthorizingRealm extends AuthenticatingRealm {
// 认证:告诉Shiro这个用户的密码是什么
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token);
// 授权:告诉Shiro这个用户有什么权限
protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
}
// 自定义Realm示例
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
// 认证方法:验证用户身份
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
String username = (String) token.getPrincipal();
// 从数据库查用户
User user = userService.findByUsername(username);
if (user == null) {
return null; // 用户不存在
}
// 返回用户信息给Shiro
return new SimpleAuthenticationInfo(
user.getUsername(), // 用户身份
user.getPassword(), // 密码
getName() // Realm名称
);
}
// 授权方法:获取用户权限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
// 从数据库查权限
Set<String> roles = userService.findRolesByUsername(username);
Set<String> permissions = userService.findPermissionsByUsername(username);
// 返回权限信息给Shiro
SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo();
authInfo.setRoles(roles);
authInfo.setStringPermissions(permissions);
return authInfo;
}
}
Authenticator(认证器)- “身份验证员”
简单理解: Authenticator负责验证用户身份,决定用户是否可以登录。
/**
* Authenticator = 身份检查员
* 就像机场安检,检查你的身份证和机票是否匹配
*/
public interface Authenticator {
AuthenticationInfo authenticate(AuthenticationToken authenticationToken);
}
// 默认实现:ModularRealmAuthenticator
public class ModularRealmAuthenticator extends AbstractAuthenticator {
// 支持多个Realm的认证策略:
// - AtLeastOneSuccessfulStrategy:至少一个成功
// - AllSuccessfulStrategy:全部成功
// - FirstSuccessfulStrategy:第一个成功就停止
}
// 配置示例
@Bean
public Authenticator authenticator() {
ModularRealmAuthenticator authenticator = new ModularRealmAuthenticator();
// 设置认证策略
authenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
// 设置多个Realm
List<Realm> realms = Arrays.asList(
new DatabaseRealm(), // 数据库用户
new LdapRealm(), // LDAP用户
new ApiRealm() // API用户
);
authenticator.setRealms(realms);
return authenticator;
}
Authorizer(授权器)- “权限检查员”
简单理解: Authorizer负责检查用户是否有权限执行某个操作。
/**
* Authorizer = 权限检查员
* 就像门卫,检查你是否有权限进入某个房间
*/
public interface Authorizer {
boolean isPermitted(PrincipalCollection principals, String permission);
boolean hasRole(PrincipalCollection principals, String roleIdentifier);
}
// 使用示例
public class UserController {
@RequiresPermissions("user:create") // 需要创建用户权限
public String createUser() {
return "创建用户成功";
}
@RequiresRoles("admin") // 需要管理员角色
public String adminPanel() {
return "管理员面板";
}
}
SessionManager(会话管理器)- “会话管家”
简单理解: SessionManager管理用户的会话信息,跟踪用户的登录状态。
/**
* SessionManager = 会话管家
* 就像酒店前台,管理客人的入住信息和房间状态
*/
public interface SessionManager {
Session start(SessionContext context);
Session getSession(SessionKey key);
void touch(SessionKey key);
void stop(SessionKey key);
}
// Web环境配置
@Bean
public SessionManager sessionManager() {
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionTimeout(30 * 60 * 1000); // 30分钟超时
sessionManager.setSessionIdCookieEnabled(true);
sessionManager.setSessionIdUrlRewritingEnabled(false);
return sessionManager;
}
CacheManager(缓存管理器)- “记忆助手”
简单理解: CacheManager缓存用户的认证和授权信息,提高系统性能。
/**
* CacheManager = 记忆助手
* 就像大脑的短期记忆,记住最近用过的信息
*/
public interface CacheManager {
<K, V> Cache<K, V> getCache(String name);
}
// Redis缓存配置
@Bean
public CacheManager cacheManager() {
RedisCacheManager cacheManager = new RedisCacheManager();
cacheManager.setRedisManager(redisManager());
cacheManager.setKeyPrefix("shiro:cache:");
cacheManager.setExpire(1800); // 30分钟过期
return cacheManager;
}
3. 认证和授权流程
认证流程(Authentication)- “你是谁?”

授权流程(Authorization)- “你能做什么?”

4. 实际应用示例
完整配置示例
@Configuration
public class ShiroConfig {
// 1. 配置Realm(数据源)
@Bean
public MyRealm myRealm() {
MyRealm realm = new MyRealm();
realm.setCredentialsMatcher(hashedCredentialsMatcher()); // 密码匹配器
realm.setCachingEnabled(true); // 启用缓存
return realm;
}
// 2. 配置SecurityManager(总管)
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm());
securityManager.setSessionManager(sessionManager());
securityManager.setCacheManager(cacheManager());
return securityManager;
}
// 3. 配置过滤器链
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
// 配置URL权限
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/login", "anon"); // 匿名访问
filterChainDefinitionMap.put("/logout", "logout"); // 登出
filterChainDefinitionMap.put("/admin/**", "roles[admin]"); // 需要admin角色
filterChainDefinitionMap.put("/**", "authc"); // 需要认证
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilter;
}
}
业务代码使用
@RestController
public class UserController {
// 登录接口
@PostMapping("/login")
public Result login(@RequestBody LoginRequest request) {
Subject subject = SecurityUtils.getSubject();
try {
UsernamePasswordToken token = new UsernamePasswordToken(
request.getUsername(),
request.getPassword()
);
subject.login(token);
return Result.success("登录成功");
} catch (AuthenticationException e) {
return Result.error("登录失败:" + e.getMessage());
}
}
// 需要权限的接口
@RequiresPermissions("user:view")
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
// 需要角色的接口
@RequiresRoles("admin")
@DeleteMapping("/users/{id}")
public Result deleteUser(@PathVariable Long id) {
userService.delete(id);
return Result.success("删除成功");
}
// 手动检查权限
@GetMapping("/profile")
public Result getProfile() {
Subject subject = SecurityUtils.getSubject();
if (subject.isPermitted("profile:view")) {
String username = (String) subject.getPrincipal();
User user = userService.findByUsername(username);
return Result.success(user);
} else {
return Result.error("无权限访问");
}
}
}
5. 核心概念总结
| 概念 | 作用 | 比喻 |
|---|---|---|
| Subject | 当前用户的代理 | 银行柜台员工 |
| SecurityManager | 安全总协调 | 公司CEO |
| Realm | 数据源适配器 | 翻译官 |
| Authenticator | 身份验证 | 机场安检 |
| Authorizer | 权限检查 | 门卫保安 |
| SessionManager | 会话管理 | 酒店前台 |
| CacheManager | 性能优化 | 大脑记忆 |
