文档章节

Spring Security 保护业务层

易帝加盟热火了
 易帝加盟热火了
发布于 2015/12/30 18:47
字数 2505
阅读 129
收藏 14
点赞 0
评论 0

保护业务层

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

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

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

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

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

       事先和事后授权在面向对象设计中提供了所谓的前置条件和后置条件(preconditions and ostconditions)。前置条件和后置条件允许开发者声明运行时的检查,从而保证在一个方法执行时特定的条件需要满足。在安全的事前授权和事后授权中,业务层的开发人员需要对特定的方法确定明确的安全信息,并在接口或类的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)登录并尝试修改密码。你会在尝试修改密码时,看到如下的出错界面:

校验方法安全

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

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

 

Java代码  收藏代码

  1. DEBUG - Could not complete request  

  2. o.s.s.access.AccessDeniedException: Access is denied  

  3. at o.s.s.access.vote.AffirmativeBased.decide  

  4. at o.s.s.access.intercept.AbstractSecurityInterceptor.beforeInvocation  

  5. ...  

  6. at $Proxy12.changePassword(Unknown Source)  

  7. at com.packtpub.springsecurity.web.controller.AccountController.  

  8. submitChangePasswordPage  

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

         我们只是在接口上添加了简单的声明就能够保证方法的安全,这是不是太令人兴奋了?

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

几种实现方法安全的方式

         除了@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。取决于你应用对轻便性的需求,你可能会觉得牺牲代码的轻便性但减少对特定环境的要求是值得的。

         要实现我们在第一个例子中的规则,我们需要作两个修改,首先在

<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"/>

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

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

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

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

<global-method-security>  

  <protect-pointcut access="ROLE_ADMIN"   

expression="execution(* com.packtpub.springsecurity.service.I*Service.*(..))"/>  

</global-method-security>  

切点表达式基于Spring AOP对AspectJ的支持。但是,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(..)) &&  args()"/>  

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

</global-method-security>  

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

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

         使用AOP来进行编程即便是经验丰富的开发人员可能也会感到迷惑。

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



© 著作权归作者所有

共有 人打赏支持
易帝加盟热火了
粉丝 0
博文 5
码字总数 2720
作品 0
东城
spring security 3.2.0.M1 方法级别教程 基于注解——第一部分

说明 一直在用spring security与shiro权限框架。最近spring security升级到了3.2.0.M1,所以更新了一下,看一下是否还是可以按照老方法使用。 基于方法级别的权限控制 spring security通过用户...

欧阳澄泓
2013/06/24
0
0
spring security 3.2.0.M1 方法级别教程 基于注解——第二部分

基于方法级别的权限控制 spring security通过用户角色的URL来限制访问,通常是用来保护Web应用程序的。然而,它也可以用在方法和类上,使编码或配置错误不允许后门进入受限制的数据。构建安全...

欧阳澄泓
2013/06/24
0
4
spring security学习,你妹真难

spring security可分一下几个: 1Web/HTTP 安全- 最复杂的部分。设置过滤器和相关的服务bean 来应用框架验证机制,保护URL,渲染登录和错误页面还有更多。业务类(方法)安全- 可选的安全服务...

moz1q1
2014/11/04
0
0
《Spring Security3》第一章第一部分翻译

本文为转载学习 原文链接:http://lengyun3566.iteye.com/blog/1069004 第一章 一个不安全应用的剖析 毫无疑问,安全是任何一个写于21世纪的web工程中最重要的架构组件之一。在这样一个时代,...

heroShane
2014/02/02
0
0
Spring 和 Django 安全机制的比较

做了一年多的python 方面的web开发工作,昨个有个同学问我Django的安全机制,我是一脸的茫然。每天使用公司开发框架的我,对这些东西了解的甚少,俨然成为一个真正的"码农",只知其然而不知其...

北方攻城师
2014/10/13
0
0
《Spring Security3》第二章第一部分翻译

