JSP 标签库
声明标签库
要使用任意标签,您必须在 JSP 中声明 security 标签库:
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
授权标签
此标签用于确定其内容是否应该被评估。 在Spring Security 3.0中,它可以以两种方式使用。
|
来自Spring Security 2.0的遗留选项也受到支持,但不推荐使用。 |
使用第一种方法,可以使用一个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 请求,并调用安全拦截器以查看该请求是否会成功或失败。
这可以让您将访问控制设置委托给通过在 intercept-url 命名空间配置中使用 <http> 声明定义的内容,从而节省在 JSP 中重复信息(例如所需的角色)的步骤。
如果您有基于方法的授权规则,则应将此方法与method属性(提供HTTP方法,例如POST)结合起来以激活预期的方法基于规则。
例如,如果您的规则是.requestMatchers(POST, "/admin").hasRole("ADMIN"),则应使用<sec:authorize method="POST" url="/admin">来匹配。
可以将标签评估结果(是否授予或拒绝访问)的布尔值存储在页面范围的变量中,通过设置var属性为变量名,从而避免在页面其他点重复评估条件。
禁用标签授权以进行测试
隐藏页面中的链接不会阻止未授权用户访问该URL。他们可以直接在浏览器中输入URL,例如。
作为测试过程的一部分,您可能希望揭示这些隐藏区域,以检查链接是否真正被后端安全措施保护。
如果您将系统属性spring.security.disableUISecurity设置为true,则authorize标签仍然运行但不会隐藏其内容。
默认情况下,它还会在内容周围使用<span class="securityHiddenUI">…</span>标签。
这使您可以以特定的CSS样式显示“隐藏”内容,例如不同的背景色。
尝试启用此属性运行“教程”示例应用程序,例如。
您也可以设置spring.security.securedUIPrefix和spring.security.securedUISuffix属性,以便更改周围文本从默认的span标签(或使用空字符串完全移除这些标签)。
认证标签
此标签允许访问安全上下文中存储的当前Authentication对象。
它直接在JSP中渲染该对象的一个属性。
因此,例如,如果principal的Authentication属性是一个Spring Security的UserDetails对象实例,则使用<sec:authentication property="principal.username" />将渲染当前用户的用户名。
当然,没有必要为此使用JSP标签,并且有些人更喜欢尽量减少视图中的逻辑。
您可以通过调用Authentication在MVC控制器中访问SecurityContextHolder.getContext().getAuthentication()对象,并直接将其数据添加到模型中供视图渲染。
访问控制列表标签
此标签仅在与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,并将其转换为 ACL Permission 实例,因此它们可以是工厂支持的任何格式。它们不必是整数,也可以是字符串,例如 READ 或 WRITE。
如果未找到 PermissionFactory,则使用 DefaultPermissionFactory 的实例。
来自应用上下文的 AclService 用于加载所提供对象的 Acl 实例。
Acl 将被调用以检查是否已授予所有必需的权限。
此标签还支持var属性,与authorize标签相同。
csrfInput 标签
如果启用了CSRF保护,此标签会插入一个带有正确名称和值的隐藏表单字段,用于CSRF保护Tokens。 如果没有启用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保护Tokens表单字段和头名称以及CSRF保护Tokens值的meta标签。 这些meta标签对于在您的应用程序中使用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 不输出任何内容。