Apache Shiro实战指南:入门、进阶与最佳实践

Apache Shiro实战指南:入门、进阶与最佳实践

引言

Apache Shiro 是一个开源的安全框架,用于简化安全相关的事务,如用户认证、授权、加密和会话管理等。本文将为您提供一个从入门到进阶的 Apache Shiro 实战指南,包括基本概念、配置、核心组件以及最佳实践。

入门篇

1. 安装与配置

首先,您需要在项目中添加 Shiro 的依赖。以下是 Maven 中的依赖配置:

org.apache.shiro

shiro-core

1.9.0

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 roles = getRolesFromDatabase(username);

Set permissions = getPermissionsFromDatabase(username);

// 创建 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 getRolesFromDatabase(String username) {

// 从数据库获取角色

return Collections.singleton("user");

}

private Set getPermissionsFromDatabase(String username) {

// 从数据库获取权限

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 getActiveSessions() {

// 获取所有活动会话

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。希望这篇文章对您有所帮助!

相关推荐

苹果用户必看!2025 年 iOS 租号平台 TOP5
365体育靠谱

苹果用户必看!2025 年 iOS 租号平台 TOP5

📅 07-26 👁️ 4281
咪咕灵犀怎么开启语音唤醒 咪咕灵犀语音唤醒开启方法介绍
世界杯-利瓦科维奇扑点 克罗地亚点球淘汰日本进8强
淘宝为什么店铺不能评价?淘宝评价管理在哪?
365账户受到限制怎么办

淘宝为什么店铺不能评价?淘宝评价管理在哪?

📅 08-12 👁️ 7684
刀字开头的成语
365账户受到限制怎么办

刀字开头的成语

📅 07-02 👁️ 7913
为什么总是同一只脚容易崴?如何科学应对?
365账户受到限制怎么办

为什么总是同一只脚容易崴?如何科学应对?

📅 06-30 👁️ 6457