JSP Tag Libraries

Declaring the Taglib

要使用任何这些标签,您必须在您的 JSP 中声明 security 标记库:

To use any of the tags, you must have the security taglib declared in your JSP:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

The authorize Tag

此标签用于确定是否应计算其内容。在 Spring Security 3.0 中,它可以按照两种方式使用。

This tag is used to determine whether its contents should be evaluated or not. In Spring Security 3.0, it can be used in two ways.

Spring Security 2.0 中的旧有选项也受支持,但建议不要使用。

The legacy options from Spring Security 2.0 are also supported, but discouraged.

第一种方法使用 web-security expression,这是在标签的 access`属性中指定的。表达式求值委托给应用程序上下文中定义的 `SecurityExpressionHandler<FilterInvocation>(您应该在 `<http>`名称空间配置中启用 Web 表达式,以确保此服务可用)。因此,例如,您可能拥有:

The first approach uses a web-security expression, which is specified in the access attribute of the tag. The expression evaluation is delegated to the SecurityExpressionHandler<FilterInvocation> defined in the application context (you should have web expressions enabled in your <http> namespace configuration to make sure this service is available). So, for example, you might have:

<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 结合使用时,该标签还可用于检查权限:

When used in conjunction with Spring Security’s PermissionEvaluator, the tag can also be used to check permissions:

<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>

一个常见的要求是仅显示特定链接,假设用户实际上被允许单击该链接。我们如何预先确定是否允许某些操作?此标签还可以采用替代模式,该模式允许您定义特定网址作为属性。如果用户被允许调用该网址,则计算标签主体。否则,则跳过它。因此,您可能拥有如下内容:

A common requirement is to show only a particular link, assuming the user is actually allowed to click it. How can we determine in advance whether something is allowed? This tag can also operate in an alternative mode that lets you define a particular URL as an attribute. If the user is allowed to invoke that URL, the tag body is evaluated. Otherwise, it is skipped. So you might have something like:

<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 的一个实例,它为提供的网址创建虚拟 Web 请求,并调用安全拦截器来查看请求是否会成功或失败。这允许您委托给您通过使用 <http> 命名空间配置中的 intercept-url 声明定义的访问控制设置,并且不必在 JSP 中重复信息(如必需的角色)。您还可以将此方法与 method 属性(提供 HTTP 方法,如 POST)结合使用,以进行更具体的匹配。

To use this tag, you must also have an instance of WebInvocationPrivilegeEvaluator in your application context. If you are using the namespace, one is automatically registered. This is an instance of DefaultWebInvocationPrivilegeEvaluator, which creates a dummy web request for the supplied URL and invokes the security interceptor to see whether the request would succeed or fail. This lets you delegate to the access-control setup you defined by using intercept-url declarations within the <http> namespace configuration and saves having to duplicate the information (such as the required roles) within your JSPs. You can also combine this approach with a method attribute (supplying the HTTP method, such as POST) for a more specific match.

您可以通过将 var 属性设置为变量名称,将计算标签的布尔结果(无论是授权访问还是拒绝访问)存储在页面上下文范围变量中,从而避免在页面的其他位置重复和重新计算条件的需要。

You can store the Boolean result of evaluating the tag (whether it grants or denies access) in a page context scope variable by setting the var attribute to the variable name, avoiding the need for duplicating and re-evaluating the condition at other points in the page.

Disabling Tag Authorization for Testing

为未经授权的用户隐藏页面中的链接并不能阻止他们访问该网址。例如,他们可以将其直接键入浏览器。作为测试过程的一部分,您可能希望显示隐藏区域,以检查链接是否确实已在后端得到保护。如果您将 spring.security.disableUISecurity 系统属性设置为 true,则 authorize 标签仍然会运行,但不会隐藏其内容。默认情况下,它还会用 <span class="securityHiddenUI">…​</span> 标签将内容包围起来。这使您能够以特定的 CSS 样式(如不同的背景色)显示 “hidden” 内容。例如,尝试运行 “tutorial” 示例应用程序,并启用此属性。

Hiding a link in a page for unauthorized users does not prevent them from accessing the URL. They could just type it into their browser directly, for example. As part of your testing process, you may want to reveal the hidden areas, to check that links really are secured at the back end. If you set the spring.security.disableUISecurity system property to true, the authorize tag still runs but does not hide its contents. By default, it also surrounds the content with <span class="securityHiddenUI">…​</span> tags. This lets you to display “hidden” content with a particular CSS style, such as a different background color. Try running the “tutorial” sample application, for example, with this property enabled.

如果您想更改默认 span 标签中的环绕文本(或使用空字符串将其完全删除),您还可以设置 spring.security.securedUIPrefixspring.security.securedUISuffix 属性。

You can also set the spring.security.securedUIPrefix and spring.security.securedUISuffix properties if you want to change surrounding text from the default span tags (or use empty strings to remove it completely).

The authentication Tag

