`
234390216
  • 浏览: 10187514 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
博客专栏
A5ee55b9-a463-3d09-9c78-0c0cf33198cd
Oracle基础
浏览量:460491
Ad26f909-6440-35a9-b4e9-9aea825bd38e
springMVC介绍
浏览量:1771181
Ce363057-ae4d-3ee1-bb46-e7b51a722a4b
Mybatis简介
浏览量:1394990
Bdeb91ad-cf8a-3fe9-942a-3710073b4000
Spring整合JMS
浏览量:393701
5cbbde67-7cd5-313c-95c2-4185389601e7
Ehcache简介
浏览量:678008
Cc1c0708-ccc2-3d20-ba47-d40e04440682
Cas简介
浏览量:529018
51592fc3-854c-34f4-9eff-cb82d993ab3a
Spring Securi...
浏览量:1178293
23e1c30e-ef8c-3702-aa3c-e83277ffca91
Spring基础知识
浏览量:460921
4af1c81c-eb9d-365f-b759-07685a32156e
Spring Aop介绍
浏览量:149910
2f926891-9e7a-3ce2-a074-3acb2aaf2584
JAXB简介
浏览量:66654
社区版块
存档分类
最新评论

Spring Security(17)——基于方法的权限控制

阅读更多

基于方法的权限控制

 

目录

1.1     intercept-methods定义方法权限控制

1.2     使用pointcut定义方法权限控制

1.3     使用注解定义方法权限控制

1.3.1    JSR-250注解

1.3.2    @Secured注解

1.3.3    支持表达式的注解

1.4     方法权限控制的拦截器

1.4.1    MethodSecurityInterceptor

1.4.2    AspectJMethodSecurityInterceptor

 

       之前介绍的都是基于URL的权限控制,Spring Security同样支持对于方法的权限控制。可以通过intercept-methods对某个bean下面的方法进行权限控制,也可以通过pointcut对整个Service层的方法进行统一的权限控制,还可以通过注解定义对单独的某一个方法进行权限控制。

 

1.1     intercept-methods定义方法权限控制

       intercept-methods是需要定义在bean元素下的,通过它可以定义对当前的bean的某些方法进行权限控制,具体方法是使用其下的子元素protect进行定义的。protect元素需要指定两个属性,accessmethodmethod表示需要拦截的方法名称,可以使用通配符,access表示执行对应的方法需要拥有的权限,多个权限之间可以使用逗号分隔。

   <bean id="userService" class="com.xxx.service.impl.UserServiceImpl">

      <security:intercept-methods>

         <security:protect access="ROLE_USER" method="find*"/>

         <security:protect access="ROLE_ADMIN" method="add*"/>

         <security:protect access="ROLE_ADMIN" method="update*"/>

         <security:protect access="ROLE_ADMIN" method="delete*"/>

      </security:intercept-methods>

   </bean>

 

       在上面的配置中表示在执行UserServiceImpl的方法名以find开始的方法时需要当前用户拥有ROLE_USER的权限,在执行方法名以addupdatedelete开始的方法时需要拥有ROLE_ADMIN的权限。当访问被拒绝时还是交由ExceptionTranslationFilter处理,这也就意味着如果用户未登录则会引导用户进行登录,否则默认将返回403错误码到客户端。

 

1.2     使用pointcut定义方法权限控制

       基于pointcut的方法权限控制是通过global-method-security下的protect-pointcut来定义的。可以在global-method-security元素下定义多个protect-pointcut以对不同的pointcut使用不同的权限控制。

   <security:global-method-security>

      <security:protect-pointcut access="ROLE_READ" expression="execution(* com.elim.*..*Service.find*(..))"/>

      <security:protect-pointcut access="ROLE_WRITE" expression="execution(* com.elim.*..*Service.*(..))"/>

   </security:global-method-security>

 

       上面的定义表示我们在执行com.elim包或其子包下任意以Service结尾的类,其方法名以find开始的所有方法时都需要用户拥有ROLE_READ的权限,对于com.elim包或其子包下任意以Service结尾的类的其它方法在执行时都需要ROLE_WRITE的权限。需要注意的是对应的类需要是定义在ApplicationContext中的bean才行。此外同对于URL的权限控制一样,当定义多个protect-pointcut时更具有特性的应当先定义,因为在pointcut匹配的时候是按照声明顺序进行匹配的,一旦匹配上了后续的将不再进行匹配了。

 

1.3     使用注解定义方法权限控制

       基于注解的方法权限控制也是需要通过global-method-security元素定义来进行启用的。Spring Security在方法的权限控制上支持三种类型的注解,JSR-250注解、@Secured注解和支持表达式的注解。这三种注解默认都是没有启用的,需要单独通过global-method-security元素的对应属性进行启用。

 

1.3.1   JSR-250注解

       要使用JSR-250注解,首先我们需要通过设置global-method-security元素的jsr250-annotation=”enabled”来启用基于JSR-250注解的支持,默认为disabled

       <security:global-method-security jsr250-annotations="enabled"/>

 

       此外,还需要确保添加了jsr250-api到我们的类路径下。之后就可以在我们的Service方法上使用JSR-250注解进行权限控制了。

@Service

@RolesAllowed("ROLE_ADMIN")

public class UserServiceImpl implements UserService {

 

   public void addUser(User user) {

      System.out.println("addUser................" + user);

   }

 

   public void updateUser(User user) {

      System.out.println("updateUser.............." + user);

   }

 

   @RolesAllowed({"ROLE_USER", "ROLE_ADMIN"})

   public User find(int id) {

      System.out.println("find user by id............." + id);

      return null;

   }

 

   public void delete(int id) {

      System.out.println("delete user by id................");

   }

 

   @RolesAllowed("ROLE_USER")

   public List<User> findAll() {

      System.out.println("find all user...............");

      return null;

   }

 

}

 

       上面的代码表示执行UserServiceImpl里面所有的方法都需要角色ROLE_ADMIN,其中findAll()方法的执行需要ROLE_USER角色,而find()方法的执行对于ROLE_USER或者ROLE_ADMIN角色都可以。

 

       顺便介绍一下JSR-250中对权限支持的注解。

       RolesAllowed表示访问对应方法时所应该具有的角色。其可以标注在类上,也可以标注在方法上,当标注在类上时表示其中所有方法的执行都需要对应的角色,当标注在方法上表示执行该方法时所需要的角色,当方法和类上都使用了@RolesAllowed进行标注,则方法上的@RolesAllowed将覆盖类上的@RolesAllowed,即方法上的@RolesAllowed将对当前方法起作用。@RolesAllowed的值是由角色名称组成的数组。

       PermitAll表示允许所有的角色进行访问,也就是说不进行权限控制。@PermitAll可以标注在方法上也可以标注在类上,当标注在方法上时则只对对应方法不进行权限控制,而标注在类上时表示对类里面所有的方法都不进行权限控制。(1)当@PermitAll标注在类上,而@RolesAllowed标注在方法上时则按照@RolesAllowed将覆盖@PermitAll,即需要@RolesAllowed对应的角色才能访问。(2)当@RolesAllowed标注在类上,而@PermitAll标注在方法上时则对应的方法也是不进行权限控制的。(3)当在方法上同时使用了@PermitAll@RolesAllowed时先定义的将发生作用,而都定义在类上时则是反过来的,即后定义的将发生作用(这个没多大的实际意义,实际应用中不会有这样的定义)。

       DenyAll是和PermitAll相反的,表示无论什么角色都不能访问。@DenyAll只能定义在方法上。你可能会有疑问使用@DenyAll标注的方法无论拥有什么权限都不能访问,那还定义它干啥呢?使用@DenyAll定义的方法只是在我们的权限控制中不能访问,脱离了权限控制还是可以访问的。

 

1.3.2  @Secured注解

       @Secured是由Spring Security定义的用来支持方法权限控制的注解。它的使用也是需要启用对应的支持才会生效的。通过设置global-method-security元素的secured-annotations=”enabled”可以启用Spring Security对使用@Secured注解标注的方法进行权限控制的支持,其值默认为disabled

   <security:global-method-security secured-annotations="enabled"/>

 

@Service

public class UserServiceImpl implements UserService {

 

   @Secured("ROLE_ADMIN")

   public void addUser(User user) {

      System.out.println("addUser................" + user);

   }

 

   @Secured("ROLE_USER")

   public List<User> findAll() {

      System.out.println("find all user...............");

      return null;

   }

 

}

 

       在上面的代码中我们使用@Secured定义了只有拥有ROLE_ADMIN角色的用户才能调用方法addUser(),只有拥有ROLE_USER角色的用户才能调用方法findAll()

 

1.3.3   支持表达式的注解

       Spring Security中定义了四个支持使用表达式的注解,分别是@PreAuthorize@PostAuthorize@PreFilter@PostFilter。其中前两者可以用来在方法调用前或者调用后进行权限检查,后两者可以用来对集合类型的参数或者返回值进行过滤。要使它们的定义能够对我们的方法的调用产生影响我们需要设置global-method-security元素的pre-post-annotations=”enabled”,默认为disabled

   <security:global-method-security pre-post-annotations="disabled"/>

 

使用@PreAuthorize@PostAuthorize进行访问控制

       @PreAuthorize可以用来控制一个方法是否能够被调用。

@Service

public class UserServiceImpl implements UserService {

 

   @PreAuthorize("hasRole('ROLE_ADMIN')")

   public void addUser(User user) {

      System.out.println("addUser................" + user);

   }

 

   @PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN')")

   public User find(int id) {

      System.out.println("find user by id............." + id);

      return null;

   }

 

}

       在上面的代码中我们定义了只有拥有角色ROLE_ADMIN的用户才能访问adduser()方法,而访问find()方法需要有ROLE_USER角色或ROLE_ADMIN角色。使用表达式时我们还可以在表达式中使用方法参数。

public class UserServiceImpl implements UserService {

 

   /**

    * 限制只能查询Id小于10的用户

    */

   @PreAuthorize("#id<10")

   public User find(int id) {

      System.out.println("find user by id........." + id);

      return null;

   }

  

   /**

    * 限制只能查询自己的信息

    */

   @PreAuthorize("principal.username.equals(#username)")

   public User find(String username) {

      System.out.println("find user by username......" + username);

      return null;

   }

 

   /**

    * 限制只能新增用户名称为abc的用户

    */

   @PreAuthorize("#user.name.equals('abc')")

   public void add(User user) {

      System.out.println("addUser............" + user);

   }

 

}

       在上面代码中我们定义了调用find(int id)方法时,只允许参数id小于10的调用;调用find(String username)时只允许username为当前用户的用户名;定义了调用add()方法时只有当参数usernameabc时才可以调用。

 

       有时候可能你会想在方法调用完之后进行权限检查,这种情况比较少,但是如果你有的话,Spring Security也为我们提供了支持,通过@PostAuthorize可以达到这一效果。使用@PostAuthorize时我们可以使用内置的表达式returnObject表示方法的返回值。我们来看下面这一段示例代码。

   @PostAuthorize("returnObject.id%2==0")

   public User find(int id) {

      User user = new User();

      user.setId(id);

      return user;

   }

       上面这一段代码表示将在方法find()调用完成后进行权限检查,如果返回值的id是偶数则表示校验通过,否则表示校验失败,将抛出AccessDeniedException       需要注意的是@PostAuthorize是在方法调用完成后进行权限检查,它不能控制方法是否能被调用,只能在方法调用完成后检查权限决定是否要抛出AccessDeniedException

 

使用@PreFilter@PostFilter进行过滤

       使用@PreFilter@PostFilter可以对集合类型的参数或返回值进行过滤。使用@PreFilter@PostFilter时,Spring Security将移除使对应表达式的结果为false的元素。

   @PostFilter("filterObject.id%2==0")

   public List<User> findAll() {

      List<User> userList = new ArrayList<User>();

      User user;

      for (int i=0; i<10; i++) {

         user = new User();

         user.setId(i);

         userList.add(user);

      }

      return userList;

   }

 

       上述代码表示将对返回结果中id不为偶数的user进行移除。filterObject是使用@PreFilter@PostFilter时的一个内置表达式,表示集合中的当前对象。当@PreFilter标注的方法拥有多个集合类型的参数时,需要通过@PreFilterfilterTarget属性指定当前@PreFilter是针对哪个参数进行过滤的。如下面代码就通过filterTarget指定了当前@PreFilter是用来过滤参数ids的。

   @PreFilter(filterTarget="ids", value="filterObject%2==0")

   public void delete(List<Integer> ids, List<String> usernames) {

      ...

   }

 

1.4     方法权限控制的拦截器

       关于方法权限控制,Spring Security提供了两类AbstractSecurityInterceptor,基于AOP AllianceMethodSecurityInterceptor,和基于Aspectj继承自MethodSecurityInterceptorAspectJMethodSecurityInterceptor

 

1.4.1   MethodSecurityInterceptor

       当我们在使用基于NameSpace进行方法保护的配置时,Spring Security默认配置的就是MethodSecurityInterceptor。根据配置的不同,一个拦截器可能只是针对于一个bean,也可能是针对于多个bean的。MethodSecurityInterceptor使用一个MethodSecurityMetadataSource的实例来获取特定方法调用配置的ConfigAttribute。当我们在ApplicationContext配置文件中使用intercept-methods元素或protect-point元素定义需要保护的方法调用时,Spring Security内部默认会使用一个MapBasedMethodSecurityMetadataSource来保存在这些元素上定义的配置信息,保存的key是对应的方法名(可以是含有通配符的)。类似的使用JSR-250注解时将使用Jsr250MethodSecurityMetadataSource解析配置属性;使用@Secured注解时将使用SecuredAnnotationSecurityMetadataSource解析配置属性;使用pre-post-annotations时将使用PrePostAnnotationSecurityMetadataSource解析配置属性。

       MethodSecurityInterceptor是实现了MethodInterceptor接口的,所以我们在使用Spring Aop时,可以自己配置一个MethodSecurityInterceptorbean

 

   <!-- 自定义MethodSecurityInterceptor -->

   <bean id="methodSecurityInterceptor"

   class="org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor">

      <property name="authenticationManager" ref="authenticationManager" />

      <property name="accessDecisionManager" ref="accessDecisionManager" />

      <property name="afterInvocationManager" ref="afterInvocationManager" />

      <property name="securityMetadataSource">

         <security:method-security-metadata-source>

            <!-- 指定需要受保护的方法和需要的权限 -->

            <security:protect method="com.xxx.service.UserService.find*"

                access="ROLE_USER" />

            <security:protect method="com.xxx.service.UserService.delete*"

                access="ROLE_ADMIN" />

         </security:method-security-metadata-source>

      </property>

   </bean>

 

       定义了MethodSecurityInterceptor以后,我们需要类似AOP配置那样,配置哪些该MethodInterceptor需要拦截哪些方法的执行。这种可选配置是很多种的,因为我们这里只是拦截UserService中的具体方法,所以就采用基于bean name的自动代理。

   <!-- 基于bean的拦截 -->

   <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

      <property name="interceptorNames">

         <list>

            <value>methodSecurityInterceptor</value>

         </list>

      </property>

      <property name="beanNames">

         <list>

            <value>userService</value>

         </list>

      </property>

   </bean>

 

       按照上面的配置,我们在访问UserServicefind方法时就需要ROLE_USER的权限,而访问delete方法时则需要ROLE_ADMIN权限。

 

1.4.2   AspectJMethodSecurityInterceptor

       AspectJMethodSecurityInterceptor是继承自MethodSecurityInterceptor的,不同的是AspectJMethodSecurityInterceptor是用来支持AspectJJointPoint的,但在底层还是会把它封装成一个MethodInvocation进行调用。

 

(注:本文是基于Spring Security3.1.6所写)

(注:原创文章,转载请注明出处。原文地址:http://elim.iteye.com/blog/2262363

 

 

 

3
4
分享到:
评论
2 楼 234390216 2015-12-09  
a87604476 写道
博主,表达式的注解不是在第16节的时候说过了吗

刚好跟本文主题相契合,就再说一次。
1 楼 a87604476 2015-12-08  
博主,表达式的注解不是在第16节的时候说过了吗

相关推荐

    spring security 2.0 的简单配置使用(补)——用aop控制method级权限

    博文链接:https://snz.iteye.com/blog/229915

    非常珍贵的Spring Security企业级认证与授权全套视频(自鉴过后,良心推荐)

    SpringSecurity 全套开发,设计源码解读,整个拦截器链分析,QQ登录,微信登录,短信验证,短信登录,在security基础上学习写一个自定义验证授权设计模式,整套视频讲解的分享细致认真,非常值得学习。不管小白还是...

    SpringSecurity 3.0.1.RELEASE.CHM

    5.5. Spring Security中的访问控制(验证) 5.5.1. 安全和AOP建议 5.5.2. 安全对象和AbstractSecurityInterceptor 5.5.2.1. 配置属性是什么? 5.5.2.2. RunAsManager 5.5.2.3. AfterInvocationManager 5.5.2.4...

    Spring Security-3.0.1中文官方文档(翻译版)

    5.5. Spring Security 中的访问控制(验证) 5.5.1. 安全和AOP 建议 5.5.2. 安全对象和AbstractSecurityInterceptor 5.5.2.1. 配置属性是什么? 5.5.2.2. RunAsManager 5.5.2.3. AfterInvocationManager ...

    spring security3中文文档

    即使用一个基于Spring3的web工程作为基础,以理解使用Spring Security3使其保证安全的概念和策略。 不管你是不是已经使用Spring Security还是只是对这个软件有兴趣,就都会在本书中得到有用的信息。

    Spring Security 中文教程.pdf

    5.5. Spring Security中的访问控制(验证) 5.5.1. 安全和AOP建议 5.5.2. 安全对象和AbstractSecurityInterceptor 5.5.2.1. 配置属性是什么? 5.5.2.2. RunAsManager 5.5.2.3. AfterInvocationManager ...

    word源码java-rbac-security:基于角色的权限访问控制(Role-BasedAccessControl)

    Control的缩写,意思就是基于角色的权限访问控制。 基本思想: 对系统的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的...

    SpringBoot+Vue前后端分离,使用SpringSecurity完美处理权限问题的解决方法

    当前后端分离时,权限问题的处理也和我们传统的处理方式有一点差异。笔者前几天刚好在负责一个项目的权限管理模块,现在权限管理模块已经做完了,我想通过5-6篇文章,来介绍一下项目中遇到的问题以及我的解决方案,...

    简单高效的后台权限管理系统.zip

    安全框架采用Spring Security 5.0.7,可实现对按钮级别的权限控制,并集成了社交账户登录(QQ和微信)以及手机验证码登录;前端页面使用Bootstrap构建,主题风格为时下Google最新设计语言Material Design,并提供多...

    spring web flow demo

    只需将某个 flow 声明为“ secured ”,即可利用 Spring Security 来确定当前用户是否有权限运 行 flow 、激发事件等等。 • 更简洁的配置 官方的数据说同一个 flow , 2.0 版的配置比 1.x 版的配置少 50% 的 XML ...

    基于 SpringBoot + JPA + Security + Thymeleaf 实现的开发者社区+源代码+文档说明

    ORM框架用的 Spring Data JPA,权限管理用的是 Spring Security。 以 MySQL 作为数据库,同时用 Redis 数据库缓存几个排行榜。模板引擎使用的是官方推荐的 Thymeleaf,告别JSP吧。 图片上传使用第三方上传——七牛云...

    开源一套简单通用的后台管理系统.docx

     前段时间我们写一个简单的后台模板SpringBoot系列——Security + Layui实现一套权限管理后台模板,今天我们把它完善成一个简单通用的后台管理系统,我把它叫做:Base Admin  这套Base Admin是一套简单通用的后台...

    智慧酒店管理系统 java+springboot+redis 【APP+WEB双端】

    1.SpringSecurity使用token写入过期时间进行有效期管理(SpringSecurity结合Redis进行token有效期管理请移步我的另一个项目——小区智能管理系统) 2.可以通过角色权限或者指定人员授予菜单权限来实现动态菜单 3引用...

    JAVA著名免费框架若依前后端分离项目详细部署文档

    后端采用Spring Boot、Spring Security、Redis & Jwt。 权限认证使用Jwt,支持多终端认证系统。 支持加载动态权限菜单,多方式轻松权限控制。 高效率开发,使用代码生成器可以一键生成前后端代码。)

    微人事项目

    人事管理系统——微人事。主要目的是通过这个项目加强各个部门之间的协调从而提高工作效率。该项目是一个前后端分离的...而后端使用Spring Boot开发,使用到了Spring Security实现权限认证、 WebSocket实现消息代理等。

    一个简单的后台管理系统-基于Java SSM,Java Config配置+源代码+文档说明

    * 权限Spring Security * 缓存Ehcache(后期加入) * 后台数据校验Hibernate Validation(后期加入) * more ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目...

    asp.net知识库

    .NET20 一种简单的窗口控件UI状态控制方法 翻译MSDN文章 —— 泛型FAQ:最佳实践 Visual C# 3.0 新特性概览 C# 2.0会给我们带来什么 泛型技巧系列:如何提供类型参数之间的转换 C#2.0 - Object Pool 简单实现 ...

    FCat企业级基础功能框架-其他

    FCat是基于Angular4+SpringCloud的企业级基础功能框架(户权限管理、区域管理、GIS地图、......),其核心设计目标是分离前后端、开发快速、学习简单、功能强大、不重复造轮子,其目标是帮助企业搭建一套基础功能框架...

    JAVA上百实例源码以及开源项目源代码

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

    JAVA上百实例源码以及开源项目

     Java访问权限控制,为Java操作文件、写入文件分配合适的权限,定义写到文件的信息、定义文件,输出到c:/hello.txt、写信息到文件、关闭输出流。 Java绘制图片火焰效果 1个目标文件 摘要:Java源码,图形操作,火焰...

Global site tag (gtag.js) - Google Analytics