# 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.securedUIPrefix
和spring.security.securedUISuffix
。
# 身份验证标记
此标记允许访问存储在安全上下文中的当前Authentication
对象。它在JSP中直接呈现对象的属性。因此,例如,如果Authentication
的principal
属性是 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
实例,因此它们可以是工厂支持的任何格式-它们不必是整数,它们可以是READ
或WRITE
之类的字符串。如果没有找到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中的遗留选项,但不推荐。