Shiro配置

过滤器链

@Configuration
@EnableConfigurationProperties(value = {ShiroProperties.class, RedisProperties.class})
public class ShiroAutoConfiguration {


    private ShiroProperties shiroProperties;


    private RedisProperties redisProperties;


    public static final String SHIRO_FILTER_NAME = "shiroFilterFactoryBean";


    public ShiroAutoConfiguration(ShiroProperties shiroProperties, RedisProperties redisProperties) {
        this.shiroProperties = shiroProperties;
        this.redisProperties = redisProperties;
    }


    /**
     * 创建凭证匹配器
     */
    @Bean
    public HashedCredentialsMatcher getHashedCredentialsMatcher() {
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        //注入散列算法名
        matcher.setHashAlgorithmName(shiroProperties.getHashAlgorithmName());
        //注入散列次数
        matcher.setHashIterations(shiroProperties.getHashIterations());
        return matcher;
    }


    /**
     * 创建自定义realm
     * 并注入凭证匹配器
     */
    @Bean
    @ConditionalOnClass(value = {UserRealm.class})
    public UserRealm getUserRealm(HashedCredentialsMatcher matcher) {
        UserRealm userRealm = new UserRealm();
        //注入凭证匹配器
        userRealm.setCredentialsMatcher(matcher);
        return userRealm;
    }


    /**
     * 创建安全管理器
     */
    @Bean
    @ConditionalOnClass(value = DefaultWebSecurityManager.class)
    public DefaultWebSecurityManager getSecurityManager(DefaultWebSessionManager defaultWebSessionManager, UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //注入realm
        securityManager.setRealm(userRealm);
        securityManager.setSessionManager(defaultWebSessionManager);
        return securityManager;
    }


    /**
     * -声明过滤器
     * Shiro 的Web过滤器 id必须和web.xml里面的shiroFilter的 targetBeanName的值一样
     */
    @Bean(value = SHIRO_FILTER_NAME)
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        //注入安全管理器
        bean.setSecurityManager(securityManager);
        //处理用户未认证访问要认证的地址的跳转问题  默认是跳转到shiroProperties.getLoginUrl()现在改成以json串形式返回
        Map<String, Filter> filters = new HashMap<>();
        filters.put("authc", new ShiroLoginFilter());
        bean.setFilters(filters);


        Map<String, String> map = new HashMap<>();
        //配置不拦击的路径
        String[] anonUrls = shiroProperties.getAnonUrls();
        if (anonUrls != null && anonUrls.length > 0) {
            for (String anonUrl : anonUrls) {
                map.put(anonUrl, "anon");
            }
        }
        //配置拦截的路径
        String[] authcUrls = this.shiroProperties.getAuthcUrls();
        if (authcUrls != null && authcUrls.length > 0) {
            for (String authcUrl : authcUrls) {
                map.put(authcUrl, "authc");
            }
        }
        bean.setFilterChainDefinitionMap(map);
        return bean;
    }





    /**
     * sessionManager 里面可以决定sessionDAO
     * @param redisSessionDao
     * defaultWebSessionManager来源com.sxt.system.config.TokenWebSessionManager
     * @return
     */
    @Bean
    public DefaultWebSessionManager defaultWebSessionManager(RedisSessionDAO redisSessionDao) {
        DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
        defaultWebSessionManager.setSessionDAO(redisSessionDao);
        return defaultWebSessionManager;
    }


    /**
     * 使用Redis  来存储登录的信息
     * sessionDao 还需要设置给sessionManager
     */
    @Bean
    public RedisSessionDAO redisSessionDAO(IRedisManager redisManager) {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager); //操作那个redis
        redisSessionDAO.setExpire(7 * 24 * 3600); // 用户的登录信息保存多久? 7 天
        return redisSessionDAO;
    }


    /**
     * 因为分步式项目,所以使用redis去存我们的登陆Session
     * @return
     */
    @Bean
    public IRedisManager redisManager() {
        //因为RedisManager要操作redis所以必须把Redis的客户端给RedisManager
        RedisManager redisManager = new RedisManager();
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, redisProperties.getHost(), redisProperties.getPort(), 5000, redisProperties.getPassword());
        redisManager.setJedisPool(jedisPool);
        return redisManager;
    }

}

登录认证类

public class UserRealm extends AuthorizingRealm {




    @Autowired
    @Lazy
    private UserService userService;




