# JSP标记库

# 宣布Taglib

要使用任何标记,你必须在JSP中声明安全性taglib:

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

# 授权标签

此标记用于确定是否应该对其内容进行评估。在 Spring Security3.0中,可以用两种方式[1]。第一种方法使用Web安全表达式,在标记的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方法,以进行更具体的匹配。

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

# 禁用标记授权以进行测试

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

如果你想从默认的span标记中更改周围的文本(或使用空字符串完全删除它),还可以设置属性spring.security.securedUIPrefixspring.security.securedUISuffix

# 身份验证标记

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

当然,在这种情况下没有必要使用JSP标记,有些人更喜欢在视图中尽可能少地保留逻辑。你可以访问MVC控制器中的Authentication对象(通过调用SecurityContextHolder.getContext().getAuthentication()),并将数据直接添加到模型中,以便由视图进行呈现。

# AccessControlist标签

此标记仅在与 Spring Security的ACL模块一起使用时有效。它检查指定域对象所需权限的逗号分隔列表。如果当前用户拥有所有这些权限,那么将对标记主体进行评估。如果他们不这么做,就会被跳过。一个例子可能是

一般来说,这个标记应该被认为是废弃的。
而不是使用授权标签
<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,将它们转换为ACLPermission实例,因此它们可以是工厂支持的任何格式-它们不必是整数,它们可以是READWRITE之类的字符串。如果没有找到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 安全自动处理 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将不输出任何内容。


1。还支持 Spring Security2.0中的遗留选项,但不推荐。

Spring’s CORS SupportJava Configuration