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

Spring Security(14)——权限鉴定基础

阅读更多

权限鉴定基础

 

目录

1.1     Spring SecurityAOP Advice思想

1.2     AbstractSecurityInterceptor

1.2.1    ConfigAttribute

1.2.2    RunAsManager

1.2.3    AfterInvocationManager

 

       Spring Security的权限鉴定是由AccessDecisionManager接口负责的。具体来说是由其中的decide()方法负责,其定义如下。

    void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)

        throws AccessDeniedException, InsufficientAuthenticationException;

 

       如你所见,该方法接收三个参数,第一个参数是包含当前用户信息的Authentication对象;第二个参数表示当前正在请求的受保护的对象,基本上来说是MethodInvocation(使用AOP)、JoinPoint(使用Aspectj)和FilterInvocationWeb请求)三种类型;第三个参数表示与当前正在访问的受保护对象的配置属性,如一个角色列表。

 

1.1     Spring SecurityAOP Advice思想

       对于使用AOP而言,我们可以使用几种不同类型的advicebeforeafterthrowsaround。其中around advice是非常实用的,通过它我们可以控制是否要执行方法、是否要修改方法的返回值,以及是否要抛出异常。Spring Security在对方法调用和Web请求时也是使用的around advice的思想。在方法调用时,可以使用标准的Spring AOP来达到around advice的效果,而在进行Web请求时是通过标准的Filter来达到around advice的效果。

       对于大部分人而言都比较喜欢对Service层的方法调用进行权限控制,因为我们的主要业务逻辑都是在Service层进行实现的。如果你只是想保护Service层的方法,那么使用Spring AOP就可以了。如果你需要直接保护领域对象,那么你可以考虑使用Aspectj

       你可以选择使用AspectjSpring AOP对方法调用进行鉴权,或者选择使用FilterWeb请求进行鉴权。当然,你也可以选择使用这三种方式的任意组合进行鉴权。通常的做法是使用FilterWeb请求进行一个比较粗略的鉴权,辅以使用Spring AOPService层的方法进行较细粒度的鉴权。

 

1.2     AbstractSecurityInterceptor

       AbstractSecurityInterceptor是一个实现了对受保护对象的访问进行拦截的抽象类,其中有几个比较重要的方法。beforeInvocation()方法实现了对访问受保护对象的权限校验,内部用到了AccessDecisionManagerAuthenticationManagerfinallyInvocation()方法用于实现受保护对象请求完毕后的一些清理工作,主要是如果在beforeInvocation()中改变了SecurityContext,则在finallyInvocation()中需要将其恢复为原来的SecurityContext,该方法的调用应当包含在子类请求受保护资源时的finally语句块中;afterInvocation()方法实现了对返回结果的处理,在注入了AfterInvocationManager的情况下默认会调用其decide()方法。AbstractSecurityInterceptor只是提供了这几种方法,并且包含了默认实现,具体怎么调用将由子类负责。每一种受保护对象都拥有继承自AbstractSecurityInterceptor的拦截器类, MethodSecurityInterceptor将用于调用受保护的方法,而FilterSecurityInterceptor将用于受保护的Web请求。它们在处理受保护对象的请求时都具有一致的逻辑,具体的逻辑如下。

       1、先将正在请求调用的受保护对象传递给beforeInvocation()方法进行权限鉴定。

       2、权限鉴定失败就直接抛出异常了。

       3、鉴定成功将尝试调用受保护对象,调用完成后,不管是成功调用,还是抛出异常,都将执行finallyInvocation()

       4、如果在调用受保护对象后没有抛出异常,则调用afterInvocation()

 

       以下是MethodSecurityInterceptor在进行方法调用的一段核心代码。

    public Object invoke(MethodInvocation mi) throws Throwable {

        InterceptorStatusToken token = super.beforeInvocation(mi);

 

        Object result;

        try {

            result = mi.proceed();

        } finally {

            super.finallyInvocation(token);

        }

        returnsuper.afterInvocation(token, result);

    }

 

