首页 > 其他分享 >转载:权限鉴定结构

转载:权限鉴定结构

时间:2023-05-29 12:39:35浏览次数:30  
标签:权限 鉴定 访问 ConfigAttribute ROLE AccessDecisionManager 转载 AccessDecisionVoter


 

1.1    权限

所有的Authentication实现类都保存了一个GrantedAuthority列表,其表示用户所具有的权限。GrantedAuthority是通过AuthenticationManager设置到Authentication对象中的,然后AccessDecisionManager将从Authentication中获取用户所具有的GrantedAuthority来鉴定用户是否具有访问对应资源的权限。

是一个接口,其中只定义了一个getAuthority()方法,其返回值为String类型。该方法允许AccessDecisionManager获取一个能够精确代表该权限的字符串。通过返回一个字符串,一个GrantedAuthority能够很轻易的被大部分AccessDecisionManager读取。如果一个GrantedAuthority不能够精确的使用一个String来表示,那么其对应的getAuthority()方法调用应当返回一个null,这表示AccessDecisionManager必须对该GrantedAuthority的实现有特定的支持,从而可以获取该GrantedAuthority所代表的权限信息。

       spring Security内置了一个GrantedAuthority的实现,SimpleGrantedAuthority。它直接接收一个表示权限信息的字符串,然后getAuthority()方法直接返回该字符串。Spring Security内置的所有AuthenticationProvider都是使用它来封装Authentication对象的。

 

1.2     调用前的处理

是通过拦截器来控制受保护对象的访问的,如方法调用和Web请求。在正式访问受保护对象之前,Spring Security将使用AccessDecisionManager来鉴定当前用户是否有访问对应受保护对象的权限。

 

1.2.1AccessDecisionManager

是由AbstractSecurityInterceptor调用的,它负责鉴定用户是否有访问对应资源(方法或URL)的权限。AccessDecisionManager是一个接口,其中只定义了三个方法,其定义如下。

public interface AccessDecisionManager {
 
    /**
     * 通过传递的参数来决定用户是否有访问对应受保护对象的权限
     *
     * @param authentication 当前正在请求受包含对象的Authentication
     * @param object 受保护对象,其可以是一个MethodInvocation、JoinPoint或FilterInvocation。
     * @param configAttributes 与正在请求的受保护对象相关联的配置属性
     *
     */
    void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
        throws AccessDeniedException, InsufficientAuthenticationException;
 
    /**
     * 表示当前AccessDecisionManager是否支持对应的ConfigAttribute
     */
    boolean supports(ConfigAttribute attribute);
 
    /**
     * 表示当前AccessDecisionManager是否支持对应的受保护对象类型
     */
    boolean supports(Class<?> clazz);
}

方法用于决定authentication是否符合受保护对象要求的configAttributes。supports(ConfigAttribute attribute)方法是用来判断AccessDecisionManager是否能够处理对应的ConfigAttribute的。supports(Class<?> clazz)方法用于判断配置的AccessDecisionManager是否支持对应的受保护对象类型。

 

1.2.2基于投票的AccessDecisionManager实现

已经内置了几个基于投票的AccessDecisionManager,当然如果需要你也可以实现自己的AccessDecisionManager。以下是Spring Security官方文档提供的一个图,其展示了与基于投票的AccessDecisionManager实现相关的类。

转载:权限鉴定结构_ide


 

使用这种方式,一系列的AccessDecisionVoter将会被AccessDecisionManager用来对Authentication是否有权访问受保护对象进行投票,然后再根据投票结果来决定是否要抛出AccessDeniedException。AccessDecisionVoter是一个接口,其中定义有三个方法,具体结构如下所示。

public interface AccessDecisionVoter<S> {
 
    intACCESS_GRANTED = 1;
    intACCESS_ABSTAIN = 0;
    intACCESS_DENIED = -1;
 
    boolean supports(ConfigAttribute attribute);
 
    boolean supports(Class<?> clazz);
 
    int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);
}

方法的返回结果会是AccessDecisionVoter中定义的三个常量之一。ACCESS_GRANTED表示同意,ACCESS_DENIED表示返回,ACCESS_ABSTAIN表示弃权。如果一个AccessDecisionVoter不能判定当前Authentication是否拥有访问对应受保护对象的权限,则其vote()方法的返回值应当为弃权ACCESS_ABSTAIN。

