JSP 標籤庫
宣告標籤庫
要使用任何標籤,您必須在 JSP 中宣告安全標籤庫
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
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>
當與 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 方法,例如 POST)結合使用,以實現更具體的匹配。
您可以透過將 var 屬性設定為變數名,將評估標籤(是否授予或拒絕訪問)的布林結果儲存在頁面上下文範圍變數中,從而避免在頁面其他地方重複和重新評估條件。
停用標籤授權以進行測試
對未經授權的使用者隱藏頁面中的連結並不能阻止他們訪問該 URL。例如,他們可以直接在瀏覽器中輸入它。作為測試過程的一部分,您可能希望顯示隱藏區域,以檢查連結是否確實在後端受到保護。如果您將 spring.security.disableUISecurity 系統屬性設定為 true,則 authorize 標籤仍會執行,但不會隱藏其內容。預設情況下,它還會將內容用 <span class="securityHiddenUI">…</span> 標籤包圍起來。這允許您以特定的 CSS 樣式(例如不同的背景顏色)顯示“隱藏”內容。例如,啟用此屬性後,嘗試執行“tutorial”示例應用程式。
如果您想更改環繞文字(預設的 span 標籤),也可以設定 spring.security.securedUIPrefix 和 spring.security.securedUISuffix 屬性(或者使用空字串完全刪除它)。
authentication 標籤
此標籤允許訪問儲存在安全上下文中的當前 Authentication 物件。它直接在 JSP 中呈現物件的屬性。例如,如果 Authentication 的 principal 屬性是 Spring Security 的 UserDetails 物件的例項,那麼使用 <sec:authentication property="principal.username" /> 將呈現當前使用者的名稱。
當然,對於這類事情不一定非要使用 JSP 標籤,有些人更喜歡在檢視中保留儘可能少的邏輯。您可以在 MVC 控制器中訪問 Authentication 物件(透過呼叫 SecurityContextHolder.getContext().getAuthentication()),並將資料直接新增到模型中,供檢視呈現。
accesscontrollist 標籤
此標籤僅在與 Spring Security 的 ACL 模組一起使用時有效。它檢查指定域物件所需許可權的逗號分隔列表。如果當前使用者擁有所有這些許可權,則評估標籤體。如果他們沒有,則跳過。
|
一般來說,此標籤應被視為已棄用。請改用 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,將其轉換為 ACL Permission 例項,因此它們可以是工廠支援的任何格式。它們不必是整數。它們可以是字串,例如 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 Security 會自動處理 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 不會輸出任何內容。