前言:
  之前简单集成了springmvc和shiro用于后台管理平台的权限控制, 设计思路非常的优美, 而且编程确实非常的方便和简洁. 唯一的不足, 我觉得配置稍有些繁琐. 当时我有个小想法, 觉得可以写个更小巧版的shiro, 用于权限控制.
  因为shiro本身不涉及权限的数据模型, 而且权限控制这块也只是它的一小部分功能点. 因此剥离后的工作量, 预计不是很大.

相关文章列表:
  1. springmvc简单集成shiro 
  2. 利用Aspectj实现Oval的自动参数校验

设计目标
  首先来讲讲定位吧, Shiro本身是一个安全组件, 可以复用. 但是我这个版本, 倾向于半成品. 它属于一种设计思路, 多少和业务有些耦合, 它有一定的借鉴作用, 其他简易项目可以拿去copy/paste, 然后修改下代码, 就能使用上的, ^_^.
  列一下设计目标吧:
  1. 只支持权限校验, 不涉及认证
  2. 支持role/permission的注解校验(包括简单的与或操作)
  就这么简单了, ^_^.

实践:
  整个小框架, 是基于springmvc环境下, 其数据存储于http session中, 但除此以外, 和外界再无瓜葛, ^_^.
  它的核心就一个工具类, 一个切面类, 两个注解, 非常的简洁.
  权限注解类的引入:

// *) 逻辑与或
public enum MyLogic {AND,OR;
}// *) 定义权限校验注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRequiresPermissions {String[] value();MyLogic logic() default MyLogic.AND;
}// *) 定义角色校验注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRequiresRoles {String[] value();MyLogic logic() default MyLogic.AND;
}

  工具类引入:

@Getter
public class MyAuthorizeInfo {private Set<String> roles = new TreeSet<String>();private Set<String> permissions = new TreeSet<String>();public void addRole(String role) {roles.add(role);}public void addPermission(String permission) {permissions.add(permission);}}public class MyShiroHelper {private static final String MY_SHIRO_AUTHRIZE_KEY = "my_shiro_authorize_key";// 授权权限列表public static void authorize(MyAuthorizeInfo authorizeInfo) {HttpSession session = getSession();session.setAttribute(MY_SHIRO_AUTHRIZE_KEY, authorizeInfo);}// 验证角色public static boolean validateRoles(String[] roles, MyLogic logic) throws Exception {if ( roles == null || roles.length == 0 ) {return true;}try {HttpSession session = getSession();MyAuthorizeInfo authorizeInfo = (MyAuthorizeInfo)session.getAttribute(MY_SHIRO_AUTHRIZE_KEY);if ( authorizeInfo == null ) {return false;}return evaluateExpression(roles, logic, authorizeInfo.getRoles());} catch (Exception e) {throw new Exception("permission invalid state");} finally {}}// 验证权限public static boolean validatePermssion(String[] permissions, MyLogic logic) throws Exception {if ( permissions == null || permissions.length == 0 ) {return true;}try {HttpSession session = getSession();MyAuthorizeInfo authorizeInfo = (MyAuthorizeInfo)session.getAttribute(MY_SHIRO_AUTHRIZE_KEY);if ( authorizeInfo == null ) {return false;}return evaluateExpression(permissions, logic, authorizeInfo.getPermissions());} catch (Exception e) {throw new Exception("permission invalid state");} finally {}}// *) 与或操作, 布尔表达式的计算public static boolean evaluateExpression(String[] values, MyLogic logic, Set<String> sets) {if ( MyLogic.AND == logic ) {for ( String val : values ) {if ( !sets.contains(val) ) {return false;}}return true;} else if ( MyLogic.OR == logic ) {for ( String val : values ) {if ( sets.contains(val) ) {return true;}}return false;}return true;}// *) 获取Http Sessionprivate static HttpSession getSession() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();return request.getSession();}}

