JSP 标签库
声明标签库
要使用任何标签,您必须在 JSP 中声明安全标签库
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
authorize 标签
此标签用于确定是否应评估其内容。在 Spring Security 3.0 中,它可以通过两种方式使用。
|
Spring Security 2.0 中的遗留选项也受支持,但不建议使用。 |
第一种方法使用 web-security 表达式,该表达式在标签的 access 属性中指定。表达式评估委托给应用程序上下文中定义的 SecurityExpressionHandler<FilterInvocation>(您应该在 <http> 命名空间配置中启用 web 表达式以确保此服务可用)。例如,您可能有
<sec:authorize access="hasRole('supervisor')">
This content will only be visible to users who have the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s.
</sec:authorize>
当与 Spring Security 的 PermissionEvaluator 结合使用时,该标签也可以用于检查权限
<sec:authorize access="hasPermission(#domain,'read') or hasPermission(#domain,'write')">
This content will only be visible to users who have read or write permission to the Object found as a request attribute named "domain".
</sec:authorize>
一个常见的需求是,在用户确实被允许点击的情况下,只显示一个特定的链接。我们如何预先确定是否允许?这个标签也可以在另一种模式下运行,允许您将特定的 URL 定义为属性。如果用户被允许调用该 URL,则评估标签体。否则,它将被跳过。所以您可能会有类似以下的代码
<sec:authorize url="/admin">
This content will only be visible to users who are authorized to send requests to the "/admin" URL.
</sec:authorize>
要使用此标签,您的应用程序上下文中还必须有一个 WebInvocationPrivilegeEvaluator 实例。如果您正在使用命名空间,则会自动注册一个。这是一个 DefaultWebInvocationPrivilegeEvaluator 实例,它为提供的 URL 创建一个虚拟 Web 请求,并调用安全拦截器以查看该请求是成功还是失败。这允许您委托给通过 <http> 命名空间配置中的 intercept-url 声明定义的访问控制设置,并避免在 JSP 中重复信息(例如所需的角色)。您还可以将此方法与 method 属性(提供 HTTP 方法,例如 POST)结合使用,以实现更具体的匹配。
您可以通过将 var 属性设置为变量名,将评估标签(是否授予或拒绝访问)的布尔结果存储在页面上下文范围变量中,从而避免在页面其他地方重复和重新评估条件。
禁用标签授权以进行测试
对未经授权的用户隐藏页面中的链接并不能阻止他们访问该 URL。例如,他们可以直接在浏览器中输入它。作为测试过程的一部分,您可能希望显示隐藏区域,以检查链接是否确实在后端受到保护。如果您将 spring.security.disableUISecurity 系统属性设置为 true,则 authorize 标签仍会运行,但不会隐藏其内容。默认情况下,它还会将内容用 <span class="securityHiddenUI">…</span> 标签包围起来。这允许您以特定的 CSS 样式(例如不同的背景颜色)显示“隐藏”内容。例如,启用此属性后,尝试运行“tutorial”示例应用程序。
如果您想更改环绕文本(默认的 span 标签),也可以设置 spring.security.securedUIPrefix 和 spring.security.securedUISuffix 属性(或者使用空字符串完全删除它)。
authentication 标签
此标签允许访问存储在安全上下文中的当前 Authentication 对象。它直接在 JSP 中呈现对象的属性。例如,如果 Authentication 的 principal 属性是 Spring Security 的 UserDetails 对象的实例,那么使用 <sec:authentication property="principal.username" /> 将呈现当前用户的名称。
当然,对于这类事情不一定非要使用 JSP 标签,有些人更喜欢在视图中保留尽可能少的逻辑。您可以在 MVC 控制器中访问 Authentication 对象(通过调用 SecurityContextHolder.getContext().getAuthentication()),并将数据直接添加到模型中,供视图呈现。
accesscontrollist 标签
此标签仅在与 Spring Security 的 ACL 模块一起使用时有效。它检查指定域对象所需权限的逗号分隔列表。如果当前用户拥有所有这些权限,则评估标签体。如果他们没有,则跳过。
|
一般来说,此标签应被视为已弃用。请改用 authorize 标签。 |
以下列表显示了一个示例
<sec:accesscontrollist hasPermission="1,2" domainObject="${someObject}">
<!-- This will be shown if the user has all of the permissions represented by the values "1" or "2" on the given object. -->
</sec:accesscontrollist>
权限被传递给应用程序上下文中定义的 PermissionFactory,将其转换为 ACL Permission 实例,因此它们可以是工厂支持的任何格式。它们不必是整数。它们可以是字符串,例如 READ 或 WRITE。如果未找到 PermissionFactory,则使用 DefaultPermissionFactory 的实例。应用程序上下文中的 AclService 用于加载所提供对象的 Acl 实例。使用所需权限调用 Acl 以检查是否授予所有权限。
此标签也支持 var 属性,与 authorize 标签相同。
csrfInput 标签
如果启用了 CSRF 保护,此标签会插入一个隐藏的表单字段,其中包含 CSRF 保护令牌的正确名称和值。如果未启用 CSRF 保护,此标签不会输出任何内容。
通常,Spring Security 会自动为您使用的任何 <form:form> 标签插入 CSRF 表单字段,但如果由于某种原因您无法使用 <form:form>,csrfInput 是一个方便的替代品。
您应该将此标签放置在 HTML <form></form> 块中,就像您通常放置其他输入字段一样。请勿将此标签放置在 Spring <form:form></form:form> 块中。Spring Security 会自动处理 Spring 表单。以下列表显示了一个示例
<form method="post" action="/do/something">
<sec:csrfInput />
Name:<br />
<input type="text" name="name" />
...
</form>
csrfMetaTags 标签
如果启用 CSRF 保护,此标签会插入元标签,其中包含 CSRF 保护令牌表单字段、标头名称和 CSRF 保护令牌值。这些元标签对于在应用程序的 JavaScript 中使用 CSRF 保护非常有用。
您应该将 csrfMetaTags 放置在 HTML <head></head> 块中,就像您通常放置其他元标签一样。一旦您使用此标签,您就可以通过 JavaScript 访问表单字段名称、标头名称和令牌值。本示例中使用 JQuery 以简化任务。以下列表显示了一个示例
<!DOCTYPE html>
<html>
<head>
<title>CSRF Protected JavaScript Page</title>
<meta name="description" content="This is the description for this page" />
<sec:csrfMetaTags />
<script type="text/javascript" language="javascript">
var csrfParameter = $("meta[name='_csrf_parameter']").attr("content");
var csrfHeader = $("meta[name='_csrf_header']").attr("content");
var csrfToken = $("meta[name='_csrf']").attr("content");
// using XMLHttpRequest directly to send an x-www-form-urlencoded request
var ajax = new XMLHttpRequest();
ajax.open("POST", "https://www.example.org/do/something", true);
ajax.setRequestHeader("Content-Type", "application/x-www-form-urlencoded data");
ajax.send(csrfParameter + "=" + csrfToken + "&name=John&...");
// using XMLHttpRequest directly to send a non-x-www-form-urlencoded request
var ajax = new XMLHttpRequest();
ajax.open("POST", "https://www.example.org/do/something", true);
ajax.setRequestHeader(csrfHeader, csrfToken);
ajax.send("...");
// using JQuery to send an x-www-form-urlencoded request
var data = {};
data[csrfParameter] = csrfToken;
data["name"] = "John";
...
$.ajax({
url: "https://www.example.org/do/something",
type: "POST",
data: data,
...
});
// using JQuery to send a non-x-www-form-urlencoded request
var headers = {};
headers[csrfHeader] = csrfToken;
$.ajax({
url: "https://www.example.org/do/something",
type: "POST",
headers: headers,
...
});
<script>
</head>
<body>
...
</body>
</html>
如果未启用 CSRF 保护,csrfMetaTags 不会输出任何内容。