Apache Shiro 是一个功能强大且灵活的开放源代码安全框架,可以细粒度地处理认证 (Authentication),授权 (Authorization),会话 (Session) 管理和加密 (cryptography) 等企业级应用中常见的安全控制流程。 Apache Shiro 的首要目标是易于使用和理解。 有时候安全性的流程控制会非常复杂,对开发人员来说是件很头疼的事情,但并不一定如此。 框架就应该尽可能地掩盖复杂性,并公开一个简洁而直观的 API,从而简化开发人员的工作,确保其应用程序安全性。这次我们聊一聊如何在 Spring Web 应用中使用 Shiro 实现权限控制。
功能
Apache Shiro 是一个具有许多功能的综合型应用程序安全框架。 下图为 Shiro 中的最主要的几个功能:
Shiro 的主要目标是“应用安全的四大基石” - 认证,授权,会话管理和加密:
架构
从整体概念上理解,Shiro 的体系架构有三个主要的概念:Subject (主体,也就是用户),Security Manager (安全管理器)和 Realms (领域)。 下图描述了这些组件之间的关系:
这几大组件可以这样理解:
数据准备
在 Web 应用中,对安全的控制主要有角色、资源、权限(什么角色能访问什么资源)几个概念,一个用户可以有多个角色,一个角色也可以访问多个资源,也就是角色可以对应多个权限。落实到数据库设计上,我们至少需要建 5 张表:用户表、角色表、资源表、角色-资源表、用户-角色表,这 5 张表的结构如下:
用户表:
id | username | password |
---|---|---|
1 | 张三 | 123456 |
2 | 李四 | 666666 |
3 | 王五 | 000000 |
角色表:
id | rolename |
---|---|
1 | 管理员 |
2 | 经理 |
3 | 员工 |
资源表:
id | resname |
---|---|
1 | /user/add |
2 | /user/delete |
3 | /compony/info |
角色-资源表:
id | roleid | resid |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 2 | 3 |
用户-角色表:
id | userid | roleid |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
对应的 POJO 类如下:
/** * 用户 */ public class User { private Integer id; private String username; private String password; //getter & setter... }
/** * 角色 */ public class Role { private String id; private String rolename; }
/** * 资源 */ public class Resource { private String id; private String resname; }
/** * 角色-资源 */ public class RoleRes { private String id; private String roleid; private String resid; }
/** * 用户-角色 */ public class UserRole { private String id; private String userid; private String roleid; }
Spring 与 Shiro 整合的详细步骤,请参阅我的博客 《 Spring 应用中整合 Apache Shiro 》 。 这里补充一下:需要提前引入 Shiro 的依赖,打开mvnrepository.com,搜索 Shiro,我们需要前三个依赖,也就是 Shiro-Core、Shiro-Web 以及 Shiro-Spring,以 Maven 项目为例,在 pom.xml 中的 <dependencies> 节点下添加如下依赖:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
在 application-context.xml 中需要这样配置 shiroFilter bean:
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!-- 登录页面 --> <property name="loginUrl" value="/login"/> <!-- 登录成功后的页面 --> <property name="successUrl" value="/index"/> <!-- 非法访问跳转的页面 --> <property name="unauthorizedUrl" value="/403"/> <!-- 权限配置 --> <property name="filterChainDefinitions"> <value> <!-- 无需认证即可访问的静态资源,还可以添加其他 url --> /static/** = anon <!-- 除了上述忽略的资源,其他所有资源都需要认证后才能访问 --> /** = authc </value> </property> </bean>
接下来就需要定义 Realm 了,自定义的 Realm 集成自 AuthorizingRealm 类:
public class MyRealm extends AuthorizingRealm { @Autowired private UserService userService; /** * 验证权限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String loginName = SecurityUtils.getSubject().getPrincipal().toString(); if (loginName != null) { String userId = SecurityUtils.getSubject().getSession().getAttribute("userSessionId").toString(); // 权限信息对象,用来存放查出的用户的所有的角色及权限 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 用户的角色集合 ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal(); info.setRoles(shiroUser.getRoles()); info.addStringPermissions(shiroUser.getUrlSet()); return info; } return null; } /** * 认证回调函数,登录时调用 */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) { String username = (String) token.getPrincipal(); User user = new User(); sysuser.setUsername(username); try { List<SysUser> users = userService.findByNames(user); List<String> roleList= userService.selectRoleNameListByUserId(users.get(0).getId()); if (users.size() != 0) { String pwd = users.get(0).getPassword(); // 当验证都通过后,把用户信息放在 session 里 Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("userSession", users.get(0)); session.setAttribute("userSessionId", users.get(0).getId()); session.setAttribute("userRoles", org.apache.commons.lang.StringUtils.join(roleList,",")); return new SimpleAuthenticationInfo(username,users.get(0).getPassword()); } else { // 没找到该用户 throw new UnknownAccountException(); } } catch (Exception e) { System.out.println(e.getMessage()); } return null; } /** * 更新用户授权信息缓存. */ public void clearCachedAuthorizationInfo(PrincipalCollection principals) { super.clearCachedAuthorizationInfo(principals); } /** * 更新用户信息缓存. */ public void clearCachedAuthenticationInfo(PrincipalCollection principals) { super.clearCachedAuthenticationInfo(principals); } /** * 清除用户授权信息缓存. */ public void clearAllCachedAuthorizationInfo() { getAuthorizationCache().clear(); } /** * 清除用户信息缓存. */ public void clearAllCachedAuthenticationInfo() { getAuthenticationCache().clear(); } /** * 清空所有缓存 */ public void clearCache(PrincipalCollection principals) { super.clearCache(principals); } /** * 清空所有认证缓存 */ public void clearAllCache() { clearAllCachedAuthenticationInfo(); clearAllCachedAuthorizationInfo(); } }
最后定义一个用户登录的控制器,接受用户的登录请求:
@Controller public class UserController { /** * 用户登录 */ @PostMapping("/login") public String login(@Valid User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){ try { if(bindingResult.hasErrors()){ return "login"; } //使用权限工具进行认证,登录成功后跳到 shiroFilter bean 中定义的 successUrl SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword())); return "redirect:index"; } catch (AuthenticationException e) { redirectAttributes.addFlashAttribute("message","用户名或密码错误"); return "redirect:login"; } } /** * 注销登录 */ @GetMapping("/logout") public String logout(RedirectAttributes redirectAttributes ){ SecurityUtils.getSubject().logout(); return "redirect:login"; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍Springboot 整合shiro实现权限控制的方法,包括了Springboot 整合shiro实现权限控制的方法的使用技巧和注意事项,需要的朋友参考一下 Author:jeffrey Date:2019-04-08 一、开发环境: 1、mysql - 5.7 2、navicat(mysql客户端管理工具) 3、idea 2017.2 4、jdk8 5、tomcat 8.5 6、s
本页内容包括: 模块和源文件 访问级别 访问级别的使用原则 默认访问级别 单目标应用程序的访问级别 Framework的访问级别 访问控制语法 自定义类型 元组类型 函数类型 枚举类型 原始值和关联值 嵌套类型 子类 常量、变量、属性、下标 Getter和Setter 初始化 默认初始化方法 结构体的默认成员初始化方法 协议 协议继承 协议一致性 扩展 协议的扩展 泛型 类型别名 访问控制可以限定
数据只能由所属的智能合约读写,智能合约默认无法读写其他智能合约的数据。 为了方便用户操作,使用智能合约的私有对象作为数据对象,系统通过反射,获取私有对象所属的智能合约和对象名。其他智能合约无法创建和获取该智能合约的私有对象,就无法读写对应的数据。 如果智能合约希望自己的数据能够被其他智能合约读写,需要智能合约主动提供数据操作接口,其他智能合约通过引用该合约,调用相应接口,从而操作相应数据。 智能合
我正在开发一个基于REST的web应用程序,其中REST服务集成了Apache shiro,以执行基本身份验证和基于角色的授权。 现在,我想通过方法级别的权限配置(REST情况下的微服务)来增强授权功能。如果我没有错的话,Apache shiro提供了HttpMethodPermissionFilter类,该类可以用作过滤器,根据其HTTP方法(GET、POST、DELETE、HEAD等)限制传入
本文向大家介绍SpringBoot中整合Shiro实现权限管理的示例代码,包括了SpringBoot中整合Shiro实现权限管理的示例代码的使用技巧和注意事项,需要的朋友参考一下 之前在 SSM 项目中使用过 shiro,发现 shiro 的权限管理做的真不错,但是在 SSM 项目中的配置太繁杂了,于是这次在 SpringBoot 中使用了 shiro,下面一起看看吧 一、简介 Apache Sh
本文向大家介绍详解spring整合shiro权限管理与数据库设计,包括了详解spring整合shiro权限管理与数据库设计的使用技巧和注意事项,需要的朋友参考一下 之前的文章中我们完成了基础框架的搭建,现在基本上所有的后台系统都逃不过权限管理这一块,这算是一个刚需了。现在我们来集成shiro来达到颗粒化权限管理,也就是从连接菜单到页面功能按钮,都进行权限都验证,从前端按钮的显示隐藏,到后台具体功能