Spirng Security本身提供了一个JSP标签库,而Thymeleaf通过特定的方言实现了与Spring Security的集成。
使用Spring Security的JSP标签库
Spring Security的JSP标签库很小,只包含是三个标签:
为了使用JSP标签库,需要在JSP中声明它:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
- 1
访问认证信息的细节
如下是一个简单的示例:
Hello <security:authentication property="principal.username" />!
- 1
其中property用来标示用户认证对象的一个属性。可用的属性取决于用户认证的方式。但是,我们可以依赖几个通用的属性:
如下示例展现了如何将标签的值赋给一个变量——loginId:
<security:authentication property="principal.username" var="loginId" />
- 1
这个变量默认是定义在页面作用域内的,如果想将其定义为其他作用域,可以通过scope属性来声明。如:
<security:authentication property="principal.username" var="loginId" scope="request" />
- 1
<security:authentication>
标签非常有用,下面是更多的功能。
条件性渲染内容
有时候视图上的一部分内容需要根据用户被授予了什么权限来确定是否渲染。Spring Security的JSP标签能够根据用户被授予的权限有条件地渲染页面的部分内容。下面是一个简单的示例:
<sec:authorize access="hasRole('ROLE_ADMIN')">
...
</sec:authorize>
- 1
- 2
- 3
access属性被赋值为一个SpEL表达式,只有当用户拥有admin权限,标签内的内容才会渲染出来。
借助于SpEL表达式,我们可以构造出更有意思的表达式。例如,假设应用中的一些管理功能只能对用户名为habuma的用户有用,可以这样实现:
<security:authorize access="isAuthenticated() and principal.username=='habuma'">
<a href="/admin">Administration</a>
</security:authorize>
- 1
- 2
- 3
这并不是一个理想的例子,如果你仔细一些就会发现问题,这个例子只是从视图上阻止了链接渲染,但是没有什么可以阻止别人在浏览器的地址栏手动输入“/admin”这各URL。根据前面所学,这是一个很容易解决的问题。在安全配置中,添加一个antMatchers()方法对链接进行限制即可。
.antMatchers("/admin")
.access("isAuthenticated() and principal.username=='habuma'");
- 1
- 2
上面的配置虽然完成了功能,但是在两个地方使用了相同的SpEL表达式,这种重复并不是一件令人愉快的事。要解决这个问题,我们要借助<security:authorize>
标签的url属性:
<security:authorize url="/admin">
<Spring:url value="/admin" var="admin_url" />
<a href="${admin_url}">Admin</a>
</security>
- 1
- 2
- 3
- 4
url属性对一个给定的URL模式会间接引用其安全性约束,而我们已经在Spring Security配置中为“/admin”声明了安全性约束,因而在<security:authorize>
标签中只需要声明路径即可。
使用Thymeleaf的Spring Security方言
下表列出了安全方言所提供的属性:
要使用Thymeleaf的Spring Security方言,我们需要做三项配置:
- a、引入Maven依赖
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
- b、在配置中使用SpirngTemplateEngine来注册SpringSecurityDislect。
@Bean
public SpringTemplateEngine templateEngine(TemplateResolver reslover){
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(resolver);
templateEngine.addDislect(new SpringSecurityDialect()); //注册安全方言
return templateEngine;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- c、安全方言注册完成之后,我们就可以在Thymeleaf模板中使用它的属性了。不过我们还需要在使用这些属性的模板中声明安全命名空间:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
...
</html>
- 1
- 2
- 3
- 4
- 5
- 6
现在,配置已经完成。假设我们想要为认证用户渲染“Hello”文本。如下的Thymeleaf模板代码片段就能完成此任务:
<div sec:authorize="isAuthentecated()">
Hello <span sec:authentication="name">someone</span>
</div>
- 1
- 2
- 3
与JSP中URL功能相同的功能实现如下:
<span sec:authorize-url="/admin">
<a th:href="@{/admin}">Admin</a>
</span>
- 1
- 2
- 3
本系列学习笔记到此结束,学习完理论知识过后建议做一个小Demo加深印象,在这个过程中,你或许会遇到一些书本上没提到的有意思的小Bug,我的小Demo已经分享到Github,上面有我在练习过程中遇到的几个有趣的小Bug,相关链接和介绍在第一篇:SpringSecurity学习笔记之一:SpringSecurity概述及Github项目克隆
欢迎克隆阅读。