1. 介绍
- 本文主要是关注于
Spring Security
的表达式。会有很多案例给大家演示一下怎么使用这些表达式 - 掌握了
Spring Security
表达式,会让你很灵活地实现复杂的ACL控制规则
2. Maven 依赖
- 想要使用
Spring Security
,你需要再pom.xml
中加入以下的内容。
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
</dependencies>
-
最新的版本可以点击这里查看
-
温馨提示:这里只是包含了
Spring Security
的依赖,不要忘记把spring-core
和spring-context
的依赖都加进去
3. 配置
-
首先,我们先新建一个Java配置类
SecurityWithoutCsrfConfig
-
该类需要继承
WebSecurityConfigurerAdapter
,这里我们就可以使用该基类所提供的方法。具体代码如下:
@Configuration
@EnableAutoConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityWithoutCsrfConfig extends WebSecurityConfigurerAdapter {
...
}
- 我们也可以通过XML的方式进行配置,不过不推荐。实例代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans ...>
<global-method-security pre-post-annotations="enabled"/>
</beans:beans>
4. 表达式讲解
- 下面是我们可能会用到的表达式:
hasRole, hasAnyRole
hasAuthority, hasAnyAuthority
permitAll, denyAll
isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated
principal, authentication
hasPermission
- 接下来我们回详细地介绍每个表达式的使用。
4.1. hasRole, hasAnyRole
- 这些表达式负责定义应用程序中特定URL或方法的访问控制或授权。
- 下面是具体的写法:
@Override
protected void configure(final HttpSecurity http) throws Exception {
...
.antMatchers("/auth/admin/*").hasRole("ADMIN")
.antMatchers("/auth/*").hasAnyRole("ADMIN","USER")
...
}
-
在此示例中,我们指定对以
/auth/
开头的所有链接进行访问权限的限制,只有角色USER
或角色ADMIN
登录的用户有访问权限。此外,要访问以/auth/admin/
开头的链接,我们需要在系统中具有ADMIN
角色。 -
在XML中可以进行一下的配置:
<http>
<intercept-url pattern="/auth/admin/*" access="hasRole('ADMIN')"/>
<intercept-url pattern="/auth/*" access="hasAnyRole('ADMIN','USER')"/>
</http>
4.2. hasAuthority, hasAnyAuthority
-
Roles
和Authorities
在Spring
中是很相似的 -
主要区别在于,角色具有特殊的语义 - 从
Spring Security 4
开始,任何与角色相关的方法都会自动添加ROLE_
前缀。 -
hasAuthority('ROLE_ADMIN')
类似于hasRole('ADMIN')
,因为ROLE_
前缀会自动添加。 -
我们使用
authorities
来赋予用户权限的时候,比较大的好处是我们不必使用ROLE_
前缀。 -
下面示例是使用
authorities
的代码
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user1").password("user1Pass").authorities("USER")
.and().withUser("admin").password("adminPass").authorities("ADMIN");
}
- 我们可以使用一下
authorities
表达式来限定权限
@Override
protected void configure(final HttpSecurity http) throws Exception {
...
.antMatchers("/auth/admin/*").hasAuthority("ADMIN")
.antMatchers("/auth/*").hasAnyAuthority("ADMIN", "USER")
...
}
- 我们可以看到,这里是没有出现到
roles
相关的配置。 - 可以通过一下方式来配置XML文件。
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user1" password="user1Pass" authorities="ROLE_USER"/>
<user name="admin" password="adminPass" authorities="ROLE_ADMIN"/>
</user-service>
</authentication-provider>
</authentication-manager>
<http>
<intercept-url pattern="/auth/admin/*" access="hasAuthority('ADMIN')"/>
<intercept-url pattern="/auth/*" access="hasAnyAuthority('ADMIN','USER')"/>
</http>
4.3. permitAll, denyAll
-
这是两个比较简单的方法,要么就是拒绝指定的所有请求,要么就是允许指定的所有请求。
-
示例:
...
.antMatchers("/*").permitAll()
...
-
使用此配置,我们将授权所有用户(匿名用户和登录用户)访问以
'/'
开头的页面。 -
我们也可以拒绝访问整个网站,代码如下:
...
.antMatchers("/*").denyAll()
...
- 以下的XML配置可以达到同样的效果。
<http auto-config="true" use-expressions="true">
<intercept-url access="permitAll" pattern="/*" /> <!-- Choose only one -->
<intercept-url access="denyAll" pattern="/*" /> <!-- Choose only one -->
</http>
4.4. isAnonymous, isRememberMe, isAuthenticated, isFullyAuthenticated
- 在本小节中,我们将重点关注与用户登录状态相关的表达式。我们从没有登录页面的用户开始。通过在Java配置中指定以下内容,我们允许所有未经授权的用户访问我们的主页:
...
.antMatchers("/*").anonymous()
...
- XML配置如下:
<http>
<intercept-url pattern="/*" access="isAnonymous()"/>
</http>
- 如果希望访问网站的都需要登录,那么我们可以使用
isAuthenticated()
方案进行以下的配置:
...
.antMatchers("/*").authenticated()
...
- or XML version:
- XML版本如下:
<http>
<intercept-url pattern="/*" access="isAuthenticated()"/>
</http>
- 此外,我们还有两个表达式,
isRememberMe()
和isFullyAuthenticated()
。通过使用cookie,Spring可以实现存储功能,因此无需每次都登录系统。 - 为了能够访问仅通过
记住我
的功能登录的用户,我们可以使用:
...
.antMatchers("/*").rememberMe()
...
- XML版本如下:
<http>
<intercept-url pattern="*" access="isRememberMe()"/>
</http>
-
最后,即使用户已经登录,我们有时候想要求用户再次进行身份验证。例如,用户想要更改设置或付款信息。
-
为了做到这一点,我们可以指定
isFullyAuthenticated()
,如果用户不是匿名用户或记住我的用户,则返回true:
...
.antMatchers("/*").fullyAuthenticated()
...
- XML版本
<http>
<intercept-url pattern="*" access="isFullyAuthenticated()"/>
</http>
4.5. principal, authentication
-
这些表达式允许分别从
SecurityContext
和respectively
表示当前授权(或匿名)用户的principal
对象和当前的Authentication
对象 -
例如,我们可以使用委托人来加载用户的电子邮件,头像或登录用户可访问的任何其他数据。
-
身份验证提供有关完整身份验证对象的信息及其授予的权限
4.6. hasPermission APIs
-
如表达式已经设置在了
Spring Security
的ACL系统中,系统是允许我们根据抽象权限指定对各个域对象的授权约束。 -
让我们来看一个例子。我们有一项服务,允许合作撰写文章,与主编辑,决定其他作者提出的文章应该发表
-
为了允许使用此类服务,我们可以使用访问控制方法创建以下方法:
@PreAuthorize("hasPermission(#articleId, 'isEditor')")
public void acceptArticle(Article article) {
…
}
- 只有授权的用户可以在服务中调用此方法
网友评论