springBoot集成shiro实现权限刷新

 更新时间:2024年11月05日 09:48:08   作者:利瑞华  
在SpringBoot项目中集成Shiro进行权限管理,包括基础配置引入依赖、创建Shiro配置类以及用户认证与授权实现,具有一定的参考价值,感兴趣的可以了解一下

一、Spring Boot 集成 Shiro 基础配置

引入依赖
在 Spring Boot 项目的pom.xml(如果是 Maven 项目)中添加 Shiro 相关依赖,例如:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring-boot-starter</artifactId>
    <version>1.7.1</version>
</dependency>

这里的版本号可以根据实际需求进行调整。

创建 Shiro 配置类
创建一个配置类,比如ShiroConfig,用于配置 Shiro 的核心组件,如安全管理器(SecurityManager)、过滤器链(FilterChain)等。

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroWebAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@ImportAutoConfiguration({ShiroAutoConfiguration.class, ShiroWebAutoConfiguration.class})
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置安全管理器,后续创建并注入
        shiroFilterFactoryBean.setSecurityManager(securityManager());

        // 配置过滤器链
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置Realm,后续创建并注入
        securityManager.setRealm(userRealm());
        return securityManager;
    }

    @Bean
    public UserRealm userRealm() {
        return new UserRealm();
    }
}

在上述配置中,定义了哪些 URL 需要进行认证(authc),哪些可以匿名访问(anon),并设置了安全管理器和相关的 Realm(用于用户认证和授权的组件)。

二、用户认证与授权实现(基于 Shiro 的 Realm)

创建 Realm 类
创建一个继承自AuthorizingRealm的类,比如UserRealm,用于实现用户的认证和授权逻辑。

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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserRealm extends AuthorizingRealm {

    @Override
    protected AuthenticationInfo doAuthentication(AuthenticationToken token) throws AuthenticationException {
        // 获取用户名和密码等信息,这里假设从token中获取
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());

        // 实际应用中应该从数据库等地方查询用户信息进行验证
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new AuthenticationException("用户不存在");
        }
        if (!user.getPassword().equals(password)) {
            throw new AuthenticationException("密码错误");
        }

        // 认证通过,返回认证信息
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }

    @Override
    protected AuthorizationInfo doAuthorization(AuthorizationInfo authorizationInfo) {
        // 获取当前用户
        User user = (User) getSubject().getPrincipal();

        // 根据用户角色和权限信息设置授权信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        List<Role> roles = user.getRoles();
        for (Role role : roles) {
            simpleAuthorizationInfo.addRole(role.getName());
            List<Permission> permissions = role.getPermissions();
            for (Permission permission : permissions) {
                simpleAuthorizationInfo.addStringPermission(permission.getName());
            }
        }

        return simpleAuthorizationInfo;
    }
}

doAuthentication方法中实现用户认证逻辑,通过查询数据库等方式验证用户的用户名和密码是否正确。在doAuthorization方法中根据用户的角色和权限信息设置授权信息。

三、权限刷新机制

1. 基于缓存清理的权限刷新

当权限发生变化时(比如管理员在后台修改了用户的角色或权限),可以通过清理 Shiro 相关缓存来实现权限的刷新。

在 Realm 中添加缓存管理
UserRealm类中,可以使用 Shiro 提供的缓存机制来缓存用户的认证和授权信息,以提高性能。例如:

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.ShiroSpringBootAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroCacheManagerAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroRedisCacheManagerAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSessionManagerAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSpringSessionAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.web.ShiroWebAutoConfiguration;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroWebAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@ImportAutoConfiguration({ShiroAutoConfiguration.class, ShiroWebAutoConfiguration.class})
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置安全管理器,后续创建并注入
        shiroFilterFactoryBean.setSecurityManager(securityManager());

        // 配置过滤器链
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置Realm,后续创建并注入
        securityManager.setRealm(userRealm());
        return securityManager;
    }

    @Bean
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        // 设置缓存管理器
        userRealm.setCacheManager(cacheManager());
        return userRealm;
    }

    @Bean
    public CacheManager cacheManager() {
        // 这里可以根据实际情况选择不同的缓存管理器实现,如Ehcache、Redis等
        return new MemoryCacheManager();
    }
}

这里设置了MemoryCacheManager作为缓存管理器示例,实际应用中可以根据需求选择更合适的,如RedisCacheManager等。

