領先一步
VMware 提供訓練和認證,以加速您的進展。
了解更多假設您正處於安全連線中(您已登入並授權存取特定資源),但您的安全基礎架構團隊已更新您的權限。也許您被賦予更多權限,或者您的權限被完全撤銷... 問題是您的安全連線已在連線註冊表中註冊,並且在您登出/登入之前,代表您在此安全連線中的 Principal 將不會被重新建立。如果情況更加戲劇化(畢竟我們在這裡談論的是安全性)... 您是一位心懷不滿的員工,而您的直屬主管發現了您的「不當行為」,但您的公司需要 5 次會議和 10 份批准表格才能完成某件事,而在這段時間內,您可以自由地造成更大的危害嗎?
顯然,在使用者處於連線狀態時,可能有很多業務情境會促使調整使用者的權限。同樣,在 Spring Security 中,顯然有多種方法可以實現這一點。一種方法是使用連線註冊表(實際上是為並行連線控制而設計的)將人員踢出系統。建立一個 GUI 或啟用 JMX,可以從已註冊連線的列表中「過期」使用者。他們提出的下一個請求將被拒絕,並且連線將失效,從而強制執行身份驗證過程。然而,為了讓它更有趣,並且也為了展示另一種實現類似目標的方法,讓我們稍微改變情境,假設我們不想完全使使用者的安全連線失效,而只是想暫時中止它。
現在,「中止」這個詞在安全性的上下文中可能意味著很多不同的事情。它可能意味著暫時中止,或者可能意味著完全撤銷權限。我將由您來定義這個詞在任何上下文中的含義... 我寧願向您展示如何使用 Spring Security 元件(例如 AccessDecisionVoter 和 AccessDesisionManager)即時調整安全連線。同樣在以下範例中,我們將透過暫時中止使用者的權限而不使其連線失效來調整當前的安全連線。
為了實現這一點,我們需要遵循以下步驟。
1. 在 Spring Security 配置中定義 AccessDecisionManager 1.1 定義基本投票器,例如 RoleVoter 和 AuthenticatedVoter 2. 定義和實作 AccessDecisionVoter。此投票器必須維護一份權限被撤銷的使用者列表,並且每次使用者執行安全操作時都必須投票 ACCESS_DENIED。 3. 將此投票器新增到已在 AccessDecisionManager 中註冊的投票器堆疊中。
此外,為了能够在應用程式執行期間與此投票器互動,我們還可以使用 Spring JMX 將此投票器動態匯出為 JMX bean,從而啟用 JMX。
大致就是這樣。
因此,首先我們需要定義 AccessDecisionManager (ADM)。由於我們正在使用 Spring Security 名稱空間(盡可能),因此諸如 "security:http" 之類的配置元素,Spring Security 將為我們註冊預設的 AccessDecisionManager,它恰好是 AffirmativeBased ADM。這對我們不利,因為我們試圖在這裡更加保守。因此,我們要做的是定義 UnanimousBased ADM,並使用指向 UninimousBased ADM 的 access-decision-manager-ref 屬性覆蓋 "security:http" 元素的預設 ADM(請參閱下文)
<!-- 定義自訂投票器 --> <bean id="suspendVoter" class="org.springframework.security.sample.SuspendRealTimeVoter"/>
<!-- 將 AccessDesisionManager 定義為 UnanimousBased --> <bean id="accessDecisionManager" class="org.springframework.security.vote.UnanimousBased"> <property name="decisionVoters"> <list> <ref bean="suspendVoter" /> <bean class="org.springframework.security.vote.RoleVoter" /> <bean class="org.springframework.security.vote.AuthenticatedVoter" /> </list> </property> </bean>
我們還將把我們的自訂投票器放在投票器堆疊順序的第一位,因為我們知道在 Unanimous based 決策過程中,第一個 NO 意味著不應執行進一步的評估。意識到其他投票決策可能很耗時或效能密集,因此在投票器堆疊中首先註冊自訂投票器將確保僅在權限未被中止時才執行此類投票操作。
<!-- 定義 http 安全性配置 --> <security:http access-decision-manager-ref="accessDecisionManager" . . . . .> . . . . </security:http>
剩下要做的唯一一件事是 JMX 啟用 "suspendVoter"。這可以使用 Spring JMX 輕鬆完成。 <!-- JMX 啟用自訂投票器 --> <bean class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <map> <entry key="org.springframework.security:name=SuspendRealTimeVoter" value-ref="suspendVoter" /> </map> </property> </bean>
現在 "suspendVoter" 將以名稱 org.springframework.security:name=SuspendRealTimeVoter 匯出到 JMX 伺服器中
從程式碼的角度來看,我們需要實作的唯一自訂組件是 SuspendRealTimeVoter 類別。在其中,我們將維護一組權限被暫時撤銷的使用者。在 vote(..) 方法中,我們的邏輯非常簡單。如果使用者在列表中,則投票 ACCESS_DENIED,否則投票 ACCESS_GRANTED。
public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) { String userName = authentication.getName(); return revokedUsers.contains(userName) ? ACCESS_DENIED : ACCESS_GRANTED; }
您還將看到 suspend(String userName) 和 grant(String userName) 方法,我們將透過這些方法測試此功能。
注意:為了透過 JMX 與我們的投票器互動,我們將使用 JDK (1.5+) 提供的 JConsole 工具,因此需要 JMX 啟用我們的應用程式伺服器。對於此範例,我正在使用 Tomcat,因此如果您正在使用 Tomcat,請將以下 VM 引數新增到其啟動腳本中
-Dcom.sun.management.jmxremote
啟動伺服器,部署應用程式並存取其 URL:https://127.0.0.1:8080/spring-security-sample-suspendUser
成功登入後,按幾次重新整理,以查看您的連線是否正常運作。然後導航到 JDK 的 bin 目錄,開啟命令提示字元並輸入 jconsole(請參閱下文)
當 JConsole 開啟時,按一下 MBeans 標籤。導航樹狀結構並存取 SuspendRealTimeVoter。
您將看到 suspend(..) 和 grant(..) 方法在Operations 標籤下可用。中止您登入的使用者的權限,然後重新整理您所在的 HTML 頁面。您將看到 denied.html 頁面。透過為該使用者呼叫 grant(..) 方法來取消中止使用者,您就恢復正常了。現在,如果確實需要 5 次會議和 10 份批准表格,您可以暫時撤銷使用者的權限,讓您的主管有足夠的時間做出此類決策。
結論
這只是一個範例,示範了如何使用投票器暫時中止安全連線。但我希望您可以清楚地看到如何使用相同的方法來實現其他目標。此類目標可能是自動重新驗證使用者身份,或只是更新他/她的 GrantedAuorities 列表等等。
可以從此處下載本文的範例原始程式碼:spring-security-sample-suspenduser