内置了三个基于投票的AccessDecisionManager实现类,它们分别是AffirmativeBased、ConsensusBased和UnanimousBased。

       AffirmativeBased的逻辑是这样的:

(1)只要有AccessDecisionVoter的投票为ACCESS_GRANTED则同意用户进行访问;

(2)如果全部弃权也表示通过;

(3)如果没有一个人投赞成票,但是有人投反对票,则将抛出AccessDeniedException。

       ConsensusBased的逻辑是这样的:

(1)如果赞成票多于反对票则表示通过。

(2)反过来,如果反对票多于赞成票则将抛出AccessDeniedException。

(3)如果赞成票与反对票相同且不等于0,并且属性allowIfEqualGrantedDeniedDecisions的值为true,则表示通过,否则将抛出异常AccessDeniedException。参数allowIfEqualGrantedDeniedDecisions的值默认为true。

(4)如果所有的AccessDecisionVoter都弃权了,则将视参数allowIfAllAbstainDecisions的值而定,如果该值为true则表示通过,否则将抛出异常AccessDeniedException。参数allowIfAllAbstainDecisions的值默认为false。

       UnanimousBased的逻辑与另外两种实现有点不一样,另外两种会一次性把受保护对象的配置属性全部传递给AccessDecisionVoter进行投票,而UnanimousBased会一次只传递一个ConfigAttribute给AccessDecisionVoter进行投票。这也就意味着如果我们的AccessDecisionVoter的逻辑是只要传递进来的ConfigAttribute中有一个能够匹配则投赞成票,但是放到UnanimousBased中其投票结果就不一定是赞成了。UnanimousBased的逻辑具体来说是这样的:

(1)如果受保护对象配置的某一个ConfigAttribute被任意的AccessDecisionVoter反对了,则将抛出AccessDeniedException。

(2)如果没有反对票,但是有赞成票,则表示通过。

(3)如果全部弃权了,则将视参数allowIfAllAbstainDecisions的值而定,true则通过,false则抛出AccessDeniedException。

 

1.2.2.1RoleVoter

是Spring Security内置的一个AccessDecisionVoter,其会将ConfigAttribute简单的看作是一个角色名称,在投票的时如果拥有该角色即投赞成票。如果ConfigAttribute是以“ROLE_”开头的,则将使用RoleVoter进行投票。当用户拥有的权限中有一个或多个能匹配受保护对象配置的以“ROLE_”开头的ConfigAttribute时其将投赞成票;如果用户拥有的权限中没有一个能匹配受保护对象配置的以“ROLE_”开头的ConfigAttribute,则RoleVoter将投反对票;如果受保护对象配置的ConfigAttribute中没有以“ROLE_”开头的,则RoleVoter将弃权。

 

1.2.2.2AuthenticatedVoter

也是Spring Security内置的一个AccessDecisionVoter实现。其主要用来区分匿名用户、通过Remember-Me认证的用户和完全认证的用户。完全认证的用户是指由系统提供的登录入口进行成功登录认证的用户。

可以处理的ConfigAttribute有IS_AUTHENTICATED_FULLY、IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_ANONYMOUSLY。如果ConfigAttribute不在这三者范围之内,则AuthenticatedVoter将弃权。否则将视ConfigAttribute而定,如果ConfigAttribute为IS_AUTHENTICATED_ANONYMOUSLY,则不管用户是匿名的还是已经认证的都将投赞成票;如果是IS_AUTHENTICATED_REMEMBERED则仅当用户是由Remember-Me自动登录,或者是通过登录入口进行登录认证时才会投赞成票,否则将投反对票;而当ConfigAttribute为IS_AUTHENTICATED_FULLY时仅当用户是通过登录入口进行登录的才会投赞成票,否则将投反对票。

是通过AuthenticationTrustResolver的isAnonymous()方法和isRememberMe()方法来判断SecurityContextHolder持有的Authentication是否为AnonymousAuthenticationToken或RememberMeAuthenticationToken的,即是否为IS_AUTHENTICATED_ANONYMOUSLY和IS_AUTHENTICATED_REMEMBERED。

 

自定义Voter

