引言
Apache Shiro 是一个开源的安全框架,用于简化安全相关的事务,如用户认证、授权、加密和会话管理等。本文将为您提供一个从入门到进阶的 Apache Shiro 实战指南,包括基本概念、配置、核心组件以及最佳实践。
入门篇
1. 安装与配置
首先,您需要在项目中添加 Shiro 的依赖。以下是 Maven 中的依赖配置:
2. 基本概念
Subject:表示当前进行操作的实体,可以是用户、应用程序或系统。
SecurityManager:Shiro 的核心,负责管理内部组件的交互。
Realm:用于获取安全数据,如用户名、密码、角色和权限等。
Session:用户会话,用于存储用户的状态信息。
3. 简单示例
以下是一个简单的 Shiro 应用程序示例:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
public class ShiroExample {
public static void main(String[] args) {
// 初始化 SecurityManager
SecurityManager securityManager = new IniSecurityManagerFactory("classpath:shiro.ini").createSecurityManager();
SecurityUtils.setSecurityManager(securityManager);
// 获取 Subject
Subject subject = SecurityUtils.getSubject();
// 创建认证 token
UsernamePasswordToken token = new UsernamePasswordToken("user", "password");
try {
// 执行认证
subject.login(token);
// 检查是否认证成功
if (subject.isAuthenticated()) {
System.out.println("认证成功");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
进阶篇
1. Realm 实现与自定义
Shiro 的 Realm 用于获取安全数据,您可以根据需要自定义 Realm。以下是一个简单的 Realm 实现:
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class CustomRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
String password = new String((char[]) token.getCredentials());
// 根据用户名从数据库获取密码和盐值
String dbPassword = getPasswordFromDatabase(username);
String salt = getSaltFromDatabase(username);
// 创建 AuthenticationInfo 对象
AuthenticationInfo info = new SimpleAuthenticationInfo(username, dbPassword, salt, this.getName());
return info;
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
// 根据用户名从数据库获取角色和权限
Set
Set
// 创建 AuthorizationInfo 对象
AuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roles);
info.setStringPermissions(permissions);
return info;
}
private String getPasswordFromDatabase(String username) {
// 从数据库获取密码
return "password";
}
private String getSaltFromDatabase(String username) {
// 从数据库获取盐值
return "salt";
}
private Set
// 从数据库获取角色
return Collections.singleton("user");
}
private Set
// 从数据库获取权限
return Collections.singleton("read");
}
}
2. 会话管理
Shiro 提供了会话管理功能,可以用于跟踪用户会话状态。以下是一个简单的会话管理示例:
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionListener;
import org.apache.shiro.session.mgt.SessionRegistry;
import org.apache.shiro.session.mgt.eis.SessionDAO;
public class SessionManagerExample {
public static void main(String[] args) {
// 创建 SessionManager
DefaultSessionManager sessionManager = new DefaultSessionManager();
sessionManager.setSessionListeners(Arrays.asList(new SessionListener() {
@Override
public void onStart(Session session) {
System.out.println("Session started: " + session.getId());
}
@Override
public void onStop(Session session) {
System.out.println("Session stopped: " + session.getId());
}
@Override
public void onExpiration(Session session) {
System.out.println("Session expired: " + session.getId());
}
}));
sessionManager.setSessionDAO(new MockSessionDAO());
// 获取 Session
Session session = sessionManager.createSession();
session.setAttribute("key", "value");
System.out.println("Session attribute: " + session.getAttribute("key"));
}
}
class MockSessionDAO implements SessionDAO {
@Override
public void update(Session session) {
// 更新会话
}
@Override
public void delete(Session session) {
// 删除会话
}
@Override
public Collection
// 获取所有活动会话
return Collections.emptyList();
}
@Override
public Session getSession(String id) {
// 根据 ID 获取会话
return null;
}
@Override
public void deleteSession(String id) {
// 根据 ID 删除会话
}
}
最佳实践
1. 使用 Shiro 的注解进行权限控制
Shiro 提供了一系列注解,用于简化权限控制。以下是一些常用的注解:
@RequiresRoles("role"):检查用户是否具有指定角色。
@RequiresPermissions("permission"):检查用户是否具有指定权限。
@RequiresAuthentication:检查用户是否已认证。
@RequiresGuest:检查用户是否未认证。
2. 使用缓存提高性能
Shiro 支持使用缓存来存储用户信息、角色和权限等数据,从而提高性能。您可以使用 Ehcache、Redis 等缓存框架来实现缓存。
3. 使用 Shiro 的安全过滤器
Shiro 提供了安全过滤器,可以用于拦截请求并进行权限控制。您可以将安全过滤器添加到 Web 应用的过滤器链中。
4. 使用 Shiro 的 Web 支持
Shiro 提供了 Web 支持,可以用于简化 Web 应用中的安全配置。您可以使用 Shiro 的 Web 模块来配置过滤器、拦截器和注解。
总结
Apache Shiro 是一个功能强大的安全框架,可以帮助您轻松实现用户认证、授权和会话管理等安全事务。通过本文的入门、进阶和最佳实践,您应该能够更好地理解和应用 Shiro。希望这篇文章对您有所帮助!