跳到主要内容

JSP 标签库

QWen Max 中英对照 JSP Taglib JSP Tag Libraries

声明 Taglib

要使用任何标签,必须在您的JSP中声明安全标签库:

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

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

当与 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>
xml

一个常见的需求是仅显示某个特定的链接,前提是用户实际上被允许点击该链接。我们如何提前确定某件事是否被允许?此标签也可以以另一种模式运行,允许你将特定的 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>
xml

要使用此标签,您还必须在应用程序上下文中有一个 WebInvocationPrivilegeEvaluator 的实例。如果您使用的是命名空间,则会自动注册一个实例。这是一个 DefaultWebInvocationPrivilegeEvaluator 的实例,它为提供的 URL 创建一个虚拟的 web 请求,并调用安全拦截器以查看请求是否会成功或失败。这使您可以委托给通过在 <http> 命名空间配置中使用 intercept-url 声明所定义的访问控制设置,并且不必在 JSP 中重复这些信息(例如所需的角色)。您还可以将此方法与 method 属性(提供 HTTP 方法,如 POST)结合使用,以实现更具体的匹配。

您可以将评估标签的结果(无论是允许还是拒绝访问)存储在页面上下文范围变量中,方法是将 var 属性设置为变量名称,从而避免在页面的其他位置重复和重新评估该条件。

禁用标签授权进行测试

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

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

认证标签

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

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

The accesscontrollist 标签

此标签仅在与 Spring Security 的 ACL 模块一起使用时有效。它会检查指定域对象的逗号分隔的所需权限列表。如果当前用户具有所有这些权限,则计算标签体。如果他们没有这些权限,则跳过标签体。

警告

通常,此标签应被视为已弃用。请改用 The 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>
xml

权限被传递给在应用程序上下文中定义的 PermissionFactory,将其转换为 ACL Permission 实例,因此它们可以是工厂支持的任何格式。它们不必是整数。它们可以是诸如 READWRITE 之类的字符串。如果没有找到 PermissionFactory,则使用 DefaultPermissionFactory 的实例。应用程序上下文中的 AclService 用于加载所提供对象的 Acl 实例。通过所需的权限调用 Acl,以检查是否全部授予了这些权限。

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

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

The csrfMetaTags 标签

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

你应该将 csrfMetaTags 放置在 HTML 的 <head></head> 块中,通常你会在这里放置其他 meta 标签。一旦使用了这个标签,你就可以通过 JavaScript 访问表单字段名称、头部名称和令牌值。在这个示例中使用了 JQuery 来简化任务。以下是一个示例:

// 示例代码
javascript
<!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>
xml

如果未启用CSRF保护,csrfMetaTags将不输出任何内容。