Posted on 2009-01-10 00:43
啥都寫點 閱讀(970)
評論(0) 編輯 收藏 所屬分類:
J2EE
安全攔截器
- 認證管理器:由AuthenticationManager(接口)定義
- ProviderManager(AuthenticationManager的一個實現)
- AuthByAdapterProvider(使用容器適配器驗證身份)
- AnonymousAuthenticationProvider(以匿名用戶方式驗證用戶)
- CasAuthenticationProvider(根據JA-SIG"中心認證服務"(CAS)驗證身份)
- DaoAuthenticationProvider(從數據庫中獲取用戶信息,包括用戶名和密碼)
- userDetailsService屬性:用來指定將用戶從數據庫中檢索用戶信息的那個Bean(UserDetailsService接口)
- InMemoryDaoImpl:一個從Spring配置文件中獲取用戶信息的實現
- JdbcDaoImpl:簡單而靈巧的認證Dao,從關系數據庫中檢索用戶的信息
- 可裝配編碼器,看一下Spring Security的密碼編碼器
- Md5PasswordEncoder:在密碼上執行“信息摘要”(MD5)編碼
- PlaintextPasswordEncoder:在密碼上不執行任何編碼,照原樣返回它
- ShaPasswordEncoder:在密碼上執行"安全散列算法"(SHA)編碼
- 使用LDAP SHA和salted-SHA(SSHA)編碼技術編碼密碼
- 設置種子源(salt salt):一個種子源為所用的編碼技術提供種子或者稱加密密匙
- SystemWideSaltSource:對所有用戶提供相同的種子
- ReflectionSaltSource:利用用戶的User對象中某個指定屬性的反射來生成種子
- 啟用用戶信息的緩存功能,提供一個UserCache接口的實現
- NullUserCache
- EhCacheB asedUserCache:基于EHcache實現的
- LdapAuthenticationProvider(根據某一輕量級目錄訪問協議服務器驗證身份)
- ref = "authenticator"策略:根據LDAP倉庫處理實際的身份驗證
- 方法1:利用一個LADP用戶的用戶名和密碼綁定到LDAP服務器
- 方法2:在LDAP中檢索一個用戶的數目,然后將提供的密碼和檢索到的LDAP記錄中的密碼屬性相比較
- spring自帶兩個實現
- BindAuthenticator
- property: userDnPatterns:此屬性是用來告訴BindAuthenticator如何在LDAP中找到某個用戶的。它的值是一個模式列表。
- constructor-arg ref="initialDirContextFactory"
- 由DefaultInitialDirContextFactory實現:用來捕捉連接到一臺LDAP服務器所需的全部信息,并生成一個JNDIDirContext對象
- constructor-arg value="ldap://ldap.roadrantz.com:389/dc=roadrantz,dc=com"
- LdapAuthenticator
- (可選)PasswordComparisonAuthenticator:這是作為BindAuthenticator之外的一種可選方式。除類名稱外,聲明與BindAuthenticator完全相同。
-
但是還有屬性可以用來自定義。舉例來說,如果默認的userPassword屬性并不符合你的需求,則可以通過裝配一個新的值到passwordAttributeName屬性來覆蓋它。 <property name="passwordAttributeName" value="userCredentials">(轉配的地方與 BindAuthenticator下的第二個分支的地方一致)
與BindAuthentication不同,passwordComparisonAuthenticator并不利用用戶的DN綁定到LDAP,雖然有些LDAP提供者允許匿名綁定,在這種情況下,雖然 initialDirContextFactory會正常工作,但出于安全考慮,因此我們需要為DefaultInitialDirContextFactory提供一個管理器DN和密碼來綁定。 <property name="mamagerDn" value="cn=manager, dc=roadrantz,dc=com" /> <property name="managerPassword" value="letmein" />( 這兩個屬性與BindAuthenticator的第二分支下的地方一致)
- ref = "populator"策略:負責從LDAP倉庫檢索用戶獲得的權限集
- DefaultLdapAuthoritiesPopulator
-
<constructor-arg ref="initialDirContextFactory">
<constructor-arg value=" ou=groups ">:幫助DefaultLdapAuthoritiesPopulator在LDAP倉庫中查找組。由于LDAP倉庫實際上是分層的,安全組隨處可見。這個構造函數參數指定一個基礎DN,根據它來搜索組。這個基礎DN與初始上下文相關。
<property name="groupRoleAttribute" value="ou"> :指定將包含角色信息的特征名稱。它的默認值為cn,這里設置成了ou。
<property name="convertToUpperCase" value="fasle"> 關閉將組名稱轉換為大寫字母的操作(就是前綴后面的字符)
<property name="rolePrefix" value="GROUP_"> 改變前綴
更改查找成員方式。如果你的LDAP倉庫使用一個associate屬性(不是member屬性)跟蹤成員資格。則需要添加<property name="groupSearchFilter" value="(associate={0})"> {0}表示用戶的DN
- JaasAuthenticationProvider(從JAAS登陸配置中獲取用戶信息)
- RemmberMeAuthenticationProvider(驗證某一之前驗證過并且被記住的用戶的身份)
- RemoteAuthenticationProvider(根據遠程服務驗證用戶身份)
- TestingAuthenticationProvider(用于單元測試。)
- X509AuthenticationProvider(使用X.509證書驗證用戶身份)
- RunAsImplAuthenticationProvider(針對身份已經被運行身份管理器替換的用戶進行認證)
- 訪問決策管理器
- AccessDecisionManager
- 實現1:AffirmativeBased:只要有一個投票者投票贊成授予訪問權,就允許訪問
- <property name="decisionVoters"><list><ref bean="roleVoter" /></list></property>
- <property name="allowIfAllAbstain" value="true" /> : 如果所有的投票者都放棄投票,則如同它們都投贊成票一樣,訪問將被授權。
- 實現2:ConsensusBased:大多數的
- 實現3:UnanimousBased:所有的
- 運行身份管理器
- 調用后臺管理器
保護Web應用程序:Spring Security對Web安全性的支持大量地依賴于Servlet過濾器。在對一個Spring保護的Web應用程序提出請求時,他將經過至少下列四個過濾器
- 集成過濾器:負責在一個請求的開始時檢索先前存儲的認證信息(通常存儲在HTTP會話中。)
- 認證處理過濾器:將決定該請求是否是一個認證請求,如果是(通常為用戶名/密碼)就會被從這個請求中提取出來,然后轉交給認證管理器來確定用戶的身份。
- 例外轉換過濾器:如發現異常,則當前請求會被發送到一個身份驗證入口點(譬如登陸頁面)
- 安全攔截器
-
每當用戶請求Web應用程序中的一個頁面時,那個頁面可能是需要保護的,也可能是不需要保護的,在Spring Security中,一個過濾器安全攔截器負責攔截請求,判斷某一請求是否安全,并且給予身份驗證和訪問決策管理器一個機會來驗證相應用戶的身份和權限。在Spring配置文件中,過濾器安全攔截器是按照以下方式聲明的: <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager" /> <property name="accessDecisionManager" ref="accessDecisionManager" /> <property name="objectDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /editProfile.htm=ROLE_MOTORIST </value> </property> </bean>FilterSecurityInterceptor充當Web應用程序的安全攔截器。當有一個請求進來想要訪問某以資源時,FilterSecurityInceptor將執行幾項檢查: 1、當前用戶已通過身份驗證了嗎? 2、所請求的資源受保護了嗎? 3、當前用戶已經被授予足夠訪問所請求資源的權限了嗎?
ChannelProcessingFilter(確保安全性請求在HTTPS上傳送):是一種Spring Security過濾器,它攔截某一請求,查看它是否需要被保護,如果是,就通過將該請求重新定向至原始請求URL的HTTPS格式來讓“s”起作用。(見PPT) 配置如下: <bean id="channelProcessingFilter" class="org.acegisecurity.securechannel.ChannelProcessingFilter"> <property name="channelDecisionManager" ref="channelDecisionManager" /> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /login.htm=REQUIRES_SECURE_CHANNEL /j_acegi_security_check*=REQUIRES_SECURE_CHANNEL /**=REQUIRES_INSECURE_CHANNEL </value> </property> </bean>這里的filterInvocationDefinitionSource屬性被配置來告訴ChannelProcessingFilter哪些頁面應該使用HTTPS保護,以及哪些不應該進行保護。ChannelDecisionManagerImple:權衡決定某一請求是否應該被重新定向。<bean id="channelDecisionManager" class="org.acegisecurity.securechannel.ChannelDecisionManagerImpl"> <property name="channelProcessors"> <list> <bean class="org.acegisecurity.securechannel.SecureChannelProcessor" /> <bean class="org.acegisecurity.securechannel.InsecureChannelProcessor" /> </list> </property> </bean>
代理Spring Security過濾器(FilterToBeanProxy):本身做的工作并不多,而是將自己的工作委托給Spring應用程序上下文中的來完成。 下面我來演示如何配置FilterToBeanProxy
-
==========這里委托給了一個FooFilter bean=========web.xml 中的配置:<filter> <filter-name>Foo</filter-name> <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>com.roadrantz.FooFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>Foo</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> spring上下文中的配置: <bean id="fooFilter" class="com.roadrantz.FooFilter"> <property name="bar" ref="bar" /></bean>
==========這里委托給了FilterChainProxy (Spring Security要求至少配置四個而且可能一打或者更多的過濾器)========= web.xml 中的配置:<filter> <filter-name>Acegi Filter Chain Proxy</filter-name> <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class> <init-param> <param-name>targetClass</param-name> <param-value>org.acegisecurity.util.FilterChainProxy</param-value> </init-param> </filter> <filter-mapping> <filter-name>Acegi Filter Chain Proxy</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> spring上下文中的配置: <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=filter1,filter2,filter3 </value> </property> </bean>
視圖層安全:Spring Security帶有一個小型(但是功能強大)的JSP標簽庫。這個標簽庫只提供了三個標簽:1、<authz:acl> 根據當前用戶是否已被授予針對某一域對象的一組特定權限之一,有條件地渲染標簽體。2、<authz:authentication> 提供有關當前用戶的信息。3、<authz:authorize>根據當前用戶是否已被授予某些權限,有條件地渲染標簽體。通過<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %> 引入標簽庫。
-
<authz:authorize>:有3個屬性 1、<authz:authorize ifAllGranted="ROLE_MOTORIST,ROLE_VIP"> welcome motorist<br/> <a href="j_acegi_logout">logoff</a> </authz:authorize>2、同1,將ifAllGranted 替換成 ifAnyGranted3、同1,將ifAllGranted 替換成 ifNotGranted
<authz:authentication>:顯示用戶身份驗證信息 <authz:authentication>標簽把 Authentication.getPrincipal()返回的那個對象的屬性呈遞給JSP輸出。Authentication.getPrincipal()通常返回Spring Security 的org.acegisecurity.userdetails.UserDetails接口的一個實現,包括一個getUsername()方法。因此,要想顯示UserDetails對象的username屬性,添加如下: <authz:authorize ifAnyGranted="ROLE_MOTORIST,ROLE_VIP"> welcome <arthz:authentication operation="username" /> </authz:authorize>
保護方法調用
-
創建一個安全切面:也許設置一個AOP代理的最簡單的方式是使用Spring的BeanNameAutoProxyCreator,并且簡單地列舉出你想要保護的Bean.假設你希望保護courseService和billingService Bean:<bean id="autoProxyCheator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <value>securityInterceptor</value> </list> </property> <property name="beanNames"> <list> <value>courseService</value> <value>billingService</value> </list> </property></bean>在這個示例中我們要求自動代理創建器通過一個名為 securityInterceptor的攔截器代理它的Bean,這個securityInterceptor Bean按照以下方式配置: <bean id="securityInterceptor" class="org.acegisecurity.intercept.method.MethodSecurityInterceptor"> <property name="authenticationManager" ref="authenticationManager" /> <property name="accessDecisionManager" ref="accessDecisionManager" /> <property name="objectDefinitionSource"> <value> com.springinactionl.springtraining.service.CourseService.createCourse=ROLE_ADMIN com.springinactionl.springtraining.service.CourseService.enroll*=ROLE_ADMIN,ROLE_REGISSTRAR </value> </property> </bean>
使用元數據保護方法:首先聲明一個元數據實現以告訴Spring如何裝在元數據 <bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes" />接下來,聲明一個對象定義源 <bean id="objectDefinitionSource" class="org.acegisecurity.intercept.method.MethodDefinitionAttributes"> <property name="attributes"><ref bean="attributes" /> </property> </bean>配置好后,裝配到MethodSecurityIntereceptor的objectDefinitionSource屬性中 <bean id="securityInterceptor" class="org.acegisecurity.intercept.method.MethodSecurityInterceptor"> ......... <property name="objectDefinitionSource"> <value> <ref bean="objectDefinitionSource"> </value> </property> </bean>現在可以在代碼上加上安全屬性標記,舉例/** * @@org.acegisecurity.SecurityConfig("ROLE_ADMIN") * @@org.acegisecurity.SecurityConfig("ROLE_REGISTRAR") */public void enrollStudentInCourse(Course course,Student student) throws CourseException
--
學海無涯