当然,用户也可以通过实现AccessDecisionVoter来实现自己的投票逻辑。

 

1.3     调用后的处理

是用来在访问受保护的对象之前判断用户是否拥有访问该对象的权限。有的时候我们可能会希望在请求执行完成后对返回值做一些修改,当然,你可以简单的通过AOP来实现这一功能。Spring Security为我们提供了一个AfterInvocationManager接口,它允许我们在受保护对象访问完成后对返回值进行修改或者进行权限鉴定,看是否需要抛出AccessDeniedException,其将由AbstractSecurityInterceptor的子类进行调用。AfterInvocationManager接口的定义如下。

public interface AfterInvocationManager {
   
    Object decide(Authentication authentication, Object object, Collection<ConfigAttribute> attributes,
        Object returnedObject) throws AccessDeniedException;
 
    boolean supports(ConfigAttribute attribute);
 
    boolean supports(Class<?> clazz);
}

 

以下是Spring Security官方文档提供的一个AfterInvocationManager构造实现的图。

转载:权限鉴定结构_sed_02


 

类似于AuthenticationManager,AfterInvocationManager拥有一个默认的实现类AfterInvocationProviderManager,其中拥有一个由AfterInvocationProvider组成的集合,AfterInvocationProvider与AfterInvocationManager具有相同的方法定义,在调用AfterInvocationProviderManager中的方法时实际上就是依次调用其中包含的AfterInvocationProvider对应的方法。

需要注意的是AfterInvocationManager需要在受保护对象成功被访问后才能执行。

 

1.4     角色的继承

对于角色继承这种需求也是经常有的,比如要求ROLE_ADMIN将拥有所有的ROLE_USER所具有的权限。当然我们可以给拥有ROLE_ADMIN角色的用户同时授予ROLE_USER角色来达到这一效果或者修改需要ROLE_USER进行访问的资源使用ROLE_ADMIN也可以访问。Spring Security为我们提供了一种更为简便的办法,那就是角色的继承,它允许我们的ROLE_ADMIN直接继承ROLE_USER,这样所有ROLE_USER可以访问的资源ROLE_ADMIN也可以访问。定义角色的继承我们需要在ApplicationContext中定义一个RoleHierarchy,然后再把它赋予给一个RoleHierarchyVoter,之后再把该RoleHierarchyVoter加入到我们基于Voter的AccessDecisionManager中,并指定当前使用的AccessDecisionManager为我们自己定义的那个。以下是一个定义角色继承的完整示例。

<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.1.xsd">
 
   <!-- 通过access-decision-manager-ref指定将要使用的AccessDecisionManager -->
   <security:httpaccess-decision-manager-ref="accessDecisionManager">
      <security:form-login/>
      <security:intercept-urlpattern="/admin.jsp" access="ROLE_ADMIN" />
      <security:intercept-urlpattern="/**" access="ROLE_USER" />
   </security:http>
 
   <security:authentication-manageralias="authenticationManager">
      <security:authentication-provider
user-service-ref="userDetailsService"/>
   </security:authentication-manager>
 
   <beanid="userDetailsService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
      <propertyname="dataSource" ref="dataSource" />
   </bean>
   <!-- 自己定义AccessDecisionManager对应的bean -->
   <beanid="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
      <propertyname="decisionVoters">
         <list>
            <reflocal="roleVoter"/>
         </list>
      </property>
   </bean>
 
   <beanid="roleVoter"
class="org.springframework.security.access.vote.RoleHierarchyVoter">
      <constructor-argref="roleHierarchy" />
   </bean>
   <beanid="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
      <propertyname="hierarchy"><!-- 角色继承关系 -->
         <value>
            ROLE_ADMIN > ROLE_USER
         </value>
      </property>
   </bean>
 
</beans>

在上述配置中我们就定义好了ROLE_ADMIN是继承自ROLE_USER的,这样ROLE_ADMIN将能够访问所有ROLE_USER可以访问的资源。通过RoleHierarchyImpl的hierarchy属性我们可以定义多个角色之间的继承关系,如:

<beanid="roleHierarchy"
class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
      <propertyname="hierarchy"><!-- 角色继承关系 -->
         <value>
            ROLE_ADMIN > ROLE_USER
            ROLE_A > ROLE_B
            ROLE_B > ROLE_C
            ROLE_C > ROLE_D
         </value>
      </property>
   </bean>

