9.3.1 使用 Spring 表达式进行安全保护

表 9.4 中的大多数方法都是一维的,也就是说我们可以使用 hasRole() 限制某个特定的角色,但是我们不能在相同的路径上同时通过 hasIpAddress() 限制特定的 IP 地址。

另外,除了表 9.4 定义的方法以外,我们没有办法使用其他的条件。如果我们希望限制某个角色只能在星期二进行访问的话,该怎么办呢?

在第 3 章中,我们看到了如何使用 Spring 表达式语言(Spring Expression Language,SpEL),将其作为装配 bean 属性的高级技术。借助 access() 方法,我们也可以将 SpEL 作为声明访问限制的一种方式。例如,如下就是使用 SpEL 表达式来声明具有 ROLE_SPITTER 角色才能访问 /spitter/me URL:

.antMatchers("/spitter/me").access("hasRole('ROLE_SPITTER')");

这个对 /spitter/me 的安全限制与开始时的效果是等价的,只不过这里使用了 SpEL 来描述安全规则。如果当前用户被授予了给定角色的话,那 hasRole() 表达式的计算结果就为 true。

让 SpEL 更强大的原因在于,hasRole() 仅是 Spring 支持的安全相关表达式中的一种,表 9.5 列出了 Spring Security 支持的所有 SpEL 表达式。

安全表达式

计算结果

authentication

用户的认证对象

denyAll

结果始终为 false

hasAnyRole(list of roles)

如果用户被授予了列表中任意的指定角色,结果为 true

hasRole(role)

如果用户被授予了指定的角色,结果为 true

hasIpAddress(IP Address)

如果请求来自指定 IP 的话,结果为 true

isAnonymous()

如果当前用户为匿名用户,结果为 true

isAuthenticated()

如果当前用户进行了认证的话,结果为 true

isFullyAuthenticated()

如果当前用户进行了完整认证的话(不是通过 Remember-me 功能进行的认证),结果为 true

isRememberMe()

如果当前用户是通过 Remember-me 自动认证的,结果为 true

permitAll

结果始终为true

principal

用户的principal对象

在掌握了 Spring Security 的 SpEL 表达式后,我们就能够不再局限于基于用户的权限进行访问限制了。例如,如果你想限制 /spitter/me URL 的访问,不仅需要 ROLE_SPITTER,还需要来自指定的 IP 地址,那么我们可以按照如下的方式调用 access() 方法:

.antMatchers("/spitter/me")
.access("hasRole('ROLE_SPITTER') and hasIpAddress('192.168.1.2')");

我们可以使用 SpEL 实现各种各样的安全性限制。我敢打赌,你已经在想象基于 SpEL 所能实现的那些有趣的安全性限制了。

但现在,让我们看一下 Spring Security 拦截请求的另外一种方式:强制通道的安全性。

Last updated