Spring Boot集成Shiro实现动态加载权限的完整步骤

下面我将为您详细讲解Spring Boot集成Shiro实现动态加载权限的完整步骤。

一、引入依赖

在Spring Boot项目中,需要引入以下依赖:

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

<!-- mybatis-plus依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.2.0</version>
</dependency>

<!-- druid依赖 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.5</version>
</dependency>

其中,shiro-spring-boot-web-starter是Shiro的Spring Boot集成依赖,mybatis-plus-boot-starter是Mybatis Plus的Spring Boot集成依赖,druid-spring-boot-starter是Druid连接池的Spring Boot集成依赖。

二、定义Shiro的Realm

在Spring Boot项目中,需要定义一个继承自AuthorizingRealm的Realm类,用于进行认证和授权操作。示例代码如下:

@Component
public class UserRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        User user = userService.getUserByUsername(username);
        if (user == null) {
            throw new UnknownAccountException("账号不存在");
        } else {
            return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
        }
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        User user = (User) principalCollection.getPrimaryPrincipal();
        List<Role> roleList = userService.getRoleListByUserId(user.getId());
        Set<String> roleSet = new HashSet<>();
        Set<String> permissionSet = new HashSet<>();
        for (Role role : roleList) {
            roleSet.add(role.getName());
            List<Permission> permissionList = userService.getPermissionListByUserIdAndRoleId(user.getId(), role.getId());
            for (Permission permission : permissionList) {
                permissionSet.add(permission.getName());
            }
        }
        authorizationInfo.setRoles(roleSet);
        authorizationInfo.setStringPermissions(permissionSet);
        return authorizationInfo;
    }
}

以上代码中,doGetAuthenticationInfo方法用于进行认证操作,根据用户名查询用户并返回认证信息;doGetAuthorizationInfo方法用于进行授权操作,根据用户的角色和权限进行授权。

三、配置Shiro的过滤器

在Spring Boot项目中,需要配置Shiro的过滤器,来控制用户访问URL的权限。示例代码如下:

@Configuration
public class ShiroConfig {

    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 自定义过滤器,用于动态加载权限
        Map<String, Filter> filters = new LinkedHashMap<>();
        filters.put("perms", new CustomPermissionsAuthorizationFilter());
        shiroFilterFactoryBean.setFilters(filters);
        // 定义url过滤规则
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 配置不需要权限认证的url
        filterChainDefinitionMap.put("/login", "anon");
        // 配置需要权限认证的url
        filterChainDefinitionMap.put("/**", "perms");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public SecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm);
        return securityManager;
    }

}

其中,定义了一个自定义过滤器CustomPermissionsAuthorizationFilter,用于动态加载权限,在后面会详细介绍;同时,还定义了url过滤规则,配置了不需要权限认证的url和需要权限认证的url。

四、配置Shiro的权限注解

在Spring Boot项目中,需要在需要控制权限的方法上添加Shiro的注解@RequiresPermissions。示例代码如下:

@RequiresPermissions("user:view")
@GetMapping("/list")
public Result list(@RequestParam(required = false) String username) {
    List<User> userList = userService.getUserList(username);
    return Result.success(userList);
}

以上代码中,使用了@RequiresPermissions("user:view")注解,表示用户需要具备“user:view”权限才能访问该方法。

五、实现动态加载权限

在Spring Boot项目中,实现动态加载权限需要定义一个自定义过滤器CustomPermissionsAuthorizationFilter。示例代码如下:

public class CustomPermissionsAuthorizationFilter extends PermissionsAuthorizationFilter {

    @Autowired
    private UserService userService;

    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = getSubject(request, response);
        // 获取请求的url
        String url = getPathWithinApplication(request);
        // 获取当前用户的角色和权限
        User user = (User) subject.getPrincipal();
        List<Permission> permissionList = userService.getPermissionListByUrlAndUserId(url, user.getId());
        Set<String> permissionSet = new HashSet<>();
        for (Permission permission : permissionList) {
            permissionSet.add(permission.getName());
        }
        // 判断用户是否具备请求的url所需的权限
        return subject.isPermittedAll(permissionSet.toArray(new String[permissionSet.size()]));
    }

}

以上代码中,重写了父类的isAccessAllowed方法,用于实现动态加载权限。首先获取请求的url和当前用户的角色和权限信息,然后根据url和userId查询当前登录用户所具备的权限,最后判断用户是否具备请求的url所需的权限。

六、使用示例

以下是一个获取用户列表的Controller示例:

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/list")
    @RequiresPermissions("user:view")
    public Result list(@RequestParam(required = false) String username) {
        List<User> userList = userService.getUserList(username);
        return Result.success(userList);
    }

    @PostMapping("/add")
    @RequiresPermissions("user:add")
    public Result add(@RequestBody User user) {
        userService.addUser(user);
        return Result.success();
    }

}