权限修改时清理缓存
当权限发生变化时,在相关的业务逻辑代码中(比如在修改用户角色或权限的服务方法中),需要清理对应的缓存。例如:

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.ShiroSpringBootAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroCacheManagerAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.cache.ShiroRedisCacheManagerAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSessionManagerAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.session.ShiroSpringSessionAutoConfiguration;
import org.apache.shiro.spring.boot.autoconfigure.web.ShiroWebAutoConfiguration;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
import org.apache.shiro.web.maven.plugins.shiro.spring.boot.autoconfigure.ShiroWebAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@ImportAutoConfiguration({ShiroAutoConfiguration.class, ShiroWebAutoConfiguration.class})
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 设置安全管理器,后续创建并注入
        shiroFilterFactoryBean.setSecurityManager(securityManager());

        // 配置过滤器链
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/**", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置Realm,后续创建并注入
        securityManager.setRealm(userRealm());
        return securityManager;
    }

    @Bean
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        // 设置缓存管理器
        userRealm.setCacheManager(cacheManager());
        return userRealm;
    }

    @Bean
    public CacheManager cacheManager() {
        // 这里可以根据实际情况选择不同的缓存管理器实现,如Ehcache、Redis等
        return new MemoryCacheManager();
    }

    // 在权限修改的服务方法中
    public void updateUserPermissions(User user, List<Permission> newPermissions) {
        // 先更新数据库中的用户权限信息
        userService.updateUserPermissions(user, newPermissions);

        // 清理缓存
        Cache<String, AuthorizationInfo> cache = userRealm().getCacheManager().getCache("authorizationCache");
        if (cache!= null) {
            cache.clear();
        }
    }
}

这样,当调用updateUserPermissions方法修改用户权限后,会清理掉授权信息的缓存,下次用户访问相关资源时,Shiro 会重新进行授权计算。

2. 主动触发授权更新

除了通过清理缓存来间接实现权限刷新外,还可以在权限发生变化时主动触发授权更新。

在 Realm 中添加更新授权方法
UserRealm类中添加一个方法来手动触发授权更新,例如:

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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserRealm extends AuthorizingRealm {

    //... 前面的认证和授权方法

    public void updateAuthorization(User user) {
        PrincipalCollection principals = getSubject().getPrincipals();
        if (principals!= null && principals.contains(user)) {
            super.doAuthorization(principals);
        }
    }
}

这个方法通过获取当前用户的主体信息,然后调用super.doAuthorization来重新进行授权计算。

在权限修改业务逻辑中调用更新授权方法
在修改用户权限等相关业务逻辑代码中,调用上述updateAuthorization方法来主动触发授权更新。例如:

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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class UserService {

    //... 其他业务方法

    public void updateUserPermissions(User user, List<Permission> newPermissions) {
        // 先更新数据库中的用户权限信息
        userRepository.updateUserPermissions(user, newPermissions);

        // 主动触发授权更新
        UserRealm userRealm = (UserRealm) applicationContext.getBean("userRealm");
        userRealm.updateAuthorization(user);
    }
}

通过这种方式,当权限发生变化时,可以及时、主动地更新用户的授权信息,确保用户的权限访问符合最新的设置。

综上所述,在 Spring Boot 结合 Shiro 进行管理时,通过合理配置 Shiro 的基础组件以及实现有效的权限刷新机制,可以更好地保障系统的安全性和权限管理的灵活性。

到此这篇关于springBoot集成shiro实现权限刷新的文章就介绍到这了,更多相关springBoot shiro权限刷新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SpringBoot项目打成War包部署的方法步骤

    SpringBoot项目打成War包部署的方法步骤

    这篇文章主要介绍了springboot项目如何打war包流程的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 详解Java的引用类型及使用场景

    详解Java的引用类型及使用场景

    这篇文章主要介绍了详解Java的引用类型及使用场景,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-03-03
  • JDBC Template基本使用方法详解

    JDBC Template基本使用方法详解

    这篇文章主要介绍了JDBC Template基本使用方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Java详细讲解异常Exception的处理

    Java详细讲解异常Exception的处理

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等
    2022-06-06
  • Java检查日期字符串是否合法的方法总结

    Java检查日期字符串是否合法的方法总结

    后端接口在接收数据的时候,都需要进行检查。检查全部通过后,才能够执行业务逻辑。本文总结了四个Java检查日期字符串是否合法的方法,感兴趣的可以了解一下
    2022-10-10
  • SpringBoot属性绑定与bean属性校验实现方法详解

    SpringBoot属性绑定与bean属性校验实现方法详解

    这篇文章主要介绍了SpringBoot属性绑定与bean属性校验实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-11-11
  • Spring Boot 整合 MongoDB的示例

    Spring Boot 整合 MongoDB的示例

    这篇文章主要介绍了Spring Boot 整合 MongoDB的示例,帮助大家更好的理解和学习spring boot框架,感兴趣的朋友可以了解下
    2020-10-10
  • 微服务mybatis typehandler使用详解(就这一篇够了)

    微服务mybatis typehandler使用详解(就这一篇够了)

    TypeHandler是MyBatis框架的核心组件,实现数据库表字段类型和Java 数据类型之间的相互转换,本文介绍通过实例代码mybatis typehandler使用,感兴趣的朋友一起看看吧
    2024-02-02
  • 在Java中为日期增加一天的多种方法

    在Java中为日期增加一天的多种方法

    这篇文章主要给大家介绍了关于如何在Java中为日期增加一天的多种方法,在JAVA业务代码中,经常会遇到通过指定时间,增加指定天数的业务需求,需要的朋友可以参考下
    2023-07-07
  • Java实现将数据导出为Word文档的方法步骤

    Java实现将数据导出为Word文档的方法步骤

    我们在开发一些系统的时候,例如OA系统,经常能遇到将审批单数据导出为word和excel文档的需求,导出为excel是比较简单的,但是word文档的格式不像表格那样可以轻松的定位,所以本文给大家介绍了Java怎样实现将数据导出为Word文档,需要的朋友可以参考下
    2025-01-01

最新评论