授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限。

如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等。

一、用户权限模型

为实现一个较为灵活的用户权限数据模型,通常把用户信息单独用一个实体表示,用户权限信息用两个实体表示。

  1. 用户信息用 LoginAccount 表示,最简单的用户信息可能只包含用户名 loginName 及密码 password 两个属性。实际应用中可能会包含用户是否被禁用,用户信息是否过期等信息。
  2. 用户权限信息用 Role 与 Permission 表示,Role 与 Permission 之间构成多对多关系。Permission 可以理解为对一个资源的操作,Role 可以简单理解为 Permission 的集合。
  3. 用户信息与 Role 之间构成多对多关系。表示同一个用户可以拥有多个 Role,一个 Role 可以被多个用户所拥有。

权限声明及粒度

Shiro权限声明通常是使用以冒号分隔的表达式。就像前文所讲,一个权限表达式可以清晰的指定资源类型,允许的操作。同时,Shiro权限表达式支持简单的通配符,可以更加灵活的进行权限设置。

下面以实例来说明权限表达式。

可查询用户数据

User:view

可查询或编辑用户数据

User:view,edit

可对用户数据进行所有操作

User:*或 user

可编辑id为123的用户数据

User:edit:123

授权处理过程

认证通过后接受 Shiro 授权检查,授权验证时,需要判断当前角色是否拥有该权限。

只有授权通过,才可以访问受保护 URL 对应的资源,否则跳转到“未经授权页面”。

如果我们自定义Realm实现,比如我后面的例子中,自定义了ShiroDbRealm类,当访问被@RequiresPermissions注解的方法时,会先执行ShiroDbRealm.doGetAuthorizationInfo()进行授权。