本文为转载学习 原文链接:http://lengyun3566.iteye.com/blog/1078173 第二章 Spring Security起步 在本章中,我们将要学习Spring Security背后的核心理念,包括重要的术语和产品架构。我们...

heroShane
2014/02/03
0
0
让Spring Security 来保护你的Spring Boot项目吧

参考资料: 书籍:Spring实战(第4版) 第9章和第14章 Spring Security 参考手册 初识 Spring Security 程序猿DD的Spring Security学习笔记 Spring Security 简介 Spring Security是一个能够为...

潇潇漓燃
05/19
0
0
Acegi 为 Web services 的安全护航

安全,可是说是个老生常谈的话题,也可以说是个永恒的话题,无论是在那个领域,那个行业,安全都是非常的重要,写本文时正好看到一些矿难和香港游客 在印尼发生灾难的新闻,可见我们周围到处...

红薯
2011/04/22
904
2
使用 Spring Security 保护 Web 应用的安全 转载

在 Web 应用开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。如果在应用开发的后期才考虑安全的问题,就可能陷入一个两难的境...

小样
2012/08/24
0
0
Spring Boot + Spring Data JPA 项目整合开发记录(持续更新)

刚换了公司,项目架构师提出新的系统架构时还是愣了一下,搭建难度较低,很容易上手,但是对Spring Data JPA的了解不够深入,所以还是有些吃力,在框架搭建初期有许多东西并没有很好的集成。...

华山猛男
07/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

大数据教程(2.13):keepalived+nginx(多主多活)高可用集群搭建教程【自动化脚本】

上一章节博主为大家介绍了目前大型互联网项目的keepalived+nginx(主备)高可用系统架构体系,相信大家应该看了博主的文章对keepalived/nginx技术已经有一定的了解,在本节博主将为大家分享k...

em_aaron
2分钟前
0
0
Git 2.18版本发布:支持Git协议v2,提升性能

在最新的官方 Git 客户端正式版2.18中添加了对 Git wire 协议 v2 的支持,并引入了一些性能与 UI 改进的新特性。在 Git 的核心团队成员 Brandon Williams 公开宣布这一消息前几周,Git 协议 ...

六库科技
7分钟前
0
0
Java8新特性之接口

在JDK8以前,我们定义接口类中,方法都是抽象的,并且不能存在静态方法。所有的方法命名规则基本上都是 public [返回类型] [方法名](参数params) throws [异常类型] {}。 JDK8为接口的定义带...

developlee的潇洒人生
45分钟前
0
0
aop + annotation 实现统一日志记录

aop + annotation 实现统一日志记录 在开发中,我们可能需要记录异常日志。由于异常比较分散,每个 service 方法都可能发生异常,如果我们都去做处理,会出现很多重复编码,也不好维护。这种...

长安一梦
56分钟前
2
0
将博客搬至CSDN

AHUSKY
今天
1
0
Python web框架Django学习(1)

1.Django简介 (1)Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Django。Django是一个开放源代码的Web应用框架,由Python写成。 (2...

十年磨一剑3344
今天
0
0
Databook-数据之书

Databook-数据之书 用于数据分析的Jupyter Notebooks。 不需购买服务器,快速开始自己的数据分析过程。 源码:https://github.com/openthings/databook 作者:openthings,https://github.co...

openthings
今天
5
0
Python PIPEs

https://www.python-course.eu/pipes.php https://www.tutorialspoint.com/python/os_pipe.htm

zungyiu
今天
1
0
gRPC学习笔记

gRPC编程流程 1. proto文件定义 proto文件用于定义需要通过gRPC生成的接口,可以理解为接口定义文档 2. 通过构建工具生成服务基类代码-Maven或Gradle 3. 服务端开发 服务端实现类须实现通过构...

OSC_fly
今天
0
0
Docker Mac (三) Dockerfile 及命令

Dockerfile 最近学习docker的时候,遇到一件怪事,关于docker镜像可能会被破坏,还不知道它会有此措施 所以需要了解构建Dockerfile的正确方法 Dockerfile是由一系列命令和参数构成的脚本,这些命...

___大侠
今天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部