手动阀

Good Luck To You!

Apache Shiro 使用手册(四) Realm 实现

Apache Shiro 是一个强大且灵活的 Java 安全框架,用于处理身份验证、授权、会话管理和加密,在 Shiro 中,Realm 是核心组件之一,它负责与数据源(如数据库、LDAP 等)进行交互以获取用户信息和权限数据。

本手册将介绍如何实现自定义 Realm,以便更好地理解 Shiro 的工作原理。

什么是 Realm?

Realm 是 Shiro 中的一个接口,定义了如何获取用户的身份信息和权限数据,Shiro 提供了一些内置的 Realm 实现,例如IniRealmJdbcRealmLdapRealm 等,但在实际项目中,我们通常需要自定义 Realm 来满足特定的需求。

实现自定义 Realm

要实现自定义 Realm,我们需要继承AuthorizingRealm 类并重写其方法,以下是一个简单的示例:

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
public class MyCustomRealm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 获取当前登录的用户
        String username = (String) principals.getPrimaryPrincipal();
        // 根据用户名从数据库或其他数据源获取角色和权限信息
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        // 添加角色
        authorizationInfo.addRole("admin");
        // 添加权限
        authorizationInfo.addStringPermission("user:read");
        return authorizationInfo;
    }
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 获取基于用户名和密码的令牌
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = new String(upToken.getPassword());
        // 从数据库或其他数据源获取用户信息
        // 这里假设用户名为 "admin",密码为 "password"
        if ("admin".equals(username)) {
            return new SimpleAuthenticationInfo(username, password, getName());
        } else {
            throw new UnknownAccountException("用户名或密码错误");
        }
    }
}

配置 Shiro

在 Shiro 配置文件中,我们需要指定自定义的 Realm,以下是一个使用shiro.ini 文件的配置示例:

[main]
myCustomRealm = com.example.MyCustomRealm
securityManager.realms = $myCustomRealm

或者,如果你使用的是 Spring Boot,可以在配置类中进行配置:

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ShiroConfig {
    @Bean
    public MyCustomRealm myCustomRealm() {
        return new MyCustomRealm();
    }
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myCustomRealm());
        return securityManager;
    }
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 配置过滤器链
        return shiroFilterFactoryBean;
    }
}

测试自定义 Realm

我们可以编写一个简单的测试用例来验证自定义 Realm 是否工作正常:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.junit.Assert;
import org.junit.Test;
public class MyCustomRealmTest {
    @Test
    public void testLogin() {
        // 设置安全管理器
        SecurityUtils.setSecurityManager(new DefaultWebSecurityManager(new MyCustomRealm()));
        Subject subject = SecurityUtils.getSubject();
        // 创建用户名/密码令牌
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "password");
        try {
            // 执行登录操作
            subject.login(token);
            // 检查是否认证成功
            Assert.assertTrue(subject.isAuthenticated());
            // 检查是否有特定角色
            Assert.assertTrue(subject.hasRole("admin"));
            // 检查是否有特定权限
            Assert.assertTrue(subject.isPermitted("user:read"));
        } catch (AuthenticationException e) {
            e.printStackTrace();
            Assert.fail("登录失败");
        } finally {
            // 注销登录
            subject.logout();
        }
    }
}

通过以上步骤,你可以实现一个自定义的 Realm,并将其集成到 Shiro 的安全框架中,希望这个指南对你有所帮助!

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

Copyright Your WebSite.Some Rights Reserved.