- 作者简介
- 内容提要
- 关于本书
- 路线图
- 代码规范与下载
- 作者在线
- 封面插图简介
- 前言
- 译者序
- 致谢
- 第1部分 Spring 的核心
- 第1章 Spring 之旅
- 第2章 装配 Bean
- 第3章 高级装配
- 第4章 面向切面的 Spring
- 第2部分 Web 中的 Spring
- 第5章 构建 Spring Web 应用程序
- 第6章 渲染 Web 视图
- 第7章 Spring MVC 的高级技术
- 第8章 使用 Spring Web Flow
- 第9章 保护 Web 应用
- 第3部分 后端中的 Spring
- 第10章 通过 Spring 和 JDBC 征服数据库
- 第11章 使用对象-关系映射持久化数据
- 第12章 使用 NoSQL 数据库
- 第13章 缓存数据
- 第14章 保护方法应用
- 第4部分 Spring 集成
- 第15章 使用远程服务
- 第16章 使用 Spring MVC 创建 REST API
- 第17章 Spring消息
- 第18章 使用 WebSocket 和 STOMP 实现消息功能
- 第19章 使用 Spring 发送 Email
- 第20章 使用 JMX 管理 Spring Bean
- 第21章 借助 Spring Boot 简化 Spring 开发
9.5.1 使用 Spring Security 的 JSP 标签库
Spring Security的JSP标签库很小,只包含三个标签,如表9.6所示。
表9.6 Spring Security通过JSP标签库在视图层上支持安全性
JSP标签 | 作 用 |
<security:accesscontrollist> | 如果用户通过访问控制列表授予了指定的权限,那么渲染该标签体中的内容 |
<security:authentication> | 渲染当前用户认证对象的详细信息 |
<security:authorize> | 如果用户被授予了特定的权限或者SpEL表达式的计算结果为true,那么渲染该标签体中的内容 |
为了使用JSP标签库,我们需要在对应的JSP中声明它:
只要标签库在JSP文件中进行了声明,我们就可以使用它了。让我们看看Spring Security提供的这三个标签是如何工作的。
访问认证信息的细节
借助Spring Security JSP标签库,所能做到的最简单的一件事情就是便利地访问用户的认证信息。例如,对于Web站点来讲,在页面顶部以用户名标示显示“欢迎”或“您好”信息是很常见的。这恰恰是<security:authentication>能为我们所做的事情。例如:
其中,property用来标示用户认证对象的一个属性。可用的属性取决于用户认证的方式。但是,我们可以依赖几个通用的属性,在不同的认证方式下,它们都是可用的,如表9.7所示。
表9.7 使用<security:authentication> JSP标签来访问用户的认证详情
认 证 属 性 | 描 述 |
authorities | 一组用于表示用户所授予权限的GrantedAuthority对象 |
Credentials | 用于核实用户的凭证(通常,这会是用户的密码) |
details | 认证的附加信息(IP地址、证件序列号、会话ID等) |
principal | 用户的基本信息对象 |
在我们的示例中,实际上渲染的是principal属性中嵌套的username属性。
当像前面示例那样使用时,<security:authentication>将在视图中渲染属性的值。但是如果你愿意将其赋值给一个变量,那只需要在var属性中指明变量的名字即可。例如,如下展现了如何将其设置给名为loginId的属性:
这个变量默认是定义在页面作用域内的。但是如果你愿意在其他作用域内创建它,例如请求或会话作用域(或者是能够在javax.servlet.jsp.PageContext中获取的其他作用域),那么可以通过scope属性来声明。例如,要在请求作用域内创建这个变量,那可以使用<security:authentication>按照如下的方式来设置:
<security:authentication>标签非常有用,但这只是Spring Security JSP标签库功能的基础功能。让我们来看一下如何根据用户的权限来渲染内容。
条件性的渲染内容
有时候视图上的一部分内容需要根据用户被授予了什么权限来确定是否渲染。对于已经登录的用户显示登录表单,或者对还未登录的用户显示个性化的问候信息都是毫无意义的。
Spring Security的<security:authorize>JSP标签能够根据用户被授予的权限有条件地渲染页面的部分内容。例如,在Spittr应用中,对于没有ROLE_SPITTER角色的用户,我们不会为其显示添加新Spitter记录的表单。程序清单9.9展现了如何使用<security:authorize>标签来为具有ROLE_SPITTER角色的用户显示Spitter表单。
程序清单9.9 使用<security:authorize>标签基于SpEL进行有条件地渲染
access属性被赋值为一个SpEL表达式,这个表达式的值将确定<security: authorize>标签主体内的内容是否渲染。这里我们使用了hasRole('ROLE_SPITTER')表达式来确保用户具有ROLE_SPITTER角色。但是,当你设置access属性时,可以任意发挥SpEL的强大威力,包括表9.5所示的Spring Security所提供的表达式。
借助于这些可用的表达式,可以构造出非常有意思的安全性约束。例如,假设应用中有一些管理功能只能对用户名为habuma的用户可用。也许你会像这样使用isAuthenticated()和principal表达式:
我相信你能设计出比这个更有意思的表达式,可以尽情发挥你的想象力来构造更多的安全性约束。借助于SpEL,选择其实是无限的。
但是我构造的这个示例还有一件事让人很困惑。尽管我想限制管理功能只能给habuma用户,但使用JSP标签表达式并不见得理想。确实,它能在视图上阻止链接的渲染。但是没有什么可以阻止别人在浏览器的地址栏手动输入“/admin”这个URL。
根据我们在本章前面所学,这是一个很容易解决的问题。在安全配置中,添加一个对antMatchers()方法的调用将会严格限制对“/admin”这个URL的访问。
现在,管理功能已经被锁定了。URL地址得到了保护,并且到这个URL的链接在用户没有授权使用的情况下不会显示。但是为了做到这一点,我们需要在两个地方声明SpEL表达式——在安全配置中以及在<security:authorize>标签的access属性中。有没有办法消除这种重复性,并且还要确保只有规则条件满足的情况下才渲染管理功能的链接呢?
这是<security:authorize>的url属性所要做的事情。它不像access属性那样明确声明安全性限制,url属性对一个给定的URL模式会间接引用其安全性约束。鉴于我们已经在Spring Security配置中为“/admin”声明了安全性约束,所以我们可以这样使用url属性:
因为只有基本信息中用户名为“habuma”的已认证用户才能访问“/admin” URL,所以只有满足以上条件,<security:authorize>标签主体中的内容才会被渲染。我们只在一个地方配置了表达式(安全配置中),但是在两个地方进行了应用。
Spring Security的JSP标签库非常便利,尤其是只给满足条件的用户渲染特定的视图元素时更是如此。如果我们选择Thymeleaf而不是JSP作为视图方案的话,我们其实还能延续这种好运气。我们已经看到Thymeleaf的Spring方言能够自动为表单添加隐藏的CSRF token,现在我们看一下Thymeleaf如何支持Spring Security。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论