Chapter 15. 基于表达式的权限控制

Spring Security 3.0介绍了使用Spring EL表达式的能力,作为一种验证机制 添加简单的配置属性的使用和访问决策投票,就像以前一样。 基于表达式的安全控制是建立在相同架构下的,但是允许使用复杂的布尔逻辑 包含在单独的表达式中。

15.1. 概述

Spring Security使用Spring El来支持表达式,你应该看一下如何工作的 如果你对深入了解这个话题感兴趣的话。表达式是执行在一个“根对象” 上的,作为一部分执行上下文。Spring Security使用特定的类对应web和方法安全,作为根对象, 为了提供内建的表达式,访问值,比如当前的认证主体。

15.1.1. 常用内建表达式

表达式根对象的基本类是SecurityExpressionRoot。 这个提供了一些常用的表达式,都可以在web和method权限控制中使用。

Table 15.1. 常用内建表达式

表达式 说明
hasRole([role]) 返回 true 如果当前主体拥有特定角色。
hasAnyRole([role1,role2]) 返回 true 如果当前主体拥有任何一个提供的角色 (使用逗号分隔的字符串队列)
principal 允许直接访问主体对象,表示当前用户
authentication 允许直接访问当前 Authentication对象 从SecurityContext中获得
permitAll 一直返回true
denyAll 一直返回false
isAnonymous() 如果用户是一个匿名登录的用户 就会返回 true
isRememberMe() 如果用户是通过remember-me 登录的用户 就会返回 true
isAuthenticated() 如果用户不是匿名用户就会返回true
isFullyAuthenticated() 如果用户不是通过匿名也不是通过remember-me登录的用户时, 就会返回true

15.2. Web 安全表达式

为了保护单独的URL,你需要首先把<http>的 use-expressions属性设置为true。Spring Security会把 <intercept-url>access当做包含了Spring EL表达式。 表达式应该返回boolean,定义访问是否应该被允许,比如:

  <http use-expressions="true">
<intercept-url pattern="/admin*"
access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
...
</http>

这里我们已经定义了应用的“admin”范围(通过URL模式定义的) 应该只对拥有“admin”权限的用户有效,并且用户要在本地子网的IP地址下。 我们已经看到了内建的hasRole表达式,在上一章节。 表达式hasIpAddress是一个附加的内建表达式,是由web安全提供的。 它是由WebSecurityExpressionRoot定义的,它的实例作为表达式根对象 当执行web权限表达式时。这个对象也直接暴露了HttpServletRequest对象 使用request这个名字,所以你可以直接调用request在一个表达式里。

如果使用了表达式,一个WebExpressionVoter会被添加到 AccessDecisionManager中,这是被命名空间创建的。 所以如果你没有使用命名空间还希望使用表达式,你必须把这些添加到你的配置中。

15.3. 方法安全表达式

方法安全有一点儿复杂,比单独允许和拒绝规则来说。Spring Security 3.0介绍了一些新注解, 为了对复杂的表达式进行支持。

15.3.1. @Pre 和 @Post 注解

这里有四个注解,支持表达式属性允许进行前置和后置调用验证检测,也支持过滤提交的 集合参数或返回值。它们是@PreAuthorize@PreFilter@PostAuthorize 和 @PostFilter。它们可以通过 global-method-security 命名空间元素启用:

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

15.3.1.1. 访问控制使用 @PreAuthorize 和 @PostAuthorize

使用最广泛的注解是@PreAuthorize,它可以决定一个方法是否可以被调用。 比如(来自“Contacts”实例应用)

  @PreAuthorize("hasRole('ROLE_USER')")
public void create(Contact contact);

这意味着只允许拥有"ROLE_USER"角色的用户访问。 很明显,相同的事情可以简单实用传统的配置方法,简单的配置属性来要求角色。 但是如果是这样呢:

  @PreAuthorize("hasPermission(#contact, 'admin')")
public void deletePermission(Contact contact, Sid recipient, Permission permission);

这里我们其实使用了方法参数作为表达式的一部分来决定是否当前的用户拥有“admin” 表达式对给定的contract。内建的 hasPermission()表达式链接到 Spring Security ACL模块,通过applicaton context。你可以访问任何方法参数,通过名称 就像表达式的变量,在编译的时候使用debug信息。任何Spring EL功能都可以在表达式里使用, 所以你可以访问参数的属性。比如,如果你希望特定的方法只允许访问一个用户名和contract匹配, 你可以写成

  @PreAuthorize("#contact.name == authentication.name)")
public void doSomething(Contact contact);

这里我们访问了另一个内建的表达式,authentication, 它是保存在安全上下文里的Authentication实例。 你也可以直接访问它的“principal”属性, 使用principal表达式。这个值一般是一个 UserDetails实例,所以你可能使用一个 像是principal.username或是 principal.enabled的表达式。

不太常见的是,你可能希望之星一个访问控制检测,在方法调用之后。这个可以使用 @PostAuthorize 注解。为了访问一个方法的返回值, 使用表达式中的内建名称returnObject

15.3.1.2. 过滤使用 @PreFilter 和 @PostFilter

你可能已经知道了,Spring Security支持对集合和数据的过滤, 现在也可以使用表达式实现了。通常是用在一个方法的返回值中。比如:

  @PreAuthorize("hasRole('ROLE_USER')")
@PostFilter("hasPermission(filterObject, 'read') or hasPermission(filterObject, 'admin')")
public List<Contact> getAll();

当使用@PostFilter注解时,Spring Security遍历返回的集合 删除任何表达式返回false的元素。名字filterObject引用 集合中的当前对象。你也可以在方法调用之前进行过滤,使用@PreFilter 虽然很少需要这样做。这个语法是一样的,但是如果这里有更多参数,都是集合类型 然后你必须使用注解的filterTarget属性选择其中一个。

注意过滤显然不是一个让你读取数据查询的解决方法。如果你过滤大型集合,删除很多实体, 然后这就会是非常没有效率的。

spring security注解(1)的更多相关文章

  1. spring security 注解@EnableGlobalMethodSecurity详解

     1.Spring Security默认是禁用注解的,要想开启注解,需要在继承WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解 ...

  2. Spring Security 学习总结

    Spring Security Spring Security是基于Spring提供声明式安全保护的安全性框架.Spring Security提供了完整的安全性解决方案,能够在Web请求级别和方法调用 ...

  3. Spring Boot + Spring Cloud 实现权限管理系统 (Spring Security 版本 )

    技术背景 到目前为止,我们使用的权限认证框架是 Shiro,虽然 Shiro 也足够好用并且简单,但对于 Spring 官方主推的安全框架 Spring Security,用户群也是甚大的,所以我们这 ...

  4. Spring Boot + Spring Cloud 实现权限管理系统 后端篇(二十五):Spring Security 版本

    在线演示 演示地址:http://139.196.87.48:9002/kitty 用户名:admin 密码:admin 技术背景 到目前为止,我们使用的权限认证框架是 Shiro,虽然 Shiro ...

  5. Spring Security 快速上手

    Spring Security 框架简介 Spring Security 说明 Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案 关于安全方面的两 ...

  6. Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼.本文主要介绍 同域 和 跨域 两种不同场景单点登录的实现原理,并使用 Spring ...

  7. spring security 在controller层 方法级别使用注解 @PreAuthorize("hasRole('ROLE_xxx')")设置权限拦截 ,无权限则返回403

    1.前言 以前学习的时候使用权限的拦截,一般都是对路径进行拦截 ,要么用拦截器设置拦截信息,要么是在配置文件内设置拦截信息, spring security 支持使用注解的形式 ,写在方法和接口上拦截 ...

  8. Spring Security OAuth2 开发指南

    官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html 翻译及修改补充:Alex Liao. 转载请注明来源:htt ...

  9. SPRING SECURITY JAVA配置:Web Security

    在前一篇,我已经介绍了Spring Security Java配置,也概括的介绍了一下这个项目方方面面.在这篇文章中,我们来看一看一个简单的基于web security配置的例子.之后我们再来作更多的 ...

随机推荐

  1. django批量form表单处理

    1.应用说明 一般在表单信息录入中,如果存在许多重复提交的信息,我们就需要进行批量处理,比如学生信息的批量录入. 这里一种方式就是使用xlrd模块处理,把学生信息录入到系统内 另外一种方式就是采用我们 ...

  2. C语言结构体排序

    定义学生信息结构体和结构体数组,包括学号.两门百分制成绩和姓名;键盘输入 学生不多于 30 人的信息,以输入成绩为负数或大于 100 作为输入结束;按照学号和平均成绩排序,并输出学生信息 //输入学生 ...

  3. c++ 11 线程池的简单封装

    #include <condition_variable> #include <queue> #include <thread> #include <vect ...

  4. LeetCode970. 强整数

    问题:970. 强整数 用户通过次数0 用户尝试次数0 通过次数0 提交次数0 题目难度Easy 给定两个非负整数 x 和 y,如果某一整数等于 x^i + y^j,其中整数 i >= 0 且  ...

  5. 使用MyEclipse/Eclipse修改项目名称报Can't convert argument: null!

    报错: java.lang.IllegalArgumentException: Can't convert argument: null! 方法/步骤    报错原因:使用MyEclipse修改项目名 ...

  6. php精华之独孤九剑

    首先分享一个地址 https://segmentfault.com/a/1190000013696265(这个是主要的分享,人家作者写的非常棒

  7. [CQOI2007]余数求和 (分块+数学

    题目描述 给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数.例如G(10, 5)=5 ...

  8. spark的排序方法

    今天我们来介绍spark中排序的操作,spark的排序很简单,我们可以直接使用sortBy来进行,这个里面我们使用case clas,使用case class的好处是1.不用newjiukeyi 搞出 ...

  9. PHP代码审计1-审计环境与调试函数

    审计环境与调试函数 审计环境 测试环境 常用集成环境:phpStudy.WampServer #不同的操作系统下,漏洞测试的结果也可能不一样 PHP编写工具 EditPlu Notepad++ 代码审 ...

  10. MyBatis---简单关系查询

    联合查询 <!-- 处理关系查询相关的复杂返回数据类型(本例中未曾用到) --> <resultMap type="SchoolStudent" id=" ...