在实际项目中,经常需要用到角色权限区分,以此来为不同的角色赋予不同的权利,分配不同的任务。比如,普通用户只能浏览;会员可以浏览和评论;超级会员可以浏览、评论和看视频课等;实际应用场景很多。毫不夸张的说,几乎每个完整的项目都会设计到权限管理。 因此,这篇文章,阿粉就带大家将 shiro 权限框架整合到 SpringBoot 中,以达到快速的实现权限管理的功能。 序在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是由于 Spring Security 过于庞大和复杂,只要能满足业务需要,大多数公司还是会选择 Apache Shiro 来使用。 一般来说,Spring Security 和 Shiro 的区别如下:
这篇文章会首先带大家了解 Apache Shiro ,然后再给出使用案例 Demo。 走进 Apache Shiro官网认知照例又去官网扒了扒介绍:
简而言之,Apache Shiro 是一个强大灵活的开源安全框架,可以完全处理身份验证、授权、加密和会话管理。 Shiro能到底能做些什么呢?
为什么今天还要使用Apache Shiro?对此,官方给出了详细的解释:http://shiro./ 自2003年以来,框架环境发生了很大变化,因此今天仍然有充分的理由使用Shiro。实际上有很多原因。Apache Shiro是:
Shiro 核心概念Apache Shiro 是一个全面的、蕴含丰富功能的安全框架。 下图为描述 Shiro 功能的框架图: 如图所示,功能包括:
并且 Shiro 还有通过增加其他的功能来支持和加强这些不同应用环境下安全领域的关注点。 特别是对以下的功能支持:
注意:Shiro 不会去维护用户、维护权限,这些需要我们自己去设计/提供,然后通过相应的接口注入给 Shiro 使用案例 Demo1.新建 maven 项目为方便我们初始化项目,Spring Boot给我们提供一个项目模板生成网站。
2.导入 springboot 父依赖<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.2.RELEASE</version> </parent> 3.相关 jar 包web 包
shiro-spring 包就是此篇文章的核心 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> shiro 注解会用到 aop <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> 数据库相关包使用的是mybatisplus <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.1.0</version> </dependency> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.0</version> </dependency> 4.数据库建表语句在项目中有,项目地址: https://github.com/justdojava/java-samples 5.自定义 realm
6.shiro 配置类@Configuration public class ShiroConfiguration { private static final Logger logger = LoggerFactory.getLogger(ShiroConfiguration.class);
/** * Shiro的Web过滤器Factory 命名:shiroFilter */ @Bean(name = 'shiroFilter') public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // Shiro的核心安全接口,这个属性是必须的 shiroFilterFactoryBean.setSecurityManager(securityManager); //需要权限的请求,如果没有登录则会跳转到这里设置的url shiroFilterFactoryBean.setLoginUrl('/login.html'); //设置登录成功跳转url,一般在登录成功后自己代码设置跳转url,此处基本没用 shiroFilterFactoryBean.setSuccessUrl('/main.html'); //设置无权限跳转界面,此处一般不生效,一般自定义异常 shiroFilterFactoryBean.setUnauthorizedUrl('/error.html'); Map<String, Filter> filterMap = new LinkedHashMap<>(); // filterMap.put('authc', new AjaxPermissionsAuthorizationFilter()); shiroFilterFactoryBean.setFilters(filterMap); /* * 定义shiro过滤链 Map结构 * Map中key(xml中是指value值)的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 * anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 * authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc. * FormAuthenticationFilter */ Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); /* * 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边; authc:所有url都必须认证通过才可以访问; * anon:所有url都都可以匿名访问 */ filterChainDefinitionMap.put('/login.html', 'authc'); filterChainDefinitionMap.put('/login', 'anon'); filterChainDefinitionMap.put('/js/**', 'anon'); filterChainDefinitionMap.put('/css/**', 'anon'); filterChainDefinitionMap.put('/logout', 'logout'); filterChainDefinitionMap.put('/**', 'authc'); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }
/** * 权限管理 */ @Bean public SecurityManager securityManager() { logger.info('=======================shiro======================='); DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(MyShiroRealm()); // securityManager.setRememberMeManager(rememberMeManager); return securityManager; }
/** * Shiro Realm 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的 */ @Bean public MyShiroRealm MyShiroRealm() { MyShiroRealm userRealm = new MyShiroRealm(); userRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return userRealm; }
/** * 凭证匹配器 密码验证 */ @Bean(name = 'credentialsMatcher') public HashedCredentialsMatcher hashedCredentialsMatcher() { HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); // 散列算法:这里使用MD5算法; hashedCredentialsMatcher.setHashAlgorithmName('md5'); // 散列的次数,比如散列两次,相当于 md5(md5('')); hashedCredentialsMatcher.setHashIterations(1); // storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码 hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); return hashedCredentialsMatcher; }
/** * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; }
} 7.测试类
7.1 登录测试数据库账号(密码经过md5加盐加密) 7.2 权限测试8.说明8.1 无权限时的处理无权限时自定义了一个异常。所以,权限测试的时候没有权限就会提示配置的提示语 “没有权限”。 @ControllerAdvice public class ShiroException { @ExceptionHandler(value = UnauthorizedException.class) @ResponseBody public String name() { return '没有权限'; } } 8.2 角色权限测试与权限测试相同权限设置可在shiro配置类中shiro过滤链设置,也可用注解方式设置,本文使用注解方式。 8.3 shiro 的 session 和 cacheshiro 的 session 和 cache 管理可以自定义,本文用的是默认的,推荐自定义,方便管理。 小结
参考:https://www.cnblogs.com/joker-dj/archive/2020/04/13/12690648.html < END > 如果大家喜欢我们的文章,欢迎大家转发,点击在看让更多的人看到。也欢迎大家热爱技术和学习的朋友加入的我们的知识星球当中,我们共同成长,进步。
|
|