给spring-security提了一个issue

栏目: Java · 发布时间: 5年前

内容简介:我在使用spring-security的角色继承,关键代码片段如下:上边关于角色继承的定义方式,是我在使用之前版本的spring-security获得经验,同时,通过spring-security源码的注释也可看到相关说明但是,当我实际跑起来后,发现根本不行,角色继承没生效。我就很纳闷了,原来用过spring-security啊,就是这样就可以啊。然后试了改了改权限表达式,结果还是不行,然后我想了想,调试源码吧,调试源码一般都是必杀技。在调试源码的过程中,我逐渐发现了问题所在。

今天在用spring-security的角色继承时,遇到了一个坑,通过调试源码解决了,然后发现这应该是spring-security本身的一个小问题,然后就在Spring官方的GitHub上提了一个 issue

给spring-security提了一个issue

正文

我在使用spring-security的角色继承,关键代码片段如下:

...
// 定义角色继承,两个角色继承之间用空格或and连接
roleHierarchyImpl.setHierarchy("ROLE_DEVELOPER > ROLE_SUPERVISOR and ROLE_SUPERVISOR > ROLE_ADMIN and ROLE_ADMIN > ROLE_USER and ROLE_USER > ROLE_ANONYMOUS");
...
...
// 定义需要的权限表达式
.access("hasRole('USER')")
...

上边关于角色继承的定义方式,是我在使用之前版本的spring-security获得经验,同时,通过spring-security源码的注释也可看到相关说明

/**
 * The simple interface of a role hierarchy.
 *
 * @author Michael Mayr
 */
public interface RoleHierarchy {

   /**
    * Returns an array of all reachable authorities.
    * <p>
    * Reachable authorities are the directly assigned authorities plus all authorities
    * that are (transitively) reachable from them in the role hierarchy.
    * <p>
    * Example:<br>
    * Role hierarchy: ROLE_A > ROLE_B and ROLE_B > ROLE_C.<br>
    * Directly assigned authority: ROLE_A.<br>
    * Reachable authorities: ROLE_A, ROLE_B, ROLE_C.
    *
    * @param authorities - List of the directly assigned authorities.
    * @return List of all reachable authorities given the assigned authorities.
    */
   public Collection<? extends GrantedAuthority> getReachableGrantedAuthorities(
         Collection<? extends GrantedAuthority> authorities);

}

但是,当我实际跑起来后,发现根本不行,角色继承没生效。我就很纳闷了,原来用过spring-security啊,就是这样就可以啊。然后试了改了改权限表达式,结果还是不行,然后我想了想,调试源码吧,调试源码一般都是必杀技。在调试源码的过程中,我逐渐发现了问题所在。

我先给出角色表达式解析以及角色继承解析的相关代码路径,大家可按这个路径跟踪。

角色表达式解析:

// 由上到下为执行路径,最上端是入口点
org.springframework.security.web.FilterChainProxy.VirtualFilterChain#doFilter

org.springframework.security.web.access.intercept.FilterSecurityInterceptor#doFilter

org.springframework.security.access.intercept.AbstractSecurityInterceptor#beforeInvocation

org.springframework.security.web.access.intercept.FilterSecurityInterceptor#invoke

org.springframework.security.access.AccessDecisionManager#decide

org.springframework.security.access.vote.AffirmativeBased#decide

org.springframework.security.web.access.expression.WebExpressionVoter#vote

org.springframework.security.access.expression.ExpressionUtils#evaluateAsBoolean

org.springframework.expression.spel.standard.SpelExpression#getValue(org.springframework.expression.EvaluationContext, java.lang.Class<T>)

org.springframework.expression.spel.ast.SpelNodeImpl#getTypedValue

org.springframework.expression.spel.ast.MethodReference#getValueInternal(org.springframework.expression.spel.ExpressionState)

org.springframework.expression.spel.ast.MethodReference#getCachedExecutor

org.springframework.expression.spel.support.ReflectiveMethodExecutor#execute

java.lang.reflect.Method#invoke

org.springframework.security.access.expression.SecurityExpressionRoot#hasRole

org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyRole

org.springframework.security.access.expression.SecurityExpressionRoot#hasAnyAuthorityName

注意上边执行路径中的 java.lang.reflect.Method#invoke 实际上,权限控制表达式内部的原理是是用反射去执行对应的用于判断是否有权限方法的,也就是执行 org.springframework.security.access.expression.SecurityExpressionRoot#hasRole

给spring-security提了一个issue

执行到下图中这里后,返回的是 false 也就是授权未通过,没有对应角色,当前拥有的角色是从 org.springframework.security.access.hierarchicalroles.RoleHierarchy#getReachableGrantedAuthorities 获得的,里面并没有需要的角色”ROLE”,因此自然就是 false

给spring-security提了一个issue

那么为什么没有呢,按照角色继承的定义,应该能够有才对啊,这是我们就需要看角色继承表达式生成具体角色的逻辑了,这个逻辑的代码路径是这个:

org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl#setHierarchy

org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl#buildRolesReachableInOneStepMap

org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl#buildRolesReachableInOneOrMoreStepsMap

通过跟踪这些代码,我们从中可以看出,实际上,正确的角色继承表达式应该这样定义:

...
roleHierarchyImpl.setHierarchy("ROLE_DEVELOPER > ROLE_SUPERVISOR > ROLE_ADMIN > ROLE_USER > ROLE_ANONYMOUS");
...

实际上定义角色继承表达式的规则已经变了,然而,在spring-security代码库中的 RoleHierarchy 这个类的注释,还保留着旧版的角色继承表达式的定义方式的说明,这应当是代码更新了但是注释未更新,我按照以往的经验以及注释的说明去写,结果掉坑里了。

总结

通过这次问题的排查,可以说明: 必要的注释可以有,但是不要过分依赖于注释,要相信代码本身 ,此外在这次调试源码的过程中我还发现了一个调试源码的技巧:利用 Drop Frame ,可以倒推代码的执行路径。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

1024·人与机器共同进化

1024·人与机器共同进化

东西文库 / 译言·东西文库/电子工业出版社 / 2013-12-20 / 55元

《1024》:国内第一本专注于科技文化的mook。 本期创刊号将目光定焦在“人与机器”这个超热点领域。 如果把机器获得思维能力看作是一种进化, 那人类具备不朽之躯同样也是一种进化。 这是一个野心勃勃但又充满不确定性的未来。 在我们一厢情愿地猜测机器将在不远的将来赶超自己而惶惶不可终日时,人类其实还有一个机会——变得更像机器。这并非科幻小说,而是正在发生的现实。人类创造......一起来看看 《1024·人与机器共同进化》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器