对于最新的稳定版本,请使用 Spring Security 6.5.3! |
JSP 标签库
声明 Taglib
要使用任何标记,您必须在 JSP 中声明安全 taglib:
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
授权标签
此标签用于确定是否应评估其内容。在 Spring Security 3.0 中,可以通过两种方式使用它。
Spring Security 2.0 的旧版选项也受支持,但不鼓励使用。 |
第一种方法使用 Web 安全表达式,该表达式在access
属性。表达式求值被委托给SecurityExpressionHandler<FilterInvocation>
在应用程序上下文中定义(您应该在<http>
命名空间配置以确保此服务可用)。因此,例如,您可能有:
<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 请求,并调用安全拦截器来查看请求是成功还是失败。这允许您委托给您通过使用intercept-url
声明中的<http>
命名空间配置,并省去了在JSP中复制信息(例如所需角色)的必要性。您还可以将此方法与method
属性(提供 HTTP 方法,例如POST
) 以进行更具体的匹配。
您可以通过将var
属性添加到变量名称,避免了在页面中其他点复制和重新评估条件的需要。
禁用标记授权以进行测试
在页面中为未经授权的用户隐藏链接并不能阻止他们访问 URL。例如,他们可以直接将其输入到浏览器中。作为测试过程的一部分,您可能希望显示隐藏区域,以检查链接在后端是否确实受到保护。如果您将spring.security.disableUISecurity
系统属性设置为true
这authorize
标记仍然运行,但不会隐藏其内容。默认情况下,它还会用<span class="securityHiddenUI">…</span>
标签。 这使您可以显示具有特定 CSS 样式的“隐藏”内容,例如不同的背景颜色。例如,尝试运行“教程”示例应用程序,并启用此属性。
您还可以将spring.security.securedUIPrefix
和spring.security.securedUISuffix
properties 如果要从默认值更改周围文本span
标签(或使用空字符串将其完全删除)。
身份验证标记
此标签允许访问当前Authentication
存储在安全上下文中的对象。它直接在 JSP 中呈现对象的属性。因此,例如,如果principal
属性的Authentication
是 Spring Security 的UserDetails
对象,然后使用<sec:authentication property="principal.username" />
呈现当前用户的名称。
当然,这种事情没有必要使用 JSP 标签,有些人更喜欢在视图中保留尽可能少的逻辑。您可以访问Authentication
对象(通过调用SecurityContextHolder.getContext().getAuthentication()
),并将数据直接添加到模型中,以便由视图呈现。
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>
权限将传递给PermissionFactory
在应用程序上下文中定义,将它们转换为 ACLPermission
实例,因此它们可以是工厂支持的任何格式。它们不必是整数。它们可以是字符串,例如READ
或WRITE
.
如果没有PermissionFactory
找到,则DefaultPermissionFactory
被使用。
这AclService
来自应用程序上下文用于加载Acl
实例。
这Acl
使用所需的权限调用,以检查是否全部被授予。
此标记还支持var
属性,与authorize
标记。
csrfInput 标记
如果启用了 CSRF 保护,则此标记将插入一个隐藏的表单字段,其中包含 CSRF 保护Tokens的正确名称和值。 如果未启用 CSRF 保护,则此标记不输出任何内容。
通常,Spring Security 会自动为任何<form:form>
标签,但如果由于某种原因您无法使用<form:form>
,csrfInput
是一个方便的替代品。
您应该将此标签放在 HTML 中<form></form>
块,您通常会在其中放置其他输入字段。
请勿将此标签放置在弹簧中<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 保护Tokens表单字段和标头名称以及 CSRF 保护Tokens值的元标记。 这些元标记对于在应用程序中的 JavaScript 中采用 CSRF 保护非常有用。
你应该把csrfMetaTags
在 HTML 中<head></head>
块,您通常会在其中放置其他元标记。
使用此标记后,您可以使用 JavaScript 访问表单字段名称、标头名称和Tokens值。
在此示例中使用 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
不输出任何内容。