因此,这篇文章,阿淼就带大家将 shiro 权限框架整合到 SpringBoot 中,以达到快速的实现权限管理的功能。

在 Spring Boot 中做权限管理,一样平常来说,主流的方案是 Spring Security ,但是由于 Spring Security 过于弘大和繁芜,只要能知足业务须要,大多数公司还是会选择 Apache Shiro 来利用。

一样平常来说,Spring Security 和 Shiro 的差异如下:

shiroajaxjsp玩转SpringBoot之整合 shiro 权限框架 AJAX

Spring SecurityApache Shiro重量级的安全管理框架轻量级的安全管理框架观点繁芜,配置繁琐观点大略、配置大略功能强大功能大略

这篇文章会首先带大家理解 Apache Shiro ,然后再给出利用案例 Demo。

走进 Apache Shiro官网认知

照例又辞官网扒了扒先容:

Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications. Apache Shiro™是一个强大且易用的Java安全框架,能够用于身份验证、授权、加密和会话管理。
Shiro拥有易于理解的API,您可以快速、轻松地得到任何运用程序——从最小的移动运用程序到最大的网络和企业运用程序。

简而言之,Apache Shiro 是一个强大灵巧的开源安全框架,可以完备处理身份验证、授权、加密和会话管理。

Shiro能到底能做些什么呢?验证用户身份用户访问权限掌握,比如:1、判断用户是否分配了一定的安全角色。
2、判断用户是否被付与完成某个操作的权限在非 Web 或 EJB 容器的环境下可以任意利用Session API可以相应认证、访问掌握,或者 Session 生命周期中发生的事宜可将一个或以上用户安全数据源数据组合成一个复合的用户 “view”(视图)支持单点登录(SSO)功能支持供应“Remember Me”做事,获取用户关联信息而无需登录 ···为什么本日还要利用Apache Shiro?

对此,官方给出了详细的阐明:shiro.apache.org/

自2003年以来,框架环境发生了很大变革,因此本日仍旧有充分的情由利用Shiro。
实际上有很多缘故原由。
Apache Shiro是:

易于利用 -易于利用是该项目的终极目标。
运用程序安全性可能非常令人困惑和沮丧,并被视为“必要的邪恶”。
如果您使它易于利用,以使新伎俩式员可以开始利用它,那么就不必再痛楚了。
全面 -Apache Shiro声称没有其他具有范围广度的安全框架,因此它可能是知足安全需求的“一站式做事”。
灵巧 -Apache Shiro可以在任何运用程序环境中事情。
只管它可以在Web,EJB和IoC环境中运行,但并不须要它们。
Shiro也不哀求任何规范,乃至没有很多依赖性。
具有Web功能 -Apache Shiro具有出色的Web运用程序支持,使您可以基于运用程序URL和Web协议(例如REST)创建灵巧的安全策略,同时还供应一组JSP库来掌握页面输出。
可插拔 -Shiro干净的API和设计模式使它易于与许多其他框架和运用程序集成。
您会看到Shiro与Spring,Grails,Wicket,Tapestry,Mule,Apache Camel,Vaadin等框架无缝集成。
受支持 -Apache Shiro是Apache Software Foundation(Apache软件基金会)的一部分,该组织被证明以其社区的最大利益行事。
项目开拓和用户群体友好的公民随时可以供应帮助。
如果须要,像Katasoft这样的商业公司也可以供应专业的支持和做事。
Shiro 核心观点

Apache Shiro 是一个全面的、蕴含丰富功能的安全框架。

下图为描述 Shiro 功能的框架图:

如图所示,功能包括:

Authentication(认证):用户身份识别,常日被称为用户“登录”Authorization(授权):访问掌握。
比如某个用户是否具有某个操作的利用权限。
Session Management(会话管理):特定于用户的会话管理,乃至在非web 或 EJB 运用程序。
Cryptography(加密):在对数据源利用加密算法加密的同时,担保易于利用。

并且 Shiro 还有通过增加其他的功能来支持和加强这些不同运用环境下安全领域的关注点。

特殊是对以下的功能支持:

Web支持:Shiro 供应的 Web 支持 api ,可以很轻松的保护 Web 运用程序的安全。
缓存:缓存是 Apache Shiro 担保安全操作快速、高效的主要手段。
并发:Apache Shiro 支持多线程运用程序的并发特性。
测试:支持单元测试和集成测试,确保代码和预想的一样安全。
"Run As":这个功能许可用户假设另一个用户的身份(在容许的条件下)。
"Remember Me":跨 session 记录用户的身份,只有在逼迫须要时才须要登录。