其中,@RequiresPermissions("user:view")@RequiresPermissions("user:add")注解用于控制用户访问该方法的权限。

另外,还需要进行登录认证才能访问受控的URL,登录认证代码如下:

@PostMapping("/login")
public Result login(@RequestBody User user) {
    UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
    Subject subject = SecurityUtils.getSubject();
    try {
        subject.login(token);
        return Result.success("登录成功");
    } catch (AuthenticationException e) {
        return Result.error(e.getMessage());
    }
}

小结

以上就是Spring Boot集成Shiro实现动态加载权限的完整步骤,包括引入依赖、定义Shiro的Realm、配置Shiro的过滤器、配置Shiro的权限注解以及实现动态加载权限。其中,完成一个自定义过滤器用于动态加载权限是实现该功能的关键所在。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Boot集成Shiro实现动态加载权限的完整步骤 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • vue项目中使用bpmn-自定义platter的示例代码

    下面我将详细讲解如何在Vue项目中使用BPMN自定义platter的完整攻略。 准备工作 首先,我们需要在Vue项目中安装相应的依赖项。打开终端(Terminal),进入到Vue项目的根目录下,然后执行以下命令: npm install bpmn-js bpmn-moddle bpmn-js-properties-panel 这三个依赖项分别是: bpmn-…

    Vue 2023年5月28日
    00
  • ionic cordova一次上传多张图片(类似input file提交表单)的实现方法

    一、背景 在移动端开发中,经常会遇到需要上传多张图片的需求,例如上传头像、相册、动态图片等。Ionic是一个基于AngularJS和Cordova的开发框架,提供了丰富的插件和能力,可以便捷地实现这类功能。 二、实现思路 实现多张图片上传的关键在于,需要通过Cordova的File Transfer插件将多张图片上传到服务器。因为Cordova File插件…

    Vue 2023年5月28日
    00
  • Vue项目打包成exe可执行文件的实现过程(无瑕疵,完美版)

    这是一个相对复杂的问题,需要较详细的解释。以下是详细的攻略: 1. 准备工作 1.1 安装依赖 将Vue项目打包成exe可执行文件的过程中需要使用nodejs的Electron打包工具,需要安装nodejs。 Electron打包工具依赖于Electron Builder,因此需要安装Electron Builder。 安装完成以上两个依赖后,需要安装cro…

    Vue 2023年5月27日
    00
  • VUE v-for循环中每个item节点动态绑定不同函数的实例

    要实现在VUE v-for循环中每个item节点动态绑定不同函数的实例,可以使用以下步骤: 在每个item节点上绑定一个唯一的key值,以便Vue能够追踪节点的增、删、移动操作。 <ul> <li v-for="(item, index) in items" :key="item.id"> {{…

    Vue 2023年5月28日
    00
  • vue之Vue.use的使用场景及说明

    Vue之Vue.use的使用场景及说明 简介 Vue.use 是一个用于安装 Vue.js 插件的方法。如果需要全局注册一个自定义插件或第三方插件,则需要使用该方法进行注册,例如 Vue.use(插件)。该方法会自动检测插件是否已经安装,如果已经安装,将不会多次进行安装。 使用场景 Vue.use方法的使用场景是当我们需要使所有实例都具备一些通用的功能时,而…

    Vue 2023年5月29日
    00
  • js中什么时候不能使用箭头函数

    使用箭头函数的时候需要注意一些使用限制,下面详细讲解什么时候不能使用箭头函数以及注意事项。 不能使用箭头函数的情况 1. 不能作为构造函数 箭头函数不能作为构造函数,也就是不能使用 new 关键字创建对象。因为箭头函数没有自己的 this,也没有 prototype 属性。所以,如果你尝试使用 “箭头函数” 作为构造函数,则会产生异常。 // 箭头函数不能作…

    Vue 2023年5月28日
    00
  • IntelliJ IDEA 安装vue开发插件的方法

    以下是详细的IntelliJ IDEA 安装vue开发插件的方法: 方法一:通过IDEA插件市场安装 打开 Intellij IDEA,选择 File -> Setting -> Plugins; 在插件市场中搜索Vue.js插件(Vue.js、Vue.js Snippets、Vue.js Style),点击Install安装; 安装完成后,重启…

    Vue 2023年5月27日
    00
  • 使用vue自定义如何实现Tree组件和拖拽功能

    下面是关于使用Vue自定义实现Tree组件和拖拽功能的攻略: 实现概述 要实现Tree组件和拖拽功能,我们需要先了解下面几个概念: 树形结构 树形结构是一种数据结构,它是由一个个节点构成的层级结构。 每个节点可以有若干个子节点,但只有一个父节点。 递归组件 Vue提供了一种专门处理树形数据的递归组件。 递归组件可以将自身再次调用,实现动态的嵌套结构。 拖拽功…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部