  最后是切面类的引入:

@Aspect
@Component
public class MyShiroAdvice {/*** 定义切点, 用于权限的校验*/@Pointcut("@annotation(com.springapp.mvc.myshiro.MyRequiresPermissions)")public void checkPermissions() {}/*** 定义切点, 用于角色的校验*/@Pointcut("@annotation(com.springapp.mvc.myshiro.MyRequiresRoles)")public void checkRoles() {}@Before("checkPermissions()")public void doCheckPermission(JoinPoint jp) throws Exception {// *) 获取对应的注解MyRequiresPermissions mrp = extractAnnotation((MethodInvocationProceedingJoinPoint)jp,MyRequiresPermissions.class);try {if ( !MyShiroHelper.validatePermssion(mrp.value(), mrp.logic()) ) {throw new Exception("access disallowed");}} catch (Exception e) {throw new Exception("invalid state");}}@Before("checkRoles()")public void doCheckRole(JoinPoint jp) throws Exception {// *) 获取对应的注解MyRequiresRoles mrp = extractAnnotation((MethodInvocationProceedingJoinPoint)jp,MyRequiresRoles.class);try {if ( !MyShiroHelper.validateRoles(mrp.value(), mrp.logic()) ) {throw new Exception("access disallowed");}} catch (Exception e) {throw new Exception("invalid state");}}// *) 获取注解信息private static <T extends Annotation> T extractAnnotation(MethodInvocationProceedingJoinPoint mp, Class<T> clazz) throws Exception {Field proxy = mp.getClass().getDeclaredField("methodInvocation");proxy.setAccessible(true);ReflectiveMethodInvocation rmi = (ReflectiveMethodInvocation) proxy.get(mp);Method method = rmi.getMethod();return (T) method.getAnnotation(clazz);}}

  这边为了简洁, 对异常类没有做细分处理.

实战:
  那如何集成, 并使用上述的小shiro框架呢?
  首先激活Aspectj, 同时把注解类纳入到spring容器中.

<aop:aspectj-autoproxy proxy-target-class="true"/>
<context:component-scan base-package="com.xxx.myshiro"/> <!-- 切面类所在的package -->

  而在具体的实战中, 可以写个简单的测试RestController类, 来演示下整个流程.

@Controller
@RequestMapping("/")
public class HelloController {@RequestMapping(value="/login", method={RequestMethod.POST, RequestMethod.GET})@ResponseBodypublic String login() {// 1) 完成登陆验证// TODO// 2) 查询权限信息// TODO// 3) 注册权限信息MyAuthorizeInfo authorizeInfo = new MyAuthorizeInfo();authorizeInfo.addRole("admin");authorizeInfo.addPermission("blog:write");authorizeInfo.addPermission("blog:read");// *) 授权赋予MyShiroHelper.authorize(authorizeInfo);return "ok";}@RequestMapping(value = "/test1", method = {RequestMethod.GET, RequestMethod.POST})@ResponseBody@MyRequiresPermissions(value={"blog:write", "blog:update"}, logic=MyLogic.AND)public String test1() {return "test1";}@RequestMapping(value = "/test2", method = {RequestMethod.GET, RequestMethod.POST})@ResponseBody@MyRequiresPermissions(value={"blog:write", "blog:update"}, logic=MyLogic.OR)public String test2() {return "test2";}}

  注: 关注下login接口, 这里完成了登陆和授权工作.
  这个小框架, 把用户登陆和权限数据模型的设计获取交给了业务开发者, 只保留了权限校验.

测试:
  在完成登陆login之后
  1. 调用/test1, 访问受限(需要blog:write && blog:update, 但是只有blog:write权限)
  2. 调用/test2, 访问通过(需要blog:write || blog:update, 有blog:write权限)

总结:
  在抛离认证和账号管理之后, 其实这个权限校验小框架, 其实非常的漂亮和实用. 真正在业务开发时, 遇到小的项目, 其实可以直接使用, 而并非要选择较重的shiro.
  当然在权限校验这块, 都是针对静态资源的权限校验, 若遇到动态权限校验(比如用户对自己编辑的文章有编辑权限, 其他用户没), 还是有所不足的.
  不过, 如果有复杂的权限表达式计算需求的, 这个不算什么难点, 可以借助Groovy轻松实现.

转载于:https://www.cnblogs.com/mumuxinfei/p/9339086.html

类Shiro权限校验框架的设计和实现相关推荐

  1. Apache Shiro权限控制框架简介

    Apache Shiro权限控制框架简介 要想实现权限控制,可以自己写代码实现,蓄力都的权限控制可以通过过滤器Filter实现,细粒度的权限控制是基于代理对象结合自定义的注解和反射技术来实现,反射技术 ...

  2. spring整合shiro权限管理与数据库设计