在上述配置我们同时定义了ROLE_ADMIN继承了ROLE_USER,ROLE_A继承了ROLE_B,ROLE_B又继承了ROLE_C,ROLE_C又继承了ROLE_D,这样ROLE_A将能访问ROLE_B、ROLE_C和ROLE_D所能访问的所有资源。

标签:权限,鉴定,访问,ConfigAttribute,ROLE,AccessDecisionManager,转载,AccessDecisionVoter
From: https://blog.51cto.com/u_16131764/6370049

相关文章

  • 转载:Servlet 工作原理解析
     Servlet工作原理解析 Web技术成为当今主流的互联网Web应用技术之一,而Servlet是JavaWeb技术的核心基础。因而掌握Servlet的工作原理是成为一名合格的JavaWeb技术开发人员的基本要求。本文将带你认识JavaWeb技术是如何基于Servlet工作,你将知道:以Tomcat为例......
  • ABAP 用户权限查询报表
    *&---------------------------------------------------------------------**&REPORTZUSER*&---------------------------------------------------------------------**&*&--------------------------------------------------------------------......
  • 转载-如何结合FT2232HL/CMSIS-DAP+Eclipse+OpenOCD软硬件工具使用SWD调试接口在Window
    原文链接:https://blog.csdn.net/zhuwade/article/details/121944736由于我们公司自己需要开发烧录工具,本人通过google搜相关文档和看ARM公司的技术文档,终于实现了这个功能。因为涉及的内容知识点比较多,对于玩嵌入式MCU的小白来说要普及的知识,逐个介绍篇幅会比较长,本文中只介绍......
  • 模糊检测(转载)
    转载https://blog.csdn.net/baidu_31657889/article/details/84671927模糊检测      模糊估计分为两个步骤:首先是边缘检测,然后是模糊确定。此处模糊估计是通过计算当前像素点与领域内像素点均值之差来确定。我们用f(x,y)表示图片,其中。定义水平绝对差如下:整个图片的水......
  • Powershell 修改 DNS 记录权限
    执行脚本需要管理员权限,且需要运行的计算机安装AD管理工具。FunctionSet_DNSACL{###$SourceServerisControldestinationServer.param($SouServer,$DstServer)$DNSServer=(Get-ADDomain).PDCEmulator$ZoneNames=(Get......
  • 基于RBAC模型的权限管理设计
    [toc]目的管理系统用户的功能菜单权限,物理资源(文件、数据)权限。RBAC模型简介RBAC模型(Role-BasedAccessControl:基于角色的访问控制)是比较早期提出的权限实现模型,在多用户计算机时期该思想即被提出,其中以美国GeorgeMason大学信息安全技术实验室(LIST)提出的RBAC96模型最具有代表,并得......
  • mysql创建用户及分配操作权限
    MySQL在安装时,会默认创建一个名为root的用户,该用户拥有超级权限,可以控制整个MySQL服务器,所以如果滥用root账户,对于系统来说是很不安全的。MySQL提供了以下3种方法创建用户。使用GRANT语句创建用户使用CREATEUSER语句创建用户在mysql.user表中添加用户1.使......
  • 【转载】Sqlserver存储过程中使用Select和Set给变量赋值
    @@sqlserverselect赋值  Sqlserver存储过程是时常使用到的一个数据库对象,在存储过程中会使用到Declare来定义存储过程变量,定义的存储过程变量可以通过Set或者Select等关键字方法来进行赋值操作,使用Set对存储过程变量赋值为直接赋值,使用Select则一般从数据表中查找出符合条......
  • drf——权限、认证源码分析、过滤、排序、分页
    权限、认证源码(了解)权限源码#继承了APIView才有的---》执行流程---》dispatch中的三大认证 self.initial(request,*args,**kwargs) #1.APIView的dispatch中self.initial(request,*args,**kwargs) definitial(self,request,*args,**kwargs):se......
  • JEECG-BOOT访问权限控制的BUG
    http://doc.jeecg.com/2044037根据此链接,还是无法解决权限问题,最后查到是一个两个角色都设置了一个用户,而后台权限获取SQL只取一个导致权限列表获取错误。  ......