1.2.1   ConfigAttribute

       AbstractSecurityInterceptorbeforeInvocation()方法内部在进行鉴权的时候使用的是注入的AccessDecisionManagerdecide()方法进行的。如前所述,decide()方法是需要接收一个受保护对象对应的ConfigAttribute集合的。一个ConfigAttribute可能只是一个简单的角色名称,具体将视AccessDecisionManager的实现者而定。AbstractSecurityInterceptor将使用一个SecurityMetadataSource对象来获取与受保护对象关联的ConfigAttribute集合,具体SecurityMetadataSource将由子类实现提供。ConfigAttribute将通过注解的形式定义在受保护的方法上,或者通过access属性定义在受保护的URL上。例如我们常见的<intercept-url pattern=”/**” access=”ROLE_USER,ROLE_ADMIN”/>就表示将ConfigAttribute ROLE_USERROLE_ADMIN应用在所有的URL请求上。对于默认的AccessDecisionManager的实现,上述配置意味着用户所拥有的权限中只要拥有一个GrantedAuthority与这两个ConfigAttribute中的一个进行匹配则允许进行访问。当然,严格的来说ConfigAttribute只是一个简单的配置属性而已,具体的解释将由AccessDecisionManager来决定。

 

1.2.2  RunAsManager

       在某些情况下你可能会想替换保存在SecurityContext中的Authentication。这可以通过RunAsManager来实现的。在AbstractSecurityInterceptorbeforeInvocation()方法体中,在AccessDecisionManager鉴权成功后,将通过RunAsManager在现有Authentication基础上构建一个新的Authentication,如果新的Authentication不为空则将产生一个新的SecurityContext,并把新产生的Authentication存放在其中。这样在请求受保护资源时从SecurityContext中获取到的Authentication就是新产生的Authentication。待请求完成后会在finallyInvocation()中将原来的SecurityContext重新设置给SecurityContextHolderAbstractSecurityInterceptor默认持有的是一个对RunAsManager进行空实现的NullRunAsManager。此外,Spring SecurityRunAsManager有一个还有一个非空实现类RunAsManagerImpl,其在构造新的Authentication时是这样的逻辑:如果受保护对象对应的ConfigAttribute中拥有以“RUN_AS_”开头的配置属性,则在该属性前加上“ROLE_”,然后再把它作为一个GrantedAuthority赋给将要创建的Authentication(如ConfigAttribute中拥有一个“RUN_AS_ADMIN”的属性,则将构建一个“ROLE_RUN_AS_ADMIN”的GrantedAuthority),最后再利用原Authenticationprincipal、权限等信息构建一个新的Authentication进行返回;如果不存在任何以“RUN_AS_”开头的ConfigAttribute,则直接返回nullRunAsManagerImpl构建新的Authentication的核心代码如下所示。

    public Authentication buildRunAs(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {

        List<GrantedAuthority> newAuthorities = new ArrayList<GrantedAuthority>();

        for (ConfigAttribute attribute : attributes) {

            if (this.supports(attribute)) {

                GrantedAuthority extraAuthority = new SimpleGrantedAuthority(getRolePrefix() + attribute.getAttribute());

                newAuthorities.add(extraAuthority);

            }

        }

        if (newAuthorities.size() == 0) {

            returnnull;

        }

        // Add existing authorities

        newAuthorities.addAll(authentication.getAuthorities());

        returnnew RunAsUserToken(this.key, authentication.getPrincipal(), authentication.getCredentials(),

                newAuthorities, authentication.getClass());

    }

 

1.2.3  AfterInvocationManager

       在请求受保护的对象完成以后,可以通过afterInvocation()方法对返回值进行修改。AbstractSecurityInterceptor把对返回值进行修改的控制权交给其所持有的AfterInvocationManager了。AfterInvocationManager可以选择对返回值进行修改、不修改或抛出异常(如:后置权限鉴定不通过)。

 

       以下是Spring Security官方文档提供的一张关于AbstractSecurityInterceptor相关关系的图。



 

 

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

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

 

 

 

  • 大小: 55.2 KB
4
0
分享到:
评论
2 楼 234390216 2015-12-22  
chenjazz 写道
楼主我想问一下:我实现了自己的SecurityMetadataSource从数据库中查询url对应的权限时,报空指针异常,这是为什么呢

这种情况首先看异常信息定位是哪里报的空指针,然后有针对性的跟踪代码查看。
1 楼 chenjazz 2015-12-22  
楼主我想问一下:我实现了自己的SecurityMetadataSource从数据库中查询url对应的权限时,报空指针异常,这是为什么呢

相关推荐

Global site tag (gtag.js) - Google Analytics