JSP 標籤庫
宣告標籤庫
若要使用任何標籤,您必須在 JSP 中宣告 security 標籤庫
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
authorize 標籤
此標籤用於判斷是否應評估其內容。在 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 請求,並調用安全攔截器以查看請求是否會成功或失敗。這可讓您委派給您使用 <http>
命名空間設定中的 intercept-url
宣告定義的存取控制設定,並節省在 JSP 中重複資訊 (例如所需的角色)。您也可以將此方法與 method
屬性 (提供 HTTP 方法,例如 POST
) 結合使用,以獲得更精確的匹配。
您可以透過將 var
屬性設定為變數名稱,將評估標籤的布林值結果 (無論它是否授予或拒絕存取) 儲存在頁面內容範圍變數中,從而避免在頁面中的其他點重複和重新評估條件的需求。
停用標籤授權以進行測試
在頁面中隱藏未授權使用者的連結並不能阻止他們存取 URL。例如,他們可以直接在瀏覽器中輸入 URL。作為測試過程的一部分,您可能希望顯示隱藏區域,以檢查連結是否真正在後端受到保護。如果您將 spring.security.disableUISecurity
系統屬性設定為 true
,則 authorize
標籤仍然執行,但不會隱藏其內容。預設情況下,它也會用 <span class="securityHiddenUI">…</span>
標籤包圍內容。這可讓您使用特定的 CSS 樣式 (例如不同的背景顏色) 顯示「隱藏」內容。例如,嘗試在啟用此屬性的情況下執行「教學課程」範例應用程式。
如果您想從預設的 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 保護,此標籤會插入 meta 標籤,其中包含 CSRF 保護令牌表單欄位和標頭名稱以及 CSRF 保護令牌值。這些 meta 標籤對於在應用程式的 JavaScript 中採用 CSRF 保護非常有用。
您應該將 csrfMetaTags
放置在 HTML <head></head>
區塊中,您通常會在其中放置其他 meta 標籤。一旦您使用此標籤,您就可以使用 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
不會輸出任何內容。