此标签允许访问存储在安全上下文中中的当前 Authentication 对象。它直接在 JSP 中呈现该对象的属性。因此,例如,如果 Authenticationprincipal 属性是 Spring Security 的 UserDetails 对象的一个实例,那么使用 <sec:authentication property="principal.username" /> 将显示当前用户的名称。

This tag allows access to the current Authentication object stored in the security context. It renders a property of the object directly in the JSP. So, for example, if the principal property of the Authentication is an instance of Spring Security’s UserDetails object, then using <sec:authentication property="principal.username" /> renders the name of the current user.

当然,对于这类操作,没有必要使用 JSP 标签,并且有些人更希望在视图中尽可能少地包含逻辑。您可以在 MVC 控制器中访问 Authentication 对象(通过调用 SecurityContextHolder.getContext().getAuthentication()),并将数据直接添加到模型中以供视图呈现。

Of course, it is not necessary to use JSP tags for this kind of thing, and some people prefer to keep as little logic as possible in the view. You can access the Authentication object in your MVC controller (by calling SecurityContextHolder.getContext().getAuthentication()) and add the data directly to your model for rendering by the view.

The accesscontrollist Tag

本标签仅在与 Spring Security 的 ACL 模块配合使用时才有效。它会检查指定域对象所需权限的逗号分隔列表。如果当前用户拥有所有这些权限,则评估标签正文。如果他们没有权限,则跳过标签正文。

This tag is only valid when used with Spring Security’s ACL module. It checks a comma-separated list of required permissions for a specified domain object. If the current user has all of those permissions, the tag body is evaluated. If they do not, it is skipped.

总的来说,此标签应被视为已弃用。改用 The authorize Tag

In general, this tag should be considered deprecated. Instead, use the The authorize Tag.

下面的清单显示了一个示例:

The following listing shows an example:

<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 实例,以便可以采用工厂支持的任何格式。它们不必是整数。它们可以是字符串,如 READWRITE。如果没有找到 PermissionFactory,则使用 DefaultPermissionFactory 实例。应用程序上下文的 AclService 用于加载所提供对象的 Acl 实例。使用 Acl 通过加载所需权限来检查是否全部授予了这些权限。

The permissions are passed to the PermissionFactory defined in the application context, converting them to ACL Permission instances, so they may be any format that is supported by the factory. They do not have to be integers. They could be strings such as READ or WRITE. If no PermissionFactory is found, an instance of DefaultPermissionFactory is used. The AclService from the application context is used to load the Acl instance for the supplied object. The Acl is invoked with the required permissions to check if all of them are granted.

此标签还支持 var 属性,与 authorize 标签的方式相同。

This tag also supports the var attribute, in the same way as the authorize tag.

The csrfInput Tag

如果启用了 CSRF 保护,此标签会使用正确的名称和值插入隐藏的表单字段以进行 CSRF 保护令牌。如果 CSRF 保护未启用,此标签不输出任何内容。

If CSRF protection is enabled, this tag inserts a hidden form field with the correct name and value for the CSRF protection token. If CSRF protection is not enabled, this tag outputs nothing.

通常情况下,Spring Security 会自动插入用于任何 <form:form> 标签的 CSRF 表单字段,但如果您由于某种原因无法使用 <form:form>csrfInput 是一个方便的替换项。

Normally, Spring Security automatically inserts a CSRF form field for any <form:form> tags you use, but if for some reason you cannot use <form:form>, csrfInput is a handy replacement.

您应该将此标签放置在 HTML <form></form> 块内,通常放置其他输入字段的位置。不要将此标签放在 Spring <form:form></form:form> 块内。Spring Security 会自动处理 Spring 表单。以下清单显示了一个示例:

You should place this tag within an HTML <form></form> block, where you would normally place other input fields. Do NOT place this tag within a Spring <form:form></form:form> block. Spring Security handles Spring forms automatically. The following listing shows an example:

	<form method="post" action="/do/something">
		<sec:csrfInput />
		Name:<br />
		<input type="text" name="name" />
		...
	</form>

The csrfMetaTags Tag

如果启用了 CSRF 保护,此标签会插入包含 CSRF 保护令牌表单字段和标头名称,以及 CSRF 保护令牌值的元标签。这些元标签适用于在您应用程序的 JavaScript 中使用 CSRF 保护。

If CSRF protection is enabled, this tag inserts meta tags that contain the CSRF protection token form field and header names and CSRF protection token value. These meta tags are useful for employing CSRF protection within JavaScript in your applications.

您应该将 csrfMetaTags 放置在 HTML <head></head> 块内,通常放置其他元标签的位置。一旦使用此标签,您便可以使用 JavaScript 访问表单字段名称、标头名称和令牌值。该示例使用了 JQuery 来简化任务。以下清单显示了一个示例:

You should place csrfMetaTags within an HTML <head></head> block, where you would normally place other meta tags. Once you use this tag, you can access the form field name, header name, and token value by using JavaScript. JQuery is used in this example to make the task easier. The following listing shows an example:

<!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 不输出任何内容。

If CSRF protection is not enabled, csrfMetaTags outputs nothing.