    之前的文章中我们完成了基础框架的搭建,现在基本上所有的后台系统都逃不过权限管理这一块,这算是一个刚需了.现在我们来集成shiro来达到颗粒化权限管理,也就是从连接菜单到页面功能按钮,都进行权限都验证, ...

  3. nginx反向代理和shiro权限校验产生的404问题

    问题描述: 我们的项目A(以下简称A)用了shiro做权限校验,nginx做反向代理,在另一个项目B(以下简称B)中点击某个A的链接时实现单点登录并会跳转到该路径.跳转到原路径的时候nginx报了40 ...

  4. shiro权限鉴定框架

    如果你看到这篇文章,你一定知道shiro是干嘛用的,如果真的真的不知道... 那么请先移步:shiro . . . 好了,聪明的你现在一定知道shiro是干嘛用的了,你应该知道,shiro不是web框 ...

  5. @vaild权限校验框架配合java正则表达式

    样例 正则表达式示例 正则表达式简单笔记 @Data class ReadParam{@Pattern(regexp = "(\\w{1,10}@\\w{1,10}\\.\\w{1,10}) ...

  6. shiro放行_Shiro框架详解 tagline

    部分面试资料链接:https://pan.baidu.com/s/1qDb2YoCopCHoQXH15jiLhA 密码:jsam 想获得全部面试必看资料,关注公众号,大家可以在公众号后台回复" ...

  7. 自定义注解实现RBAC权限校验,不要再说你不会了

    目录 1.前言 2.实现思路 3.编码实战 3.1.准备 3.2.数据库表准备 3.3.自定义注解 3.4.拦截器 3.5.接口使用 3.6.测试 3.7.结论 4.结束语 1.前言 学过Spring ...

  8. SSM集成shiro权限管理

    这几天在学习了shiro权限管理框架,在刚开始的时候学的时候因为这个配置问题困扰了我很长时间,所以在这篇文章我整合了自己用SSM搭建shiro权限框架的过程. 1.配置 1.1jar包 在项目配置开始 ...

  9. springboot shiro权限管理

    集成shiro大概分这么一个步骤: (一) pom.xml中添加Shiro依赖: (二) 注入Shiro Factory和SecurityManager. (三) 身份认证 (四) 权限控制 一:po ...

  10. 应用框架的设计与实现学习手札系列(持续更新)

    应用框架的设计与实现学习手札 类工厂服务 应用框架的设计与实现学习手札之类工厂服务--反射 转载于:https://www.cnblogs.com/stwyhm/archive/2006/08/14/ ...

最新文章

  1. 怎么把两个div一左一右放
  2. [Leetcode][第63题][JAVA][不同路径2][动态规划][压缩路径]
  3. ICML2020 | 一行代码就能实现的测试集上分技巧
  4. VS2010 MFC多文档中的工具栏CMFCToolBar停靠的问题
  5. C#LeetCode刷题之#367-有效的完全平方数(Valid Perfect Square)
  6. 10 个 Python 初学者必知编码小技巧
  7. Forms(The Definitive Guild to Django)
  8. 贝叶斯分类与贝叶斯网络
  9. Linux服务器上安装node.js
  10. django xadmin 安装和使用
  11. ros运行cpp文件
  12. Mac - 当前位置打开终端
  13. 【Elasticsearch教程8】Mapping字段类型之keyword
  14. C4D阿诺德Arnold渲染器:C4DtoA mac版(支持c4d r23)
  15. ios学习笔记之三- iPhone模拟器基本操作
  16. 互动媒体大作业——绘画系统
  17. ip_forward与路由转发
  18. 首席架构师推荐:史上最全微服务架构简史详解!
  19. 如何防止游戏检测出模拟器_【游戏教程】如何在模拟器运行完美世界
  20. pandas.pivot()函数的使用

热门文章

  1. 可能是最全的一份 2017 年中国移动互联网年度报告(建议收藏)
  2. 浪潮工程师窃取公司CPU、硬盘在咸鱼挂卖被阿里发现,判处有期徒刑3年3个月...
  3. XML非法字符的处理
  4. [bzoj4945][Noi2017]游戏
  5. Divide Groups(分组)(二分图染色)
  6. 6月14号=》136页-145页
  7. ajax 的post方法用例(带循环)
  8. 中文问题-Mobile-UrlEncode
  9. 重装上阵,全新的「极光开发者」公众号来了,关注送大礼!
  10. ARM体系结构的特点