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

yizhihongxing

下面我将为您详细讲解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日

相关文章

  • Vue3插槽Slot实现原理详解

    下面我将为你详细讲解“Vue3插槽Slot实现原理详解”的完整攻略。 什么是插槽(Slot) 在Vue开发中,有时候我们需要在父组件中定义子组件的模板结构,但是子组件的内容是不确定的。这种情况下,我们可以使用插槽(Slot)来解决问题。 插槽允许我们定义一个承载子组件内容的挂载点,然后在子组件中使用具名插槽(Named Slot)或默认插槽(Default …

    Vue 2023年5月28日
    00
  • Vue详细讲解Vuex状态管理的实现

    Vue详细讲解Vuex状态管理的实现 什么是Vuex Vuex是Vue.js的官方状态管理插件,它将组件之间共享的状态抽取出来,以一个全局单例模式管理,实现了在共享状态时一些问题的规避,使代码更容易理解和维护。 Vuex的状态管理机制 Vuex的状态管理机制可以从以下三个方面来解释: State 状态是存储在Vuex store上的单一状态树,相当于Vue模…

    Vue 2023年5月27日
    00
  • Vue组件的使用教程详解

    Vue组件的使用教程详解 Vue组件是Vue.js中最重要的概念之一,组件化开发可以使应用程序更易于维护和理解。在本文中,我们将详细讲解Vue组件的使用,包括组件定义、组件传参等方面的内容。 定义组件 使用Vue.js定义组件非常简单。可以通过Vue.component()函数定义一个全局组件,或者在Vue实例的components选项中定义局部组件。通常情…

    Vue 2023年5月27日
    00
  • 基于Vue.js与WordPress Rest API构建单页应用详解

    那么让我为你详细讲解“基于Vue.js与WordPress Rest API构建单页应用详解”的完整攻略。 概述 本文将介绍如何使用Vue.js和WordPress Rest API构建单页应用。使用Vue.js和WordPress Rest API结合,可以轻松快速的创建现代化的单页应用。Vue.js是一个用于构建用户界面的JavaScript框架,而Wo…

    Vue 2023年5月28日
    00
  • 使用VUE+SpringBoot+EasyExcel 整合导入导出数据的教程详解

    使用VUE+SpringBoot+EasyExcel 整合导入导出数据的教程详解 简介 数据的导入导出是一个web应用中很重要的功能,在开发中,往往需要对数据进行批量导入和导出。本文将介绍如何使用Vue+SpringBoot+EasyExcel进行数据的导入导出。 技术栈 前端:Vue.js 后端:SpringBoot 数据导入导出库:EasyExcel 准…

    Vue 2023年5月28日
    00
  • vue-cli中实现响应式布局的方法

    当我们使用Vue-cli构建一个项目时,可以选择一些预设好的模板,比如使用vue-init webpack模板,就会得到一个默认的项目结构。我们可以在此基础上选择性的添加我们需要的库和工具,比如Sass﹑Stylus等CSS预处理器来实现响应式布局。 以下是一些实现响应式布局的方法: 1. 使用css@media查询 media queries是css3最强…

    Vue 2023年5月28日
    00
  • vue项目中添加electron的详细代码

    在Vue项目中添加Electron的过程如下所述: 安装Electron相关依赖 需要安装Electron相关依赖,可以在终端或命令行中运行以下命令: npm install –save-dev electron 在Vue项目中添加Electron相关文件 在Vue项目的根目录下,需要添加一个名为“main.js”的文件,其中包含启动Electron的必要…

    Vue 2023年5月28日
    00
  • 一文搞懂VueJs中customRef函数使用

    一文搞懂VueJs中customRef函数使用 简介 Vue.js 3.0版本引入了一个新的api函数——customRef,用于创建一个自定义的ref。customRef的使用十分灵活。它允许你控制目标对象的依赖和副作用。在本文中,我们将探讨如何使用customRef函数。 基本用法 使用customRef函数,需要传入一个函数作为参数,这个函数有两个参数…

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