[java] view plaincopy
  1. <span style="font-size:18px">@Controller
  2. @RequestMapping(value = "/user")
  3. public class UserController {
  4. @Resource(name="userService")
  5. private IUserService userService;
  6. /**
  7. * 测试权限
  8. * 只有拥有 user:create权限,才能进行注册
  9. * @param user
  10. * @return
  11. */
  12. @RequestMapping(value = "/register")
  13. @ResponseBody
  14. @RequiresPermissions("user:create")
  15. public boolean register(User user){
  16. return userService.register(user);
  17. }</span>

二、授权实现

Shiro支持三种方式实现授权过程:

  • 编码实现
  • 注解实现
  • JSP Taglig实现

1、基于编码的授权实现

1、基于权限对象的实现

创建org.apache.shiro.authz.Permission的实例,将该实例对象作为参数传递给Subject.isPermitted()进行验证。

[java] view plaincopy
  1. Permission printPermission = new PrinterPermission("laserjet4400n", "print");
  2. Subject currentUser = SecurityUtils.getSubject();
  3. if (currentUser.isPermitted(printPermission)) {
  4. //show the Print button
  5. } else {
  6. //don't show the button?  Grey it out?
  7. }

2基于字符串的实现

相比笨重的基于对象的实现方式,基于字符串的实现便显得更加简洁。

[java] view plaincopy
  1. Subject currentUser = SecurityUtils.getSubject();
  2. if (currentUser.isPermitted("printer:print:laserjet4400n")) {
  3. //show the Print button
  4. } else {
  5. //don't show the button?  Grey it out?
  6. }

使用冒号分隔的权限表达式是org.apache.shiro.authz.permission.WildcardPermission默认支持的实现方式。

这里分别代表了资源类型:操作:资源ID

2、基于注解的授权实现

Shiro注解支持AspectJ、Spring、Google-Guice等,可根据应用进行不同的配置。

相关的注解:

@RequiresAuthentication

可以用户类/属性/方法,用于表明当前用户需是经过认证的用户。

[java] view plaincopy
  1. @RequiresAuthentication
  2. public void updateAccount(Account userAccount) {
  3. //this method will only be invoked by a
  4. //Subject that is guaranteed authenticated
  5. ...
  6. }

@RequiresPermissions

当前用户需拥有制定权限

[java] view plaincopy
  1. @RequiresPermissions("account:create")
  2. public void createAccount(Account account) {
  3. //this method will only be invoked by a Subject
  4. //that is permitted to create an account
  5. ...
  6. }

3、基于JSP TAG的授权实现

Shiro提供了一套JSP标签库来实现页面级的授权控制。

在使用Shiro标签库前,首先需要在JSP引入shiro标签:

[html] view plaincopy
  1. <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

hasRole标签

验证当前用户是否属于该角色

[html] view plaincopy
  1. <shiro:hasRole name="administrator">
  2. <a href="admin.jsp">Administer the system</a>
  3. </shiro:hasRole>

hasPermission标签

验证当前用户是否拥有制定权限

[html] view plaincopy
  1. <shiro:hasPermission name="user:create">
  2. <a href="createUser.jsp">Create a new User</a>
  3. </shiro:hasPermission>

三、Shiro授权的内部处理机制

1、在应用程序中调用授权验证方法(Subject的isPermitted*或hasRole*等)

2、Sbuject会委托应用程序设置的securityManager实例调用相应的isPermitted*或hasRole*方法。

3、接下来SecurityManager会委托内置的Authorizer的实例(默认是ModularRealmAuthorizer类的实例,类似认证实例)调用相应的授权方法。

4、每一个Realm将检查是否实现了相同的Authorizer 接口。然后,将调用Reaml自己的相应的授权验证方法。

四、授权代码

UserController:处理用户登录后的请求(注册)

[java] view plaincopy
  1. package org.shiro.demo.controller;
  2. import javax.annotation.Resource;
  3. import org.apache.shiro.authz.annotation.RequiresPermissions;
  4. import org.apache.shiro.authz.annotation.RequiresRoles;
  5. import org.shiro.demo.entity.User;
  6. import org.shiro.demo.service.IUserService;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.ResponseBody;
  10. @Controller
  11. @RequestMapping(value = "/user")
  12. public class UserController {
  13. @Resource(name="userService")
  14. private IUserService userService;
  15. /**
  16. * 测试权限
  17. * 只有拥有 user:create 权限,才能进行注册
  18. * @param user
  19. * @return
  20. */
  21. @RequestMapping(value = "/register")
  22. @ResponseBody
  23. @RequiresPermissions("user:create")
  24. public boolean register(User user){
  25. return userService.register(user);
  26. }
  27. /**
  28. * 测试角色
  29. * 只有拥有 administrator 角色,才能跳转到register页面
  30. * @return
  31. */
  32. @RequestMapping(value = "/toRegister")
  33. @RequiresRoles("administrator")
  34. public String toRegister(){
  35. return "/system/user/register";
  36. }
  37. }

ShiroDbRealm:自定义的指定Shiro验证用户授权的类

[java] view plaincopy
  1. <span style="font-size:18px">packageorg.shiro.demo.service.realm;
  2. importjava.util.ArrayList;
  3. importjava.util.List;
  4. importjavax.annotation.Resource;
  5. importorg.apache.commons.lang.StringUtils;
  6. importorg.apache.shiro.authc.AuthenticationException;
  7. importorg.apache.shiro.authc.AuthenticationInfo;
  8. importorg.apache.shiro.authc.AuthenticationToken;
  9. importorg.apache.shiro.authc.SimpleAuthenticationInfo;
  10. importorg.apache.shiro.authc.UsernamePasswordToken;
  11. importorg.apache.shiro.authz.AuthorizationException;
  12. importorg.apache.shiro.authz.AuthorizationInfo;
  13. importorg.apache.shiro.authz.SimpleAuthorizationInfo;
  14. importorg.apache.shiro.realm.AuthorizingRealm;
  15. importorg.apache.shiro.subject.PrincipalCollection;
  16. importorg.shiro.demo.entity.Permission;
  17. importorg.shiro.demo.entity.Role;
  18. importorg.shiro.demo.entity.User;
  19. importorg.shiro.demo.service.IUserService;
  20. /**
  21. * 自定义的指定Shiro验证用户登录的类
  22. * @author TCH
  23. *
  24. */
  25. publicclass ShiroDbRealm extends AuthorizingRealm{
  26. //@Resource(name="userService")
  27. privateIUserService userService;
  28. publicvoid setUserService(IUserService userService) {
  29. this.userService= userService;
  30. }
  31. /**
  32. * 为当前登录的Subject授予角色和权限
  33. * @see 经测试:本例中该方法的调用时机为需授权资源被访问时
  34. * @see经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例未启用AuthorizationCache
  35. * @seeweb层可以有shiro的缓存,dao层可以配有hibernate的缓存(后面介绍)
  36. */
  37. protectedAuthorizationInfo doGetAuthorizationInfo(
  38. PrincipalCollectionprincipals) {
  39. //获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()
  40. Stringaccount = (String) super.getAvailablePrincipal(principals);
  41. List<String>roles = new ArrayList<String>();
  42. List<String>permissions = new ArrayList<String>();
  43. //从数据库中获取当前登录用户的详细信息
  44. Useruser = userService.getByAccount(account);
  45. if(user!= null){
  46. //实体类User中包含有用户角色的实体类信息
  47. if(user.getRoles() != null && user.getRoles().size() > 0) {
  48. //获取当前登录用户的角色
  49. for(Role role : user.getRoles()) {
  50. roles.add(role.getName());
  51. //实体类Role中包含有角色权限的实体类信息
  52. if(role.getPmss() != null && role.getPmss().size() > 0) {
  53. //获取权限
  54. for(Permission pmss : role.getPmss()) {
  55. if(!StringUtils.isEmpty(pmss.getPermission())){
  56. permissions.add(pmss.getPermission());
  57. }
  58. }
  59. }
  60. }
  61. }
  62. }else{
  63. thrownew AuthorizationException();
  64. }
  65. //为当前用户设置角色和权限
  66. SimpleAuthorizationInfoinfo = new SimpleAuthorizationInfo();
  67. info.addRoles(roles);
  68. info.addStringPermissions(permissions);
  69. returninfo;
  70. }
  71. }</span>

转载于:https://www.cnblogs.com/lzlblogs/p/5973535.html

shiro中基于注解实现的权限认证过程相关推荐

  1. 将 Shiro 作为应用的权限基础 三:基于注解实现的授权认证过程

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限等等. 一.用户权限模型 为实现一个较为灵活的用户权限数据模 ...

  2. 校内实验六,Windows系统中基于用户名密码的身份认证

    Windows系统中基于用户名密码的身份认证 一.实验目的 二.实验环境及原理 三.实验内容 1 检查和删除不必要的账户 2 禁用guest用户. 3 设置帐户/密码登录身份认证 4 匿名Admini ...

  3. SpringSecurity实战:基于mysql自定义SpringSecurity权限认证规则

    上文<Spring Security 源码分析:Spring Security 授权过程>已经详细分析了Spring Security 授权过程,接下来通过上文的授权过程我们可以自定义授权 ...

  4. Spring中基于注解@AspectJ的AOP实现

    @AspectJ 作为通过 Java 5 注释注释的普通的 Java 类,它指的是声明aspects 的一种风格.通过在基于架构的 XML 配置文件中包含以下元素,@AspectJ 支持是可用的. a ...

  5. shiro学习(11):servelet实现权限认证二

    工具idea 先看看数据库 shiro_role_permission 数据 shiro_user shiro_user_role 数据 在pom.xml里面添加 <dependency> ...

  6. shiro学习(10):servelet实现权限认证一

    工具idea 先看看数据库 shiro_role_permission 数据 shiro_user shiro_user_role 数据 在pom.xml里面添加 <dependency> ...

  7. 详解比springSecurity和shiro更简单优雅的轻量级Sa-Token框架,比如登录认证,权限认证,单点登录,OAuth2.0,分布式Session会话,微服务网关鉴权

    文章目录 1. 技术选型 2. Sa-Token概述 2.1 简单介绍 2.2 登录认证 2.3 权限认证 3. 功能一览 4. Sa-Token使用 4.1 引入Sa-Token依赖 4.2 Sa- ...

  8. 再见Spring Security!推荐一款功能强大的权限认证框架,用起来够优雅!

    ‍ ‍在我们做SpringBoot项目的时候,认证授权是必不可少的功能!我们经常会选择Shiro.Spring Security这类权限认证框架来实现,但这些框架使用起来有点繁琐,而且功能也不够强大. ...

  9. 探索 Sa-Token (三) 权限认证原理

    前言:前一篇文章我们做了权限认证,看着就用一个注解就是实现权限认证,那么他的底层原理怎么实现的呢?家人们,不要着急,让我慢慢道来. # SaCheckPermission 注解 package cn. ...

最新文章

  1. 机器学习 数据量不足问题----1 做好特征工程 2 不要用太多的特征 3 做好交叉验证 使用线性svm...
  2. @PropertySource与@ConfigurationProperties多种方式读取配置文件详解,附带@PropertySources使用说明
  3. Spring IoC 源码系列(五)getBean 流程分析
  4. 荣幸参加 微软 Teched 2012 会议
  5. HBase原理-要弄懂的sequenceId
  6. socket 网络 编程
  7. Android开发进阶1 思维改变 如何知道我需要学什么(上)
  8. Qt文档阅读笔记-QGraphicsEffect::draw(QPainter *painter)官方解析与实例
  9. san服务器型号,san存储服务器配置
  10. restapi(3)- MongoDBEngine : MongoDB Scala编程工具库
  11. json的的解析方法
  12. 论文数模真的好难?那是你还不会Matlab!
  13. 2019python二级真题_2019年3月二级python真题,上岸必备!
  14. ADO连接MySql数据库之通过连接字符串
  15. python 绘制qq图
  16. C语言详解系列——函数的认识(4)函数的声明与定义,简单练习题
  17. 竟可监控员工离职倾向!一系统引发大争议
  18. 深入理解互斥锁的实现
  19. 转载 Fluent中的压力分类
  20. Linux下memc-nginx-module模块指令说明+memcached支持的命令

热门文章

  1. sqoop export hive数据同步到oracle的用法
  2. mac M1 安装navicat亲测有效
  3. Gamemaker studio2经验(3)——昼夜更替效果实现
  4. Gamemaker studio2经验(4)——打字机效果
  5. Switch上gamemaker,6.11发售,可不写代码创造游戏
  6. 如何去掉复制mobi文件代码里的一些符号
  7. 永磁材料介绍和ANSYS Workbench永磁体仿真
  8. IE中点击链接下载EXCEL文件直接以乱码方式打开解决
  9. 常见的图像重采样算法
  10. Centos6.6下编译安装Apache2.2.31