把稳: Shiro 不会去掩护用户、掩护权限,这些须要我们自己去设计/供应,然后通过相应的接口注入给 Shiro

利用案例 Demo1.新建 maven 项目

为方便我们初始化项目,Spring Boot给我们供应一个项目模板天生网站。

1、打开浏览器,访问:start.spring.io/2、根据页面提示,选择构建工具,开拓措辞,项目信息等。
2.导入 springboot 父依赖

&lt;parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.2.RELEASE</version></parent>复制代码3.干系 jar 包

web 包

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>复制代码

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.数据库

建表语句在项目中有,项目地址: github.com/mmzsblog/mm…

5.自定义 realm

public class MyShiroRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private PermissionService permissionService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); // HttpServletRequest request = (HttpServletRequest) ((WebSubject) SecurityUtils // .getSubject()).getServletRequest();//这个可以用来获取在登录的时候提交的其他额外的参数信息 String username = (String) principals.getPrimaryPrincipal(); // 受理权限 // 角色 Set<String> roles = new HashSet<String>(); Role role = roleService.getRoleByUserName(username); System.out.println(role.getRoleName()); roles.add(role.getRoleName()); authorizationInfo.setRoles(roles); // 权限 Set<String> permissions = new HashSet<String>(); List<Permission> querypermissions = permissionService.getPermissionsByRoleId(role.getId()); for (Permission permission : querypermissions) { permissions.add(permission.getPermissionName()); } authorizationInfo.setStringPermissions(permissions); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { String loginName = (String) authcToken.getPrincipal(); // 获取用户密码 User user = userService.getOne(new QueryWrapper<User>().eq("username", loginName)); if (user == null) { // 没找到帐号 throw new UnknownAccountException(); } String password = new String((char[]) authcToken.getCredentials()); String inpass = (new Md5Hash(password, user.getUsername())).toString(); if (!user.getPassword().equals(inpass)) { throw new IncorrectCredentialsException(); } // 交给AuthenticatingRealm利用CredentialsMatcher进行密码匹配 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(loginName, user.getPassword(), ByteSource.Util.bytes(loginName), getName()); return authenticationInfo; }}复制代码6.shiro 配置类

@Configurationpublic 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.考试类

@RestControllerpublic class UserController { @PostMapping("login") public String name(String username, String password) { String result = "已登录"; Subject currentUser = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); if (!currentUser.isAuthenticated()) { try { currentUser.login(token);// 会触发com.shiro.config.MyShiroRealm的doGetAuthenticationInfo方法 result = "登录成功"; } catch (UnknownAccountException e) { result = "用户名缺点"; } catch (IncorrectCredentialsException e) { result = "密码缺点"; } } return result; } @GetMapping("logout") public void logout() { Subject currentUser = SecurityUtils.getSubject(); currentUser.logout(); } @RequiresPermissions("role:update") @GetMapping("/role") public String name() { return "hello"; } @RequiresPermissions("user:select") @GetMapping("/role2") public String permission() { return "hello sel"; }}复制代码7.1 登录测试

数据库账号(密码经由md5加盐加密)

7.2 权限测试

8.解释8.1 无权限时的处理

无权限时自定义了一个非常。
以是,权限测试的时候没有权限就会提示配置的提示语 “没有权限”。

@ControllerAdvicepublic class ShiroException { @ExceptionHandler(value = UnauthorizedException.class) @ResponseBody public String name() { return "没有权限"; }}复制代码8.2 角色权限测试与权限测试相同

权限设置可在shiro配置类中shiro过滤链设置,也可用表明办法设置,本文利用表明办法。

8.3 shiro 的 session 和 cache

shiro 的 session 和 cache 管理可以自定义,本文用的是默认的,推举自定义,方便管理。

小结Apache Shiro是Java的一个安全框架Shiro是一个强大的大略易用的Java安全框架,紧张用来更便捷的认证、授权、加密、会话管理、与Web集成、缓存等Shiro利用起来小而大略spring中有spring security ,是一个权限框架,它和spring依赖过于紧密,没有shiro利用大略。
shiro不依赖于spring,shiro不仅可以实现web运用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始利用shiro.