`
lengyun3566
  • 浏览: 452561 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
D59180b9-02f1-3380-840c-ea34da46143c
《Spring Secur...
浏览量:383441
社区版块
存档分类
最新评论

《Spring Security3》第五章第三部分翻译(保护业务层)

 
阅读更多

 

保护业务层

         到目前为止,在本书中我们的关注点都主要在JBCP Pets 应用web层面的安全。但是,在实际的安全系统规划中,对服务方法应该给予同等的重视,因为它们能够访问系统中最重要的部分——数据。

         Spring Security支持添加授权层(或者基于授权的数据处理)到应用中所有Spring管理的bean中。尽管很多的开发人员关注层的安全,其实业务层的俄安全同等主要,因为恶意的用户可能会穿透web层,能够通过没有UI的前端访问暴露的服务,如使用web service

 

         让我们查看下面的图以了解我们将要添加安全层的位置:



 Spring Security有两个主要技术以实现方法的安全:

l 事先授权(Pre-authorization)保证在执行一个方法之前需要满足特定的要求——例如,一个用户要拥有特定的GrantedAuthority,如ROLE_ADMIN。不能满足声明的条件将会导致方法调用失败;

l事后授权(Post-authorization)保证在方法返回时,调用的安全实体满足声明的条件。这很少被使用,但是能够在一些复杂交互的业务方法周围提供额外的安全层。        

          事先和事后授权在面向对象设计中提供了所谓的前置条件和后置条件(preconditions and postconditions)。前置条件和后置条件允许开发者声明运行时的检查,从而保证在一个方法执行时特定的条件需要满足。在安全的事前授权和事后授权中,业务层的开发人员需要对特定的方法确定明确的安全信息,并在接口或类的API声明中添加期望的运行时条件。正如你可能想象的那样,这需要大量的规划以避免不必要的影响。

         

保护业务层方法的基本知识

         让我们以JBCP Pets中业务层的几个方法为例阐述怎样为它们应用典型的规则。

         我们对JBCP Pets的基础代码进行了重新组织以实现三层的设计,作为修改的一部分我们抽象出了前面章节已经介绍到的修改密码功能到业务层。不同于用web MVC的控制器直接访问JDBC DAO,我们选择插入一个业务服务以提供要求的附加功能。下图对此进行了描述:


 

我们能够看到在例子中com.packtpub.springsecurity.service.IuserService接口代表了应用架构的业务层,而这对我们来说,是一个合适位置来添加方法级的安全。

添加@PreAuthorize方法注解

         我们第一个的设计决策就是要在业务层上添加方法安全,以保证用户在修改密码前已经作为系统的合法用户进行了登录。这通过为业务接口方法定义添加一个简单的注解来实现,如下:

 

public interface IUserService {
  @PreAuthorize("hasRole('ROLE_USER')")
  public void changePassword(String username, String password);
}

 这就是保证合法、已认证的用户才能访问修改密码功能所要做的所有事情。Spring Security将会使用运行时的面向方面编程的切点(aspect oriented programming (AOP) pointcut)来对方法执行before advice,并在安全要求未满足的情况下抛出AccessDeniedException异常。

 

Spring Security能够使用方法注解

         我们还需要在dogstore-security.xml中做一个一次性的修改,通过这个文件我们已经进行了Spring Security其他的配置。只需要在<http>声明之前,添加下面的元素即可:

 

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

 

校验方法安全

         不相信如此简单?那我们将ROLE_USER声明修改为ROLE_ADMIN。现在用用户guest(密码guest)登录并尝试修改密码。你会在尝试修改密码时,看到如下的出错界面:



 如果查看Tomcat的控制台,你可以看到很长的堆栈信息,开始是这样的:

 

DEBUG - Could not complete request
o.s.s.access.AccessDeniedException: Access is denied
at o.s.s.access.vote.AffirmativeBased.decide
at o.s.s.access.intercept.AbstractSecurityInterceptor.beforeInvocation
...
at $Proxy12.changePassword(Unknown Source)
at com.packtpub.springsecurity.web.controller.AccountController.
submitChangePasswordPage

          基于访问拒绝的页面以及指向changePassword方法的堆栈信息,我们可以看到用户被合理的拒绝对业务方法的访问,因为缺少ROLE_ADMINGrantedAuthority。你可以测试修改密码功能对管理员用户依旧是可以访问的。

 

         我们只是在接口上添加了简单的声明就能够保证方法的安全,这是不是太令人兴奋了?当然,我们不会愿意Tomcat 原生的403错误页面在我们的产品应用中出现——我们将会在第六章:高级配置与扩展讲述访问拒绝处理时,对其进行更新。

         让我们介绍一下实现方法安全的其它方式,然后进入功能的背后以了解其怎样以及为什么能够生效。

 

几种实现方法安全的方式

         除了@PreAuthorize注解以外,还有几种其它的方式来声明在方法调用前进行授权检查的需求。我们会讲解这些实现方法安全的不同方式,并比较它们在不同环境下的优势与不足。

遵守JSR-250标准规则

         JSR-250, Common Annotations for the Java Platform定义了一系列的注解,其中的一些是安全相关的,它们意图在兼容JSR-250的环境中很方便地使用。Spring框架从Spring 2.x释放版本开始就兼容JSR-250,包括Spring Security框架。

         尽管JSR-250注解不像Spring原生的注解富有表现力,但是它们提供的注解能够兼容不同的Java EE应用服务器实现如Glassfish,或面向服务的运行框架如Apache Tuscany。取决于你应用对轻便性的需求,你可能会觉得牺牲代码的轻便性但减少对特定环境的要求是值得的。

         要实现我们在第一个例子中的规则,我们需要作两个修改,首先在dogstore-security.xml文件中:

 

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

 其次,@PreAuthorize注解需要修改成@RolesAllowed注解。正如我们可能推断出的那样,@RolesAllowed注解并不支持SpEL表达式,所以它看起来很像我们在第二节中提到的URL授权。我们修改IuserService定义如下:

 

@RolesAllowed("ROLE_USER")
public void changePassword(String username, String password);

 正如前面的练习那样,如果不相信它能工作,尝试修改ROLE_USER ROLE_ADMIN并进行测试。

 

         要注意的是,也可以提供一系列允许的GrantedAuthority名字,使用Java 5标准的字符串数组注解语法:

 

@RolesAllowed({"ROLE_USER","ROLE_ADMIN"})
public void changePassword(String username, String password);

          JSR-250还有两个其它的注解:@PermitAll @DenyAll。它们的功能正如你所预想的,允许和禁止对方法的任何请求。

【类层次的注解。注意方法级别的安全注解也可以使用到类级别上!如果提供了方法级别的注解,将会覆盖类级别的注解。如果业务需要在整个类上有安全策略的话,这会非常有用。要注意的是使用这个功能要有良好的注释的编码规范,这样开发人员能够很清楚的了解类和方法的安全特性。】

         我们将会在本章稍后的练习中介绍如何实现JSR-250风格的注解与Spring Security风格 的注解并存。

@Secured注解实现方法安全

         Spring本身也提供一个简单的注解,类似于JSR-250 @RolesAllowed注解。@Secured注解在功能和语法上都与@RolesAllowed一致。唯一需要注意的不同点是要使用这些注解的话,要在<global-method-security>元素中明确使用另外一个属性:

 

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

 因为@SecuredJSR标准的@RolesAllowed注解在功能上一致,所以并没有充分的理由在新代码中使用它,但是它能够在Spring的遗留代码中运行。

使用Aspect Oriented Programming AOP)实现方法安全

         实现方法安全的最后一项技术也可能是最强大的方法,它还有一个好处是不需要修改源代码。作为替代,它使用面向方面的编程方式为一个方法或方法集合声明切点(pointcut),而增强(advice)会在切点匹配的情况下进行基于角色的安全检查。AOP的声明只在Spring SecurityXML配置文件中并不涉及任何的注解。

         以下就是声明保护所有的service接口只有管理权限才能访问的例子:

 

<global-method-security>
  <protect-pointcut access="ROLE_ADMIN" 
expression="execution(* com.packtpub.springsecurity.service.I*Service.*(..))"/>
</global-method-security>

 切点表达式基于Spring AOPAspectJ的支持。但是,Spring AspectJ AOP仅支持AspectJ切点表达式语言的一个很小子集——可以参考Spring AOP的文档以了解其支持的表达式和其它关于Spring AOP编程的重要元素。

         注意的是,可以指明一系列的切点声明,以指向不同的角色和切点目标。以下的就是添加切点到DAO中一个方法的例子:

 

<global-method-security>
  <protect-pointcut access="ROLE_USER" 
expression="execution(* com.packtpub.springsecurity.dao.IProductDao.getCategories(..)) &amp;&amp;
args()"/>
  <protect-pointcut access="ROLE_ADMIN" expression="execution(* com.
packtpub.springsecurity.service.I*Service.*(..))"/>
</global-method-security>

 注意在新增的切点中,我们添加了一些AspectJ的高级语法,来声明Boolean逻辑以及其它支持的切点,而参数可以用来确定参数的类型声明。

         Spring Security其它允许一系列安全声明的地方一样,AOP风格的方法安全是按照从顶到底的顺序进行的,所以需要按照最特殊到最不特殊的顺序来写切点。

         使用AOP来进行编程即便是经验丰富的开发人员可能也会感到迷惑。如果你确定要使用AOP来进行安全声明,除了Spring AOP的参考手册外,强烈建议你参考一些这个专题相关的书籍。AOP实现起来比较复杂,尤其是在解决不按照你预期运行的配置错误时更是如此。

比较方法授权的类型

         以下的快速参考表可能在你选择授权方法检查时派上用场:

        

方法授权类型

声明方式

JSR标准

允许SpEL表达式

@PreAuthorize

@PostAuthorize

注解

No

Yes

@RolesAllowed

@PermitAll

@DenyAll

注解

Yes

NO

@Secure

注解

No

No

protect-pointcut

XML

No

No

         大多数使用Java 5Spring Security用户倾向于使用JSR-250注解,以达到在IT组织间最大的兼容性和对业务类(以及相关约束)的重用。在需要的地方,这些基本的声明能够被Spring Security本身实现的注解所代替。

         如果你在不支持注解的环境中(Java 1.4或更早版本)中使用Spring Security,很不幸的是,关于方法安全的执行你的选择可能会很有限。即使在这样的情况下,对AOP的使用也提供了相当丰富的环境来开发基本的安全声明。

方法的安全保护是怎样运行的?

         方法安全的访问决定机制——一个给定的请求是否被允许——在概念上与web请求的访问决定逻辑是相同的。AccessDecisionManager使用一个AccessDecisionVoters集合,其中每一个都要对能否进行访问做出允许、拒绝或者弃权的的投票。AccessDecisionManager汇集这些投票器的结果并形成一个最终能否允许处罚方法的决定。

         Web请求的访问决策没有这么复杂,这是因为通过ServletFilters对安全请求做拦截(以及请求拒绝)都相对很直接。因为方法的触发可能发生在任何的地方,包括没有通过Spring Security直接配置的代码,Spring Security的设计者于是选择Spring管理的AOP方式来识别、评估以及保护方法的触发。

         下图在总体上展现了方法触发授权决策的主要参与者:



          我们能够看到Spring Securityo.s.s.access.intercept.aopalliance.MethodSecurityInterceptor被标准的Spring AOP运行时触发以拦截感兴趣的方法调用。通过上面的流程图,是否允许方法调用的逻辑就相对很清晰了。

         此时,我们可能会比较关心方法安全功能的性能。显然,MethodSecurityInterceptor不能在应用中每个方法调用的时候触发——那方法或类上的注解是如何做到AOP拦截的呢?

         首先,AOP织入默认不会对所有Spring管理的bean触发。相反,如果<global-method-security>Spring Security配置中定义,一个标准的Spring AOP  o.s.beans.factory.config.BeanPostProcessor将会被注册,它将会探查AOP配置是否有AOP增强器(advisors)需要织入(以及拦截)。这个工作流是Spring标准的AOP处理(名为AOP自动织入),并不是Spring Security所特有的。所有的BeanPostProcessorsspring ApplicationContext初始化时执行,在所有的Spring Bean配置生效后。

         SpringAOP自动织入功能查询所有注册的PointcutAdvisors,查看是否有AOP切点匹配方法的调用并使用AOP增强(advice)。Spring Security实现了o.s.s.access.intercept.aopalliance.MethodSecurityMetadataSourceAdvisor类,它会检查所有配置的方法安全病建立适当的AOP拦截。注意的是,只有声明了方法安全的接口和类才会被AOP代理。

【强烈建议在接口上声明AOP规则(以及其它的安全注解),而不是在实现类上。使用类(通过SpringCGLIB代理)进行声明可能会导致应用出现不可预知的行为改变,通常在正确性方面比不上在接口定义安全声明(通过AOP)。】

MethodSecurityMetadataSourceAdvisorAOP影响方法行为的决定委托给o.s.s.access.method.MethodSecurityMetadataSource的实例。不同的方法安全注解都拥有自己的MethodSecurityMetadataSource,它将用来检查每个方法和类并添加在运行时执行的增强(advice)。

以下的图展现了这个过程是如何发生的:



          取决于你的应用中配置的Sprin Bean的数量,以及拥有的安全方法注解的数量,添加方法安全代理将会增加初始化ApplicationContext的时间。但是,一旦上下文初始化完成,对单个的代理bean来说性能的影响可以忽略不计了。

 

 

 

  • 大小: 21.6 KB
  • 大小: 48.7 KB
  • 大小: 37.5 KB
  • 大小: 53.3 KB
  • 大小: 58.7 KB
5
9
分享到:
评论
4 楼 苦逼老周 2015-07-14  
我的也是放在security.xml文件中不行,放在servlet.xml中可以生效,有点反人类



3 楼 xiejx618 2012-03-30  
我觉得将权限放在controller层更合适,但发现〈global-method-security jsr250-annotations="enabled"/>写在security.xml上下文,发现不起作用,写到xxxx-servlet.xml上下文就起作用了。
http://stackoverflow.com/questions/3087548/can-spring-security-use-preauthorize-on-spring-controllers-methods提到:
DispatcherServlet's context is a child context of the ContextLoaderListener's one. So they have different AOP configurations and therefore require different occurences of <global-method-security>
2 楼 shizhijie737 2011-10-27  
文档有个“病”字,改成“并”吧
1 楼 Caedmon 2011-09-11  

    [*]
引用
[u][/u][i][/i][b][/b]

相关推荐

    《Spring Security3》第二章第三部分翻译(下)附前两章doc文档

    《Spring Security3》第二章第三部分的翻译下篇主要涵盖了Spring Security的核心概念和技术,这部分内容是深入理解Spring Security架构和实现安全控制的关键。在本章节中,我们将详细探讨以下几个核心知识点: 1. *...

    spring security3 中文版本

    自此之后,Spring Security 成为了 Spring 生态系统中的一个重要组成部分,不断迭代更新,以适应不断变化的安全需求和技术发展。 ##### 1.3 发行版本号 Spring Security 3.0.1 是在 Spring Security 3.0 的基础上...

    Spring Security in Action

    Spring Security 的架构主要包括以下几层: * Presentation Layer:负责用户交互,例如登录、登出等。 * Application Layer:负责业务逻辑,例如身份验证、授权等。 * Infrastructure Layer:负责基础设施,例如...

    Spring Security 资料合集

    - Spring Security 可以与OAuth2框架集成,提供第三方服务的认证和授权,支持资源服务器、认证服务器和客户端的角色。 8. **Spring Security ACL**: - 对象级权限管理(ACL)允许开发者对应用内的具体对象实施细...

    springSecurity3例子

    - Spring Security 3引入了CSRF(跨站请求伪造)防护,通过添加一个不可预测的令牌到表单提交中,防止恶意第三方发起未经授权的操作。 5. **国际化支持**: - 支持多语言界面,可以根据用户的首选语言显示错误...

    Spring Security-3中文官方文档(及教程)

    7. **OAuth2整合**:Spring Security可以与OAuth2框架集成,支持第三方身份验证服务,如Google、Facebook等,实现社交登录功能。 8. **Web安全**:文档涵盖了HTTP基本认证、表单登录、HTTP方法转换、XSS防护、点击...

    spring security 官方文档

    5. **CSRF保护(Cross-Site Request Forgery)**:默认情况下,Spring Security提供了对CSRF攻击的防护,通过生成和验证CSRF令牌来确保只有合法的请求才能执行。 6. **Web安全(Web Security)**:对于基于Servlet...

    Spring Security3

    ### Spring Security3 相关知识点概述 #### 第一章:一个不安全应用的剖析 **安全审计** - **目的**:识别系统中的安全隐患,并评估安全措施的有效性。 - **过程**:通过模拟攻击来测试系统的安全性,分析日志记录...

    springsecurity学习笔记

    7. **OAuth2 and JWT支持**:Spring Security 提供了对OAuth2和JSON Web Tokens (JWT) 的支持,这在现代微服务架构中非常重要,因为它允许第三方应用安全地与你的服务进行交互。 8. **表达式语言(SpEL)**:Spring...

    SpringSecurity笔记,编程不良人笔记

    - OAuth2:SpringSecurity支持OAuth2协议,实现第三方登录和API保护。 - JWT(JSON Web Tokens):可使用JWT进行状态less的认证,提高系统的可扩展性。 - CORS(Cross-Origin Resource Sharing):SpringSecurity...

    springSecurity3中文文档

    第二章:springsecurity起步 第三章:增强用户体验 第四章:凭证安全存储 第五章:精确的访问控制 第六章:高级配置和扩展 第七章:访问控制列表(ACL) 第八章:对OpenID开放 第九章:LDAP目录服务 第十章:使用...

    spring security 3.x第五章例子

    Spring Security 是一个强大的和高度可定制的身份验证和...总的来说,Spring Security 3.x第五章的实例将帮助开发者深入理解这个框架的使用,通过具体的代码示例来实践安全性配置,从而更好地保护他们的Spring应用。

    SpringSecurity素材.rar

    9. **OAuth2整合**:如果视频内容深入,可能会涉及到如何集成SpringSecurity与OAuth2服务提供商,实现第三方登录功能。 10. **安全最佳实践**:最后,可能会分享一些安全编码的最佳实践,例如避免SQL注入、XSS攻击...

    《Spring Security3》第四章第四部分翻译(Remember me后台存储和SSL)附前四章doc文件

    《Spring Security3》第四章第四部分主要探讨了Remember me服务的后台存储机制以及如何结合SSL(Secure Sockets Layer)来增强应用的安全性。这一部分的知识点涵盖了Spring Security中Remember me的功能,用户身份...

    Spring Security 教程(Spring Security Tutorial)1

    - Spring Security 不仅仅关注URL级别的访问控制,还可以在方法级别实现安全控制,这样可以在业务逻辑层细化权限管理。 5. **基于角色的登录**: - 用户登录后,Spring Security 可以根据用户的角色分配不同的...

    spring security 入门经典教程

    - 第5章:服务层安全,讲解如何保护应用的服务层,确保业务逻辑的安全性。 - 第6章:配置替代认证提供者,这一章节可能讨论了如何集成不同的认证机制,例如使用LDAP或OAuth等。 - 第7章:使用ACL实现业务对象安全...

    spring security第一个项目

    在“spring security第一个项目”中,我们将探讨如何搭建一个基础的Spring Security环境,实现用户登录验证以及权限控制。 首先,我们需要理解Spring Security的基本架构。它由四个主要组件组成:Filter Security ...

    SpringMVC集成SpringSecurity

    5. **SpringSecurity配置**:在SpringSecurity配置文件中,我们需要定义`&lt;http&gt;`元素来配置URL保护策略,`&lt;authentication-manager&gt;`元素来定义认证机制,例如使用`&lt;user-service&gt;`元素配置内存中的用户信息。...

Global site tag (gtag.js) - Google Analytics