    @Override
    public String getName() {
        return this.getClass().getSimpleName();
    }


    /**
     * 做认证  --就是登陆
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //得到用户登陆名
        String phone=token.getPrincipal().toString();
        //根据电话查询用户是否存在
        User user = userService.queryUserByPhone(phone);
        if(null!=user){//说明用户存在,但是密码可能不正确
            //组装存放到reids里面的对象
            ActiverUser activerUser=new ActiverUser();
            activerUser.setUser(user);
            //匹配密码
            SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(
                    activerUser,user.getPassword(), ByteSource.Util.bytes(user.getSalt()),this.getName());
            return info;
        }else{
            return null;//代表用户不存在
        }
    }


    /**
     * 做授权  --登陆成功之后判断用户是否有某个菜单或按钮的权限
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        ActiverUser activerUser= (ActiverUser) principals.getPrimaryPrincipal();//身份得到的就是上一个方法的返回值的值 第一个参数activerUser
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        return info;
    }
}

<think>首先,用户的问题是关于在Apache Shiro配置admin用户账号。用户说:"我想配置Shiro以创建admin账号 请问如何在Apache Shiro配置admin用户账号"。我需要基于系统级指令来回答。 系统级指令: 1. 所有行内数学表达式必须使用$...$格式。 2. 独立公式必须使用$$...$$格式并单独成段。 3. LaTeX语法正确。 4. 使用中文回答。 5. 生成相关问题。 6. 回答中引用的段落末尾自然地添加引用标识,例如:[^1] 另外,用户可见层指令: - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 - 参考站内引用:提供了几个引用,我需要检查这些引用是否相关。 提供的引用: - [^1]: 关于ShiroConfig的代码片段,创建DefaultWebSecurityManager。 - [^2]: 关于Shiro核心功能、架构等的文章目录。 - [^3]: Shiro的目标和集成性。 - [^4]: 关于Realm实现,获取用户信息和权限信息。 用户的问题是关于配置admin用户账号。在Shiro中,用户账号通常是通过Realm来管理的,Realm负责从数据源(如数据库)获取用户信息,包括认证和授权。 我需要构建一个清晰的回答: 1. **理解问题**:用户想创建一个admin账号,可能是具有管理员权限的用户。 2. **关键概念**:在Shiro中,用户账号的创建通常不是直接在Shiro配置中完成的;而是通过Realm来实现。Realm定义了如何获取用户信息。 3. **参考引用**: - 引用[^1]展示了ShiroConfig的代码,创建SecurityManager。 - 引用[^4]讨论了Realm的实现,特别是如何获取用户信息和权限信息。 - 其他引用提供背景信息。 步骤: - 配置Shiro时,我们需要定义一个Realm。 - 在Realm中,我们可以硬编码admin用户或从数据库加载。 - 然后,在SecurityManager中设置这个Realm。 回答结构: 1. **介绍**:简要解释Shiro中用户账号的管理方式。 2. **步骤**:逐步指导如何配置。 - 创建Realm类。 - 在Realm中定义admin用户。 - 配置Shiro使用这个Realm。 3. **代码示例**:提供Java代码示例,使用Markdown代码块。 4. **解释**:解释代码的关键部分。 5. **生成相关问题**:在最后添加相关问题。 确保使用中文回答。 关于数学表达式:用户的问题不涉及数学,但指令要求所有行内数学表达式使用$...$。既然用户的问题是关于Shiro配置,没有数学内容,我应该避免不必要的数学表达式。只在必要时使用,但这里可能不需要。 生成相关问题:在回答结束时,添加几个相关问题,如示例所示。 引用标识:在回答中,如果引用提供的站内引用,在末尾添加[^n]。例如,如果提到Realm实现,可以引用[^4]。 具体回答: - 在Shiro中,用户账号是通过Realm管理的。我们可以创建一个自定义Realm来定义admin用户。 - 示例:创建一个SimpleAccountRealm或自定义Realm。 - 在Realm的初始化中,添加admin用户及其角色和权限。 - 然后,在Shiro配置中设置这个Realm。 代码示例: - 创建一个类继承AuthorizingRealm或SimpleAccountRealm。 - 覆盖方法或添加用户。 - 在ShiroConfig中创建Realm bean并设置到SecurityManager。 参考引用[^4]:它提到了doGetAuthenticationInfo和doGetAuthorizationInfo方法,这正是我们需要实现的。 最终回答: - 开头:解释过程。 - 步骤1:创建自定义Realm。 - 步骤2:实现方法以定义admin用户。 - 步骤3:配置Shiro使用这个Realm。 - 代码示例。 - 注意事项:如安全考虑,建议从数据库加载而不是硬编码。 - 结尾:生成相关问题。</think>### 如何在Apache Shiro配置admin用户账号 在Apache Shiro配置admin用户账号,核心是通过自定义`Realm`来实现用户认证和授权管理。Realm是Shiro连接用户数据源(如数据库、内存或配置文件)的桥梁。admin账号的创建通常涉及在Realm中定义该用户的凭证(如用户名和密码)以及分配管理员角色和权限。以下是基于Shiro框架的逐步配置指南,参考了Shiro官方文档和最佳实践[^3][^4]。 #### 步骤1: 创建自定义Realm类 首先,定义一个自定义Realm类,继承`AuthorizingRealm`。在该类中,您需要实现两个核心方法: - `doGetAuthenticationInfo()`:处理用户认证(登录),验证用户名和密码。 - `doGetAuthorizationInfo()`:处理用户授权,分配角色和权限。 这里,我们硬编码一个admin用户(用户名`admin`,密码`admin123`),并为其分配管理员角色(`adminRole`)和权限(如`user:manage`)。实际生产环境中,建议从数据库加载用户数据[^4]。 ```java import org.apache.shiro.authc.*; import org.apache.shiro.authz.*; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import java.util.*; public class AdminRealm extends AuthorizingRealm { // 认证方法:验证用户身份 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); char[] password = upToken.getPassword(); // 硬编码admin用户(实际应从数据库查询) if ("admin".equals(username)) { // 参数:用户名、密码(需加密)、Realm名称 return new SimpleAuthenticationInfo(username, "admin123".toCharArray(), getName()); } else { throw new UnknownAccountException("用户不存在"); } } // 授权方法:分配角色和权限 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // 为admin用户添加角色和权限 if ("admin".equals(username)) { Set<String> roles = new HashSet<>(); roles.add("adminRole"); // 添加管理员角色 authorizationInfo.setRoles(roles); Set<String> permissions = new HashSet<>(); permissions.add("user:manage"); // 添加管理权限,如用户管理 permissions.add("system:config"); // 系统配置权限 authorizationInfo.setStringPermissions(permissions); } return authorizationInfo; } } ``` #### 步骤2: 配置Shiro SecurityManager 在Shiro配置类中,创建`SecurityManager`并注入自定义Realm。这里使用Spring Boot风格的配置(基于`@Configuration`),参考了引用[^1]中的示例。确保将自定义Realm设置为SecurityManager的依赖。 ```java import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition; import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ShiroConfig { // 创建自定义Realm Bean @Bean public AdminRealm adminRealm() { return new AdminRealm(); } // 配置SecurityManager,注入Realm @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(adminRealm()); // 设置自定义Realm // 可选:添加缓存或会话管理器配置 return securityManager; } // 配置URL权限规则(例如,保护admin路径) @Bean public ShiroFilterChainDefinition shiroFilterChainDefinition() { DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition(); chainDefinition.addPathDefinition("/admin/**", "authc, roles[adminRole]"); // 需adminRole角色访问 chainDefinition.addPathDefinition("/**", "anon"); // 其他路径匿名访问 return chainDefinition; } } ``` #### 关键解释 - **认证过程**:当用户登录时,Shiro调用`doGetAuthenticationInfo`验证用户名和密码。示例中,admin用户使用密码`admin123`登录[^2][^4]。 - **授权过程**:登录成功后,Shiro通过`doGetAuthorizationInfo`为admin用户分配角色`adminRole`和权限(如`user:manage`),确保其能访问受限资源[^2][^4]。 - **安全建议**: - **避免硬编码密码**:生产环境中,应从数据库或加密存储加载用户信息。可以使用Shiro的`HashedCredentialsMatcher`加密密码,例如使用SHA-256算法[^4]。 - **扩展性**:如需动态管理用户,可集成数据库(如MySQL),并在Realm中查询用户表[^3][^4]。 - **测试admin账号**:启动应用后,访问登录接口(如`/login`),使用用户名`admin`和密码`admin123`即可获得管理员权限。 此配置实现了Shiro的核心目标:灵活集成到各种环境,从简单应用到企业级系统[^3]。如果您的权限模型更复杂,可参考Shiro文档调整角色和权限定义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值