SpringBoot使用Shiro实现动态加载权限详解流程

下面是"SpringBoot使用Shiro实现动态加载权限详解流程"的完整攻略:

1. 确定需求

首先,我们需要明确本次实现的需求。我们将使用Shiro来实现认证和权限控制,同时,我们的权限控制将支持动态的添加和删除。具体来说,我们需要实现以下功能:

  • 用户登录
  • 用户退出
  • 用户认证
  • 用户权限控制
  • 动态添加权限
  • 动态删除权限

2. 搭建SpringBoot项目

我们需要搭建一个SpringBoot项目来实现我们的需求。你可以使用任何IDE或者命令行工具来创建一个SpringBoot项目。在创建完项目后,需要添加Shiro的依赖,本文中使用的是官方提供的Starter。这个依赖将会自动引入所有必要的Shiro库和配置。

3. Shiro认证和权限控制配置

我们需要在SpringBoot的配置文件中配置Shiro的认证和权限控制。使用Shiro之前,我们需要先定义一个Realm,这个Realm将会为Shiro提供认证和权限控制的数据。

以下是一个使用JPA进行认证和授权的Realm的示例:

public class MyRealm extends AuthorizingRealm {

    private UserRepository repository;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();
        User user = repository.findByUsername(username);
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        for (Role role : user.getRoles()) {
            authorizationInfo.addRole(role.getName());
            authorizationInfo.addStringPermissions(role.getPermissions().stream().map(Permission::getName).collect(Collectors.toSet()));
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
        User user = repository.findByUsername(usernamePasswordToken.getUsername());
        if (user == null) {
            throw new UnknownAccountException();
        }
        return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName());
    }

}

在这个示例中,我们需要定义一个UserRepository来获取用户和角色的信息。我们重写了doGetAuthorizationInfo和doGetAuthenticationInfo两个方法来实现授权和认证的逻辑。在doGetAuthorizationInfo方法中,我们获取当前用户所拥有角色的权限,并返回一个SimpleAuthorizationInfo对象。在doGetAuthenticationInfo方法中,我们获取用户输入的用户名和密码,并在数据库中进行认证。

为了让Shiro能够使用我们的Realm,我们需要在SpringBoot的配置文件中添加相关配置。以下是一个示例:

shiro:
  security-manager:
    realm: com.example.MyRealm
    session-mode: native
  login-url: /login
  success-url: /home

在这个配置文件中,我们将security-manager的realm设置为我们自定义的MyRealm,而session-mode则为native。Shiro支持多种session类型,包括native和web,这里我们选择native。

另外,在这个示例中,我们将登录页面设置为/login,成功后跳转到/home。

通过以上配置,我们完成了Shiro的认证和权限控制的配置。

4. 动态添加和删除权限

本文中,我们使用Shiro的默认实现MemoryPermissionResolver来实现权限的动态添加和删除。MemoryPermissionResolver的实现方式是将所有权限存储在一个ConcurrentHashMap中。

以下是一个添加权限的示例:

@Service
public class PermissionService {

    private PermissionResolver permissionResolver;
    private ConcurrentHashMap<String, Permission> permissions = new ConcurrentHashMap<String, Permission>();

    public void addPermission(String permissionName) {
        Permission permission = permissionResolver.resolvePermission(permissionName);
        permissions.put(permission.getName(), permission);
    }

}

在这个示例中,我们使用了一个PermissionResolver来解析权限的名称,并将其添加到一个ConcurrentHashMap中。

以下是一个删除权限的示例:

@Service
public class PermissionService {

    private ConcurrentHashMap<String, Permission> permissions = new ConcurrentHashMap<String, Permission>();

    public void removePermission(String permissionName) {
        permissions.remove(permissionName);
    }

}

这里,我们只需要删除指定名称的权限即可。

5. 添加Shiro的注解

为了使用Shiro的注解,我们需要在SpringBoot的配置文件中添加以下配置:

@Bean
ShiroFilterChainDefinition shiroFilterChainDefinition() {
    DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
    chainDefinition.addPathDefinition("/logout", "logout");
    chainDefinition.addPathDefinition("/login", "anon");
    chainDefinition.addPathDefinition("/**", "authc");
    return chainDefinition;
}

在这个配置文件中,我们将/logout设置为logout,/login设置为匿名访问,其他路径设置为authc。

除此之外,我们还需要在Controller中使用Shiro的注解,如@RequiresRoles和@RequiresPermissions来实现权限的限制。

不过,在使用注解前,我们还需要在SpringBoot的配置文件中添加以下配置:

@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() throws Exception {
    return new LifecycleBeanPostProcessor();
}

@Bean(name = "lifecycleExecutor")
public Executor lifecycleExecutor() {
    return Executors.newSingleThreadExecutor();
}

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    return new DefaultAdvisorAutoProxyCreator();
}

@Bean
public AnnotationMethodInterceptor annotationMethodInterceptor() {
    return new AnnotationMethodInterceptor();
}

@Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
    MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
    methodInvokingFactoryBean.setTargetMethod("setSecurityManager");
    methodInvokingFactoryBean.setArguments(new Object[]{securityManager});
    return methodInvokingFactoryBean;
}

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
    authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
    authorizationAttributeSourceAdvisor.setAdvice(annotationMethodInterceptor());
    return authorizationAttributeSourceAdvisor;
}

6. 测试

我们需要编写一些测试用例来确认我们的Shiro认证和权限控制是否正常工作。

@RequiresRoles("admin")
@Test
public void testAdminRoleCanViewDashboard() {
    mockMvc.perform(get("/dashboard"))
            .andExpect(status().isOk());
}

在这个示例中,我们使用了@RequiresRoles注解,来保证用户必须具备admin角色才能访问/dashboard路径。如果访问正常,则说明我们的动态权限控制已经生效。

7. 示例说明

如果需要更进一步的示例,可以参考以下两个链接:

这两个例子提供了完整的代码和详细的文档说明,可以方便的进行测试和学习。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot使用Shiro实现动态加载权限详解流程 - Python技术站

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

相关文章

  • vue3中使用scss加上scoped导致样式失效问题

    在Vue3中,使用SCSS预处理器编写样式时,如果在<style>标签中添加scoped属性,会导致样式失效。 原因在于,scoped属性会对样式中的选择器加上一个data-v-前缀,使其只对当前组件生效。而SCSS预处理器生成的CSS选择器在编译时无法加上前缀,导致样式无法生效。 为了解决这个问题,可以使用以下两种方法之一。 方法一:使用Vue…

    Vue 2023年5月28日
    00
  • vue路径写法之关于./和@/的区别

    当使用Vue构建项目时,路径写法是必不可少的知识点,对于路径写法中的”./”与”@/”的区别,以下是详细讲解: 1. 相对路径”./” 使用相对路径”./”,我们可以引用同一目录下的文件或目录。例如,有以下文件目录结构: ├── src │ ├── components │ │ ├── a.vue │ │ ├── b.vue │ ├── views │ │ …

    Vue 2023年5月28日
    00
  • Vue项目总结之webpack常规打包优化方案

    那我们就来详细讲解一下“Vue项目总结之webpack常规打包优化方案”的完整攻略,包括以下内容: 一、Webpack基础知识 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器。它会递归地构建一个依赖关系图,在这个过程中将每个模块视为一个节点,并将模块之间的依赖关系转换为图中的边。 我相信作为一个Vue开发者,你一定已经熟练掌握了W…

    Vue 2023年5月28日
    00
  • 详解基于Vue+Koa的pm2配置

    下面我将详细讲解“详解基于Vue+Koa的pm2配置”的完整攻略。 一、背景说明 随着前端项目规模的扩大,对于前端项目的部署也变得越来越复杂。本攻略将介绍如何基于Vue+Koa来配置pm2,使得前端项目的部署得到更好的管理和控制。 二、pm2简介 pm2是一个进程管理器,可以管理和监控node.js应用程序。pm2可以通过命令行进行控制,可以通过pm2配置相…

    Vue 2023年5月28日
    00
  • Vue计时器的用法详解

    Vue计时器的用法详解 在Vue.js中,我们可以使用计时器来执行一些定时任务,比如实现一些定时更新视图、缓慢滚动等效果。本篇文章将介绍Vue计时器的使用方法。 setInterval和clearInterval 在JavaScript中,我们可以使用setInterval函数来创建计时器,该函数将在指定的时间间隔内执行回调函数。使用clearInterva…

    Vue 2023年5月29日
    00
  • 详解vue-cli3多页应用改造

    针对”详解vue-cli3多页应用改造”,我们需要掌握以下几个方面: Vue-cli3多页应用的原理和基本配置 多页应用架构演变及其对应实现(如何从单页应用改造为多页应用) 懒加载和代码分割的原理和应用 多语言和国际化的实现方式 基于Vuex的SPA应用改造为多页应用的实践 下面我们来详细讲解一下这个完整攻略吧: 一、Vue-cli3多页应用的原理和基本配置…

    Vue 2023年5月28日
    00
  • 浅析vue 函数配置项watch及函数 $watch 源码分享

    浅析 Vue 函数配置项 watch 及函数 $watch 在 Vue.js 中,watch 是一个非常重要的选项。它可以监听数据的变化,从而触发相应的逻辑。本文将从两个方面来介绍 watch:函数配置项 watch 和函数 $watch 的源码分享。 函数配置项 watch watch 是一个对象,它的属性是要监听的数据的名称,值是一个对象或函数。如果值是…

    Vue 2023年5月29日
    00
  • 在VUE style中使用data中的变量的方法

    在Vue的style中使用组件中的数据变量可以通过:style绑定对象来实现。具体方法如下: 定义组件时,定义组件中需要的数据变量 Vue.component(‘my-component’, { data: function () { return { color: ‘red’ } }, template: ‘<div :style="{ c…

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