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

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节的时候说过了吗

相关推荐

    springboot项目——基于springSecurity实现的前后端分离的企业级人事管理系统

    接着,SpringSecurity作为安全模块,主要负责用户的登录验证、权限控制以及会话管理。在本项目中,SpringSecurity可以实现用户登录时的身份验证,例如通过用户名和密码进行认证。同时,它还支持基于角色的访问控制...

    Spring Security 资料合集

    这三份资料——"实战Spring Security 3.x.pdf"、"Spring Security 3.pdf" 和 "Spring Security使用手册.pdf" 将深入探讨这些概念,并提供实践指导,帮助读者掌握如何在实际项目中应用Spring Security。通过学习这些...

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

    在本文中,我们将深入探讨如何在Spring Security 2.0版本中配置并使用AOP(面向切面编程)来实现方法级别的权限控制。首先,我们需要理解Spring Security的基础概念。 1. **Spring Security基本架构** Spring ...

    spring Security3中文教程,经典的

    Spring Security提供细粒度的权限控制,允许开发者根据角色和权限来限制访问。 #### 二、实现应用安全 - **使用Spring Security的XML配置文件**:通过XML配置文件来指定Spring Security的规则和策略,如认证管理器...

    Spring Security 3系列文章——入门篇(一)

    Spring Security支持基于表达式的访问控制,如`hasRole()`,`isAuthenticated()`等。这些表达式可以在方法级别或URL级别使用,以定义访问策略。 ### 7. Spring Security ACL 在压缩包中的`SpringSecurityAclDemo`...

    SpringSecurity笔记2-SpringSecurity命名空间

    在"SpringSecurity笔记2-SpringSecurity命名空间"这个主题中,我们将深入探讨SpringSecurity配置的核心——命名空间。 SpringSecurity通过XML配置文件中的命名空间来简化设置过程,这些命名空间提供了丰富的元素和...

    基于springboot+springSecurity+jwt实现的基于token的权限管理的一个demo,适合新手

    本示例项目——"基于springboot+springSecurity+jwt实现的基于token的权限管理的一个demo",旨在为新手提供一个易于理解的学习平台,来掌握如何在Spring Boot应用中实现用户认证与授权。下面将详细介绍这个项目所...

    SpringBoot集成Spring Security登录管理 添加 session 共享【完整源码+数据库】

    我们将基于给定的标签——SpringBoot、SpringSecurity、mysql、session共享和idea来构建一个完整的示例。 首先,SpringBoot是一个轻量级的Java框架,它简化了创建独立的、生产级别的基于Spring的应用程序。通过内置...

    spring security4登陆例子

    本文将通过一个具体的示例——Spring MVC + Spring Security 4 的整合登录实例来深入探讨Spring Security的使用方法。 #### 二、核心配置类:`SecurityConfig` 在本例中,我们使用的是Java Config的方式进行Spring...

    spring security3.1高级详细开发指南

    首先,Spring Security 3.1的四种使用方法: 1. **全配置方式**:所有用户、权限和资源都在XML配置文件中硬编码。这种方式易于理解,但维护性较差,不适合大型项目。 2. **部分数据库存储**:用户和权限存储在...

    Spring_Security权限管理_学习笔记

    Spring Security还提供了许多高级特性,如基于注解的权限控制、自定义认证和授权逻辑、支持OAuth2和其他身份验证协议等。在实际开发中,我们可以根据项目需求选择合适的配置和扩展点,以实现灵活且安全的权限管理...

    进一步了解“学习 Spring Security”.zip

    使用 Spring Security 的登录和注册示例项目如果您已经是 Learn Spring Security 的学生,您可以开始深入了解模块 2 的注册。如果您还不是学生,您可以在此处访问课程https://bit.ly/github-lss相关文章Spring ...

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

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

    Java毕业设计——基于spring boot的就业信息管理网站设计与实现(源码+数据库).7z

    开发者可以利用Spring Boot的starter特性快速引入所需的依赖,例如Spring Data JPA用于数据库操作,Spring Security进行权限管理,Spring MVC处理HTTP请求等。 数据库方面,提供的`employment.sql`文件很可能是预先...

    maven+springmvc+springsecurity+hibernate框架整合开发源代码

    本项目“maven+springmvc+springsecurity+hibernate框架整合开发源代码”就是一个这样的例子,它巧妙地将四个关键框架——Maven、Spring MVC、Spring Security和Hibernate融合在一起,构建了一个高效且安全的Web应用...

    springboot+mybatis+gradle+thymeleaf+springsecurity

    综上所述,"springboot+mybatis+gradle+thymeleaf+springsecurity"的项目组合,构建了一个功能完善的、安全的Web应用,涵盖了从数据存储、业务处理到用户界面呈现和安全防护的各个层面。开发者可以根据实际需求...

    spring-security-core-3.1.0.RC1.jar

    在本篇文章中,我们将深入探讨Spring Security的核心库——`spring-security-core-3.1.0.RC1.jar`,以及它在安全领域的应用。 一、Spring Security简介 Spring Security是一款提供全面身份验证、授权和安全访问...

    Spring Security3.pdf

    在Spring Security3中,我们首先会接触到的是其核心概念——访问控制。该框架采用基于角色的访问控制(RBAC)模型,允许开发者定义不同角色以及它们对资源的权限。通过配置XML或使用注解,我们可以为URL、方法甚至...

    基于SpringCloud2.1+spring-security-oauth2+nacos+feign的微服务开发脚手架.zip

    这是一个基于SpringCloud 2.1版本的微服务开发框架,结合了spring-security-oauth2用于权限管理和认证,Nacos作为服务注册与配置中心,以及Feign进行服务间的调用。让我们详细了解一下这些技术栈的核心概念和作用。 ...

Global site tag (gtag.js) - Google Analytics