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. 一篇RxJava友好的文章(二)

    上一篇文章介绍了rxjava的基本用法,和一些常用的操作符,以及rxjava的链式操作带来的好处.由于rxjava非常的强大,让我如此的痴迷,我打算写五篇文章,专门讲解rxjava 常见的操作符和用法 ...

  2. redis 过期回调通知

    redis 过期回调通知 背景 在使用redis的过程中,有时我们会遇到这种情景,当key过期的时候,我们需要去重新做一些操作,比如重新生成value等.之前,一直用的是添加一个celery定时任务, ...

  3. JQuery 过滤选择器 与属性修改的方法演示比较

    文本匹配 在表单输入项里面输入值,根据输入值,点击判断按钮,让对应的复选框选中 <html> <head> <meta http-equiv="Content- ...

  4. SAP库存历史库存表更新逻辑 (转)

    根据库存类型的不同,库存信息保存在不同的表中,具体而言见下表 库存类型 当前库存 历史库存 库存金额 历史库存金额 工厂级别库存 MARC MARCH MBEW MBEWH MBEW 库存地点库存 M ...

  5. Linux下常用压缩 解压命令与压缩比率对比

    常用的格式有:tar, tar.gz(tgz), tar.bz2, 不同方式,压缩和解压方式所耗CPU时间和压缩比率也差异也比较大. 1. tar只是打包动作,相当于归档处理,不做压缩:解压也一样,只 ...

  6. 22.1 高级函数【JavaScript高级程序设计第三版】

    函数是JavaScript 中最有趣的部分之一.它们本质上是十分简单和过程化的,但也可以是非常复杂和动态的.一些额外的功能可以通过使用闭包来实现.此外,由于所有的函数都是对象,所以使用函数指针非常简单 ...

  7. MySQL Limit 限定查询记录数

    MySQL Limit 限定查询记录数 MySQL LIMIT MySQL 中 LIMIT 关键字用于限定查询记录返回最大数目. 语法: ... LIMIT offset , rows 该语法中,of ...

  8. php图片上传旋转压缩方法

    用到php的exif扩展,需要开启exif 在php.ini文件中去掉exif组件的注释 extension=php_mbstring.dll //要放在php_exif.dll前面让它先加载 ext ...

  9. git 代码托管使用方法

    Git代码托管 1 准备材料 在coding,github这些代码托管网站上申请一个账户. Linux平台什么需要一个git,如ubuntu 需要 $ sudo apt-get install git ...

  10. manjaro安装teamviewer实现远程连接

    不要安装库里面的这两个版本,安装后桌面快捷方式和命令行运行都正常显示窗口,但没有teamviewer ID和随机密码 12.x版本也不用下载尝试了 ➜ ~ teamviewer Init...Chec ...