使用Spring Security3的四種方法概述
那么在Spring Security3的使用中,有4種方法:
一種是全部利用配置文件,將用戶、權限、資源(url)硬編碼在xml文件中,已經實現過,並經過驗證;
二種是用戶和權限用數據庫存儲,而資源(url)和權限的對應采用硬編碼配置,目前這種方式已經實現,並經過驗證。
三種是細分角色和權限,並將用戶、角色、權限和資源均采用數據庫存儲,並且自定義過濾器,代替原有的FilterSecurityInterceptor過濾器,
並分別實現AccessDecisionManager、InvocationSecurityMetadataSourceService和UserDetailsService,並在配置文件中進行相應配置。
目前這種方式已經實現,並經過驗證。
四是修改spring security的源代碼,主要是修改InvocationSecurityMetadataSourceService和UserDetailsService兩個類。
前者是將配置文件或數據庫中存儲的資源(url)提取出來加工成為url和權限列表的Map供Security使用,后者提取用戶名和權限組成一個完整的 (UserDetails)User對象,該對象可以提供用戶的詳細信息供AuthentationManager進行認證與授權使用。
該方法理論上可行,但是比較暴力,也沒有時間實現,未驗證,以后再研究。
說明一下,我目前調通的環境為: java1.6 + struts2.1.6 + spring3.0.1 + hibernate3.3.1 + spring security3.0.2 + oracle9i + weblogic10.3,
順便提一下,目前(2011-4-2)serutity的最新版本為3.1,比較穩定的版本為3.0.5和2.0.6。
當然在進行spring security3的下面4種方法介紹之前,先假定SSH2的環境已經配置完畢,進入正常開發的過程,並且已經導入
spring security3.0.2的5個jar包,分別為:
spring-security-acl-3.0.2.RELEASE.jar
spring-security-config-3.0.2.RELEASE.jar
spring-security-core-3.0.2.RELEASE.jar
spring-security-taglibs-3.0.2.RELEASE.jar
spring-security-web-3.0.2.RELEASE.jar
當然還有其他相關的jar包,在此不再贅述。
第一種方法
第一種方法比較簡單,可參考Spring Security自帶的例子spring-security-samples-tutorial-3.0.2.RELEASE。
這里給出下載網址:http://www.springsource.com/download/community?sid=1087087,不過在下載之前必須填寫相應的用戶信息,才允許下載。各種版本號的均可以下載。
在spring-security-samples-tutorial-3.0.2.RELEASE的例子里,硬編碼的配置請參見applicationContext-security.xml文件中的內容。
里面配置了用戶名、經過MD5加密后的密碼密文、相關的權限,以及與權相對應的訪問資源(URL)。還有對於Session超時時的處理。
特別是因為版本號為3.0.2,因此還增加了對表達式的配置演示,具體內容請參見該例子。
當然你最好運行起該例子來,感受一下,你可以直接將下載下來的解壓縮后的文件夾中找到spring-security-samples- tutorial-3.0.2.RELEASE.war文件,然后拷貝到Tomcat的安裝目錄下的\webapps文件夾下,然后運行Tomcat的服 務器,服務器在啟動過程中,會自動解開該war文件,在IE內輸入http://localhost:8080/webapps/spring-security-samples-tutorial-3.0.2.RELEASE 就可以運行該系統了。在此不再贅述。
第二種方法
第二種方法的代碼如下:
使用到的兩個表,用戶表和權限表的SQL語句。將用戶和權限以數據庫進行存儲。
- create table USERS(
- USERNAME VARCHAR2(50) not null,
- PASSWORD VARCHAR2(50) not null,
- ENABLED NUMBER(1) not null,
- USERNAMECN VARCHAR2(50),
- primary key( username )
- )
- create table AUTHORITIES(
- USERNAME VARCHAR2(50) not null,
- AUTHORITY VARCHAR2(50) not null
- )
-- 外鍵使用戶和權限相聯。
- Create/Recreate primary, unique and foreign key constraints
- alter table AUTHORITIES
- add constraint FK_AUTHORITIES_USERS foreign key (USERNAME)
- references USERS (USERNAME);
可插入幾條數據做為試驗,首先插入用戶:
- insert into users (USERNAME, PASSWORD, ENABLED, USERNAMECN, ROWID)
- values ('lxb', 'c7d3f4c857bc8c145d6e5d40c1bf23d9', 1, '登錄用戶', 'AAAHmhAALAAAAAOAAA');
- insert into users (USERNAME, PASSWORD, ENABLED, USERNAMECN, ROWID)
- values ('admin', 'ceb4f32325eda6142bd65215f4c0f371', 1, '系統管理員', 'AAAHmhAALAAAAAPAAA');
- insert into users (USERNAME, PASSWORD, ENABLED, USERNAMECN, ROWID)
- values ('user', '47a733d60998c719cf3526ae7d106d13', 1, '普通用戶', 'AAAHmhAALAAAAAPAAB');
再插入角色:
- insert into authorities (USERNAME, AUTHORITY, ROWID)
- values ('admin', 'ROLE_PLATFORMADMIN', 'AAAHmjAALAAAAAgAAA');
- insert into authorities (USERNAME, AUTHORITY, ROWID)
- values ('admin', 'ROLE_SYSADMIN', 'AAAHmjAALAAAAAgAAB');
- insert into authorities (USERNAME, AUTHORITY, ROWID)
- values ('lxb', 'ROLE_LOGIN', 'AAAHmjAALAAAAAeAAA');
- insert into authorities (USERNAME, AUTHORITY, ROWID)
- values ('lxb', 'ROLE_LOGINTOWELCOME', 'AAAHmjAALAAAAAeAAB');
- insert into authorities (USERNAME, AUTHORITY, ROWID)
- values ('user', 'ROLE_USER', 'AAAHmjAALAAAAAgAAC');
第二種方法之密碼加密
可能要有人要問,用戶表里面的密碼是如何取得的呢?這個密碼是通過MD5進行加密過的,並且以用戶名做為了鹽值,最后就成為32位數字這個 樣子,這個你可以參見下面applicationContext-Security.xml中的password-encoder和salt- source的配置就會明白。
那么在spring security3中是如何加密的呢?當我們設置了pawwrod-encoder和salt-source之后,Spring Security3會根據配置,采用相匹配的加密算法(比如設置了MD5加密算法)再加上salt-source進行加密,形成32位數字的密文。
比如用戶名為yew,密碼為yew1234,鹽值為用戶名yew。那么最后加密的明文為“yew1234{yew}”,密文就為“8fe2657d1599dba8e78a7a0bda8651bb”。
我們在試驗過程中,通常喜歡先將幾個常用的用戶及密碼插入數據庫進行試驗,這種情況下如何得到該用戶的密碼密文呢?
不妨試試我這個辦法,假設,用戶名為user,密碼明文為user369,而且在配置文件里面設置了以MD5作為加密算法,並以用戶名做為鹽值。
那么你可以首先將各個信息組合成待加密的密碼明文, 應是 密碼明文 + { + 鹽值 + }, 那么很明顯,上述user的密碼明文應當是:
user369{user}
拿上述的字串拷貝到 http://www.51240.com/md5jiami/ 網頁上的輸入框里,點擊加密按鈕,下面即可生成32位數字的密碼密文。
哈哈,屢試不爽啊。這個方法要謹慎使用,一般人我不告訴他。
第二種方法之相關配置
將權限及資源(URL或Action)的關系配置在xml文件中,並且配置與Spring Security3相關的其他配置:
1、applicationContext-Security.xml代碼
- <b:beans xmlns="http://www.springframework.org/schema/security"
- xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.0.xsd">
- <http auto-config="true" access-denied-page="/accessDenied.jsp">
- <!-- 不要過濾圖片等靜態資源,其中**代表可以跨越目錄,*不可以跨越目錄。 -->
- <intercept-url pattern="/**/*.jpg" filters="none" />
- <intercept-url pattern="/**/*.png" filters="none" />
- <intercept-url pattern="/**/*.gif" filters="none" />
- <intercept-url pattern="/**/*.css" filters="none" />
- <intercept-url pattern="/**/*.js" filters="none" />
- <!-- 登錄頁面和忘記密碼頁面不過濾 -->
- <intercept-url pattern="/login.jsp" filters="none" />
- <intercept-url pattern="/jsp/forgotpassword.jsp" filters="none" />
- <!-- 下面是對Action配置。表示具有訪問/unitsManager資源的用戶必須具有ROLE_PLATFORMADMIN的權限。
- 當用戶登錄時,SS3將用戶的所有權限從數據庫中提取出來,形成列表。 當用戶訪問該資源時,SS3將
- 登錄用戶的權限列表提出來跟下面配置的權限進行比對,若有,則允許訪問,若沒有,則給出AccessDeniedException。-->
- <intercept-url pattern="/unitsManager" access="ROLE_PLATFORMADMIN" />
- <intercept-url pattern="/usersManager" access="ROLE_PLATFORMADMIN" />
- <intercept-url pattern="/horizontalQuery" access="ROLE_PLATFORMADMIN" />
- <intercept-url pattern="/verticalQuery" access="ROLE_PLATFORMADMIN" />
- <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/index.jsp" />
- <!-- "記住我"功能,采用持久化策略(將用戶的登錄信息存放在數據庫表中) -->
- <remember-me data-source-ref="dataSource" />
- <!-- 檢測失效的sessionId,超時時定位到另外一個URL -->
- <session-management invalid-session-url="/sessionTimeout.jsp" />
- </http>
- <!-- 注意能夠為authentication-manager 設置alias別名 -->
- <authentication-manager alias="authenticationManager">
- <authentication-provider user-service-ref="userDetailsManager">
- <password-encoder ref="passwordEncoder">
- <!-- 用戶名做為鹽值 -->
- <salt-source user-property="username" />
- </password-encoder>
- </authentication-provider>
- </authentication-manager>
- </b:beans>
2、applicationContext.service.xml:
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
- http://www.springframework.org/schema/jee
- http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util-3.0.xsd">
- <!-- 定義上下文返回的消息的國際化。 -->
- <bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename"
- value="classpath:org/springframework/security/messages_zh_CN"/>
- </bean>
- <!-- 事件監聽:實現了 ApplicationListener監聽接口,包括AuthenticationCredentialsNotFoundEvent 事件,
- AuthorizationFailureEvent事件,AuthorizedEvent事件, PublicInvocationEvent事件 -->
- <bean class="org.springframework.security.authentication.event.LoggerListener" />
- <!-- 用戶的密碼加密或解密 -->
- <bean id="passwordEncoder"
- class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />
- <!-- 用戶詳細信息管理 : 數據源、用戶緩存、啟用用戶組功能。 -->
- <bean id="userDetailsManager"
- class="org.springframework.security.provisioning.JdbcUserDetailsManager">
- <property name="dataSource" ref="dataSource" />
- <property name="userCache" ref="userCache" />
- </bean>
- <bean id="userCache"
- class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
- <property name="cache" ref="userEhCache" />
- </bean>
- <bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
- <property name="cacheName" value="userCache" />
- <property name="cacheManager" ref="cacheManager" />
- </bean>
- <!-- 緩存用戶管理 -->
- <bean id="cacheManager"
- class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
- <!-- spring security自帶的與權限有關的數據讀寫Jdbc模板 -->
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource" ref="dataSource" />
- </bean>
- </beans>
3、web.xml:
- <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <!-- 設置log4j存放Log文件位置(通過spring統一進行管理) -->
- <context-param>
- <param-name>webAppRootKey</param-name>
- <param-value>log.root</param-value>
- </context-param>
- <!-- 加載log4j的配置文件 -->
- <context-param>
- <param-name>log4jConfigLocation</param-name>
- <param-value>classpath:/log4j.properties</param-value>
- </context-param>
- <!--Spring默認刷新Log4j配置文件的間隔,單位為millisecond-->
- <context-param>
- <param-name>log4jRefreshInterval</param-name>
- <param-value>60000</param-value>
- </context-param>
- <!--Spring用於log4j初始化的監聽器-->
- <listener>
- <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
- </listener>
- <!--
- 加載Spring XML配置文件,Spring安全配置及各類資源文件,暫不加
- /WEB-INF/applicationContext-security.xml,
- -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- /WEB-INF/applicationContext*.xml,
- classpath*:applicationContext.xml
- </param-value>
- </context-param>
- <!--spring監聽器的配置,用於在啟動Web容器時,自動裝配ApplicationContext的配置信息-->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- 使用Spring中的過濾器解決在請求和應答中的中文亂碼問題 -->
- <filter>
- <filter-name>characterEncodingFilter</filter-name>
- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
- <init-param>
- <param-name>encoding</param-name>
- <param-value>gbk</param-value>
- </init-param>
- <init-param>
- <!--強制轉換編碼(request和response均適用) -->
- <param-name>ForceEncoding</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>characterEncodingFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- Spring Secutiry3.0.2的過濾器鏈配置 -->
- <filter>
- <filter-name>springSecurityFilterChain</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChain</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- 配置Struts2的FilterDispathcer的Filter -->
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>
- org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
- </filter-class>
- </filter>
- <!-- struts2用以處理用戶Web請求的路徑模式-->
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- 避免亂碼問題 -->
- <filter>
- <filter-name>struts-cleanup</filter-name>
- <filter-class>
- org.apache.struts2.dispatcher.ActionContextCleanUp
- </filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts-cleanup</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- <!-- Spring刷新Interceptor防止內存泄漏 -->
- <listener>
- <listener-class>
- org.springframework.web.util.IntrospectorCleanupListener
- </listener-class>
- </listener>
- <!-- 設置session 超時時間為20分鍾 -->
- <session-config>
- <session-timeout>20</session-timeout>
- </session-config>
- <!--系統歡迎頁面-->
- <welcome-file-list>
- <welcome-file>login.jsp</welcome-file>
- </welcome-file-list>
- </web-app>
第二種方法中遇見的問題
當然,首次使用Spring serutiry,在整合的過程中,我還是遇見了不少問題,當然有些問題比如找不到類呀,包呀,和框架的整合呀等問題不作為談論的重點。主要還是探討Spring Security的配置和注意事項的問題。
我在其中碰到的對我印象最深的問題是,當完全配置好之后,重啟Web服務器,卻發現Spring Security不能攔截任何的URL了,這使我感到驚詫,因為在去年時,我已經將該框架搭建完成,在當時正是使用的該種方法,並且在試驗是否能夠攔截 jsp文件時進行了確認是沒有問題的。
接下來我又整理了一下applicationContext-security.xml的文件才發現, 除了不需要進行檢測的圖片及登錄頁面之外,沒有對任何的資源和權限之間的對應關系進行配置,參見下面的代碼:
- <http auto-config="true" access-denied-page="/accessDenied.jsp">
- <!-- 不要過濾圖片等靜態資源,其中**代表可以跨越目錄,*不可以跨越目錄。 -->
- <intercept-url pattern="/**/*.jpg" filters="none" />
- <intercept-url pattern="/**/*.png" filters="none" />
- <intercept-url pattern="/**/*.gif" filters="none" />
- <intercept-url pattern="/**/*.css" filters="none" />
- <intercept-url pattern="/**/*.js" filters="none" />
- <!-- 登錄頁面和忘記密碼頁面不過濾 -->
- <intercept-url pattern="/login.jsp" filters="none" />
- <intercept-url pattern="/jsp/forgotpassword.jsp" filters="none" />
- <!-- 下面是對Struts2的Action請求時的配置。注意在前面加/,否則不會被SS3進行攔截驗證。
- 表示具有訪問/unitsManager資源的用戶必須具有ROLE_PLATFORMADMIN的權限。
- 當用戶登錄時,SS3將用戶的所有權限從數據庫中提取出來,形成列表。 當用戶訪問該資源時,
- SS3將登錄用戶的權限列表提出來跟下面配置的權限進行比對,若有,則允許訪問,若沒有,
- 則給出AccessDeniedException。
- <intercept-url pattern="/unitsManager" access="ROLE_PLATFORMADMIN" />
- <intercept-url pattern="/usersManager" access="ROLE_PLATFORMADMIN" />
- <intercept-url pattern="/horizontalQuery" access="ROLE_PLATFORMADMIN" />
- <intercept-url pattern="/verticalQuery" access="ROLE_PLATFORMADMIN" /> -->
- <form-login login-page="/login.jsp"
- authentication-failure-url="/login.jsp?error=true"
- default-target-url="/index.jsp" />
- <!-- "記住我"功能,采用持久化策略(將用戶的登錄信息存放在數據庫表中) -->
- <remember-me data-source-ref="dataSource" />
- <!-- 檢測失效的sessionId,超時時定位到另外一個URL -->
- <session-management invalid-session-url="/sessionTimeout.jsp" />
- </http>
這樣一來,spring security3就會認為根本不需要對任何的URL或Action進行檢測(注意上面代碼中被注釋掉的4條配置)。 哈哈,當時這個問題深深動搖了我對Spring security的信心,花費了這么多天的精力,卻是這樣的結果,當時就在考慮是否有更好的替代品。有點崩潰啊。 還好,深深地求知欲和征服欲讓我堅持下來了。
哈哈,這算不算Spring Security的一個Bug呢?沒有任何的權限與資源的配置,就認為登錄后的用戶具有訪問任何資源的權限,說起來有點可怕哈。
當然,當我將上述代碼中被注釋的4條配置放開后,Spring security奇跡般的恢復了活力。
接下來實現了jsp型URL的攔截之后,我又遇見了不能攔截action的情況,不過經過多次的配置和重啟服務試驗,終於發現,在配置 Action與權限時,一定要在Action的路徑前面加“/”斜杠,否則,Spring Security就會對該請求的URL熟視無睹,無視它的存在,即使你在Action的前后加上*號進行匹配也不會起任何作用,哈哈,不禁慨嘆 Spring Security的牛脾氣。
第二種方法BTW
順便提一下子,Spring Security3需要配置的過濾器是雙重的,首先在web.xml中配置一個過濾器代理,參見上述web.xml中的springSecurityFilterChain配置。
我們通常設置過濾的url模式為/*,就是說任何的url訪問都要進行過濾,工作量有點大哈。當然我們可以為之設置不同的過濾url模式,比 如.action、.do、.jsp等。這樣的話,遇到.action或.jsp或.do結尾的url訪問,Spring Security就會突然站出來打截,若是其他的訪問,Spring Security就會揮一揮手,瀟灑地讓你路過。
所以說,這個過濾器主要對大的方面進行攔截,一些細小的活兒,還是要交給第二重過濾器。 就是說,這第一重過濾器是個總代理,他威武地管理着一個過濾器鏈。
那么這第二重過濾器的配置,就是那些所謂的過濾器鏈,分別包括“記住我”、“登錄”、“注銷”、“url訪問”等的過濾器,這個過濾器依順 序排開,形成一個過濾鏈條。具體攔截我們明細Url的是一個叫做FilterInterCeptor的伙計,我認為這個家伙是在整個過濾器鏈條中是最重要 的一個,因為我們登錄系統之后,要訪問的任何資源都必須經得他的同意。 那么這第二重鏈條就設置在applicationContext-security.xml文件中的<http>元素下面。
什么,你看不到? 忘記告訴你了,從spring security2開始,就使用了命名空間,若你在<http>中設置了auto="true",Spring Security就會在服務啟動時自動加載
所有的過濾器鏈,省事了吧!
第三種方法
當然,spring security3畢竟是西方國家的東西,以英文為主,使用習慣和文化的差異共存,況且為了適應大多數Web應用的權限管理,作者將Spring Security3打造的精簡而靈活。精簡指Spring Security3對用戶和權限的表設計的非常簡單,並且沒有采用數據庫來管理資源(URL)。這樣的話,對於我們國人用戶來說,是個很大的遺憾,這個遺 憾甚至能夠影響到我們對安全框架的選型。你想啊,在國內大多數項目中,均設置了比較復雜的權限控制,一般就會涉及到用戶、角色、權限、資源4張表,若要加 上4張表之間的對應關系表3張,得有7張表才行。
得7張表才行,但是Spring Security3才給我們提供了2張最簡潔的表,這足以不能完成國人用戶的項目應用。那么在對Spring Security3一無所知的情況下,
我們很容易就會放棄對該安全框架的選型。
還好,Spring Security3提供了靈活的擴展方法。具體應該擴展哪些類呢? 或者到底Spring Security3工作的流程如何,你不妨參看下面一篇文章,就會獲得
一些啟示,網址為:http://www.blogjava.net/youxia/archive/2008/12/07/244883.html , 哈哈,謝謝分享。
還有一個地址很有價值, http://wenku.baidu.com/view/4ec7e324ccbff121dd368364.html ,我就參考着上面的介紹擴展了4個類。
不過我得提一下,原文的作者為了考驗你的耐性和自信心,故意在代碼里面賣了幾點小小的關子,因此若是完全按照作者的原文代碼裝配起來的權限 系統,是不會那么順利地工作的,天下似乎真是沒有不花費力氣的午餐!在裝配完成后,我也是經過九九八十一難的折磨,在用戶、角色、權限、資源的
“天下黃河九曲十八彎”里面盤旋迂回,終於到達了成功的彼岸。至此才對Spring Security有了更深層次的理解,更加佩服作者的良苦用心。 哈哈。
並擴展了User類以增加其相關的各類其他信息(如Email,職務,所在單位id等)。
相關的代碼如下(包含5個關鍵類):
- /*
- * @(#) MyFilterSecurityInterceptor.java 2011-3-23 上午07:53:03
- *
- * Copyright 2011 by Sparta
- */
- package avatar.base.security;
- import java.io.IOException;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import org.springframework.security.access.SecurityMetadataSource;
- import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
- import org.springframework.security.access.intercept.InterceptorStatusToken;
- import org.springframework.security.web.FilterInvocation;
- import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
- /** *//**
- * 該過濾器的主要作用就是通過spring著名的IoC生成securityMetadataSource。
- * securityMetadataSource相當於本包中自定義的MyInvocationSecurityMetadataSourceService。
- * 該MyInvocationSecurityMetadataSourceService的作用提從數據庫提取權限和資源,裝配到HashMap中,
- * 供Spring Security使用,用於權限校驗。
- * @author sparta 11/3/29
- *
- */
- public class MyFilterSecurityInterceptor
- extends AbstractSecurityInterceptor
- implements Filter{
- private FilterInvocationSecurityMetadataSource securityMetadataSource;
- public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException{
- FilterInvocation fi = new FilterInvocation( request, response, chain );
- invoke(fi);
- }
- public FilterInvocationSecurityMetadataSource getSecurityMetadataSource(){
- return this.securityMetadataSource;
- }
- public Class<? extends Object> getSecureObjectClass(){
- return FilterInvocation.class;
- }
- public void invoke( FilterInvocation fi ) throws IOException, ServletException{
- InterceptorStatusToken token = super.beforeInvocation(fi);
- try{
- fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
- }finally{
- super.afterInvocation(token, null);
- }
- }
- @Override
- public SecurityMetadataSource obtainSecurityMetadataSource(){
- return this.securityMetadataSource;
- }
- public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource){
- this.securityMetadataSource = securityMetadataSource;
- }
- public void destroy(){
- }
- public void init( FilterConfig filterconfig ) throws ServletException{
- }
- }
- /**//*
- * @(#) MyInvocationSecurityMetadataSourceService.java 2011-3-23 下午02:58:29
- *
- * Copyright 2011 by Sparta
- */
- package avatar.base.security;
- import java.util.ArrayList;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import org.hibernate.Session;
- import org.hibernate.SessionFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- import org.springframework.security.access.ConfigAttribute;
- import org.springframework.security.access.SecurityConfig;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.security.web.FilterInvocation;
- import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
- import org.springframework.security.web.util.AntUrlPathMatcher;
- import org.springframework.security.web.util.UrlMatcher;
- import org.springframework.stereotype.Service;
- import avatar.base.security.dao.PubAuthoritiesResourcesHome;
- /** *//**
- * 最核心的地方,就是提供某個資源對應的權限定義,即getAttributes方法返回的結果。 此類在初始化時,應該取到所有資源及其對應角色的定義。
- *
- */
- @Service
- public class MyInvocationSecurityMetadataSourceService implements
- FilterInvocationSecurityMetadataSource {
- @Autowired
- private PubAuthoritiesResourcesHome pubAuthoritiesResourcesHome;
- private UrlMatcher urlMatcher = new AntUrlPathMatcher();
- private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
- public MyInvocationSecurityMetadataSourceService() {
- loadResourceDefine();
- }
- private void loadResourceDefine() {
- ApplicationContext context = new ClassPathXmlApplicationContext(
- "classpath:applicationContext.xml");
- SessionFactory sessionFactory = (SessionFactory) context
- .getBean("sessionFactory");
- Session session = sessionFactory.openSession();
- String username = "";
- String sql = "";
- // 在Web服務器啟動時,提取系統中的所有權限。
- sql = "select authority_name from pub_authorities";
- List<String> query = session.createSQLQuery(sql).list();
- /**//*
- * 應當是資源為key, 權限為value。 資源通常為url, 權限就是那些以ROLE_為前綴的角色。 一個資源可以由多個權限來訪問。
- * sparta
- */
- resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
- for (String auth : query) {
- ConfigAttribute ca = new SecurityConfig(auth);
- List<String> query1 = session
- .createSQLQuery(
- "select b.resource_string "
- + "from Pub_Authorities_Resources a, Pub_Resources b, "
- + "Pub_authorities c where a.resource_id = b.resource_id "
- + "and a.authority_id=c.authority_id and c.Authority_name='"
- + auth + "'").list();
- for (String res : query1) {
- String url = res;
- /**//*
- * 判斷資源文件和權限的對應關系,如果已經存在相關的資源url,則要通過該url為key提取出權限集合,將權限增加到權限集合中。
- * sparta
- */
- if (resourceMap.containsKey(url)) {
- Collection<ConfigAttribute> value = resourceMap.get(url);
- value.add(ca);
- resourceMap.put(url, value);
- } else {
- Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
- atts.add(ca);
- resourceMap.put(url, atts);
- }
- }
- }
- }
- @Override
- public Collection<ConfigAttribute> getAllConfigAttributes() {
- return null;
- }
- // 根據URL,找到相關的權限配置。
- @Override
- public Collection<ConfigAttribute> getAttributes(Object object)
- throws IllegalArgumentException {
- // object 是一個URL,被用戶請求的url。
- String url = ((FilterInvocation) object).getRequestUrl();
- int firstQuestionMarkIndex = url.indexOf("?");
- if (firstQuestionMarkIndex != -1) {
- url = url.substring(0, firstQuestionMarkIndex);
- }
- Iterator<String> ite = resourceMap.keySet().iterator();
- while (ite.hasNext()) {
- String resURL = ite.next();
- if (urlMatcher.pathMatchesUrl(url, resURL)) {
- return resourceMap.get(resURL);
- }
- }
- return null;
- }
- @Override
- public boolean supports(Class<?> arg0) {
- return true;
- }
- }
- /**//*
- * @(#) MyUserDetailsService.java 2011-3-23 上午09:04:31
- *
- * Copyright 2011 by Sparta
- */
- package avatar.base.security;
- import java.util.ArrayList;
- import java.util.Collection;
- import javax.sql.DataSource;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.dao.DataAccessException;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.userdetails.User;
- import org.springframework.security.core.userdetails.UserCache;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.security.core.userdetails.UserDetailsService;
- import org.springframework.security.core.userdetails.UsernameNotFoundException;
- import org.springframework.stereotype.Service;
- import avatar.base.security.dao.PubAuthoritiesResourcesHome;
- import avatar.base.security.dao.PubUsersHome;
- /** *//**
- *該類的主要作用是為Spring Security提供一個經過用戶認證后的UserDetails。
- *該UserDetails包括用戶名、密碼、是否可用、是否過期等信息。
- *sparta 11/3/29
- */
- @Service
- public class MyUserDetailsService implements UserDetailsService {
- @Autowired
- private PubUsersHome pubUsersHome;
- @Autowired
- private PubAuthoritiesResourcesHome pubAuthoritiesResourcesHome;
- @Autowired
- private DataSource dataSource;
- @Autowired
- private UserCache userCache;
- @Override
- public UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException, DataAccessException {
- Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
- //得到用戶的權限
- auths = pubUsersHome.loadUserAuthoritiesByName( username );
- String password = null;
- //取得用戶的密碼
- password = pubUsersHome.getPasswordByUsername( username );
- return new User( username, password, true, "", true, true, true, auths);
- }
- //set PubUsersHome
- public void setPubUsersHome( PubUsersHome pubUsersHome ){
- this.pubUsersHome = pubUsersHome;
- }
- public PubUsersHome getPubUsersHome(){
- return pubUsersHome;
- }
- //set PubAuthoritiesResourcesHome
- public void setPubAuthoritiesResourcesHome( PubAuthoritiesResourcesHome pubAuthoritiesResourcesHome ){
- this.pubAuthoritiesResourcesHome = pubAuthoritiesResourcesHome;
- }
- public PubAuthoritiesResourcesHome getPubAuthoritiesResourcesHome(){
- return pubAuthoritiesResourcesHome;
- }
- //set DataSource
- public void setDataSource( DataSource dataSource ){
- this.dataSource = dataSource;
- }
- public DataSource getDataSource(){
- return dataSource;
- }
- //設置用戶緩存功能。
- public void setUserCache(UserCache userCache) {
- this.userCache = userCache;
- }
- public UserCache getUserCache(){
- return this.userCache;
- }
- }
- /**//*
- * @(#) MyAccessDecisionManager.java 2011-3-23 下午04:41:12
- *
- * Copyright 2011 by Sparta
- */
- package avatar.base.security;
- import java.util.Collection;
- import java.util.Iterator;
- import org.springframework.security.access.AccessDecisionManager;
- import org.springframework.security.access.AccessDeniedException;
- import org.springframework.security.access.ConfigAttribute;
- import org.springframework.security.access.SecurityConfig;
- import org.springframework.security.authentication.InsufficientAuthenticationException;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.GrantedAuthority;
- /** *//**
- *AccessdecisionManager在Spring security中是很重要的。
- *
- *在驗證部分簡略提過了,所有的Authentication實現需要保存在一個GrantedAuthority對象數組中。
- *這就是賦予給主體的權限。 GrantedAuthority對象通過AuthenticationManager
- *保存到 Authentication對象里,然后從AccessDecisionManager讀出來,進行授權判斷。
- *
- *Spring Security提供了一些攔截器,來控制對安全對象的訪問權限,例如方法調用或web請求。
- *一個是否允許執行調用的預調用決定,是由AccessDecisionManager實現的。
- *這個 AccessDecisionManager 被AbstractSecurityInterceptor調用,
- *它用來作最終訪問控制的決定。 這個AccessDecisionManager接口包含三個方法:
- *
- void decide(Authentication authentication, Object secureObject,
- List<ConfigAttributeDefinition> config) throws AccessDeniedException;
- boolean supports(ConfigAttribute attribute);
- boolean supports(Class clazz);
- 從第一個方法可以看出來,AccessDecisionManager使用方法參數傳遞所有信息,這好像在認證評估時進行決定。
- 特別是,在真實的安全方法期望調用的時候,傳遞安全Object啟用那些參數。
- 比如,讓我們假設安全對象是一個MethodInvocation。
- 很容易為任何Customer參數查詢MethodInvocation,
- 然后在AccessDecisionManager里實現一些有序的安全邏輯,來確認主體是否允許在那個客戶上操作。
- 如果訪問被拒絕,實現將拋出一個AccessDeniedException異常。
- 這個 supports(ConfigAttribute) 方法在啟動的時候被
- AbstractSecurityInterceptor調用,來決定AccessDecisionManager
- 是否可以執行傳遞ConfigAttribute。
- supports(Class)方法被安全攔截器實現調用,
- 包含安全攔截器將顯示的AccessDecisionManager支持安全對象的類型。
- */
- public class MyAccessDecisionManager implements AccessDecisionManager {
- public void decide( Authentication authentication, Object object,
- Collection<ConfigAttribute> configAttributes)
- throws AccessDeniedException, InsufficientAuthenticationException{
- if( configAttributes == null ) {
- return ;
- }
- Iterator<ConfigAttribute> ite = configAttributes.iterator();
- while( ite.hasNext()){
- ConfigAttribute ca = ite.next();
- String needRole = ((SecurityConfig)ca).getAttribute();
- //ga 為用戶所被賦予的權限。 needRole 為訪問相應的資源應該具有的權限。
- for( GrantedAuthority ga: authentication.getAuthorities()){
- if(needRole.trim().equals(ga.getAuthority().trim())){
- return;
- }
- }
- }
- throw new AccessDeniedException("");
- }
- public boolean supports( ConfigAttribute attribute ){
- return true;
- }
- public boolean supports(Class<?> clazz){
- return true;
- }
- }
數據庫的SQL及預置數據:
- prompt PL/SQL Developer import file
- prompt Created on 2011年6月1日 by Administrator
- set feedback off
- set define off
- prompt Creating SYS_AUTHORITIES
- create table SYS_AUTHORITIES
- (
- AUTHORITY_ID VARCHAR2(32) not null,
- AUTHORITY_NAME VARCHAR2(40),
- AUTHORITY_DESC VARCHAR2(100),
- ENABLED NUMBER(1),
- ISSYS NUMBER(1),
- MODULE VARCHAR2(4)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_AUTHORITIES
- is '權限表';
- comment on column SYS_AUTHORITIES.MODULE
- is '所屬的子系統,比如平台里面包括10個系統,分別為成本、作業、集輸等。';
- alter table SYS_AUTHORITIES
- add constraint PK_PUB_AUTHORITIES primary key (AUTHORITY_ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- prompt Creating SYS_RESOURCES
- create table SYS_RESOURCES
- (
- RESOURCE_ID VARCHAR2(32) not null,
- RESOURCE_NAME VARCHAR2(100),
- RESOURCE_DESC VARCHAR2(100),
- RESOURCE_TYPE VARCHAR2(40),
- RESOURCE_STRING VARCHAR2(200),
- PRIORITY NUMBER(1),
- ENABLED NUMBER(1),
- ISSYS NUMBER(1),
- MODULE VARCHAR2(4)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_RESOURCES
- is '資源表';
- comment on column SYS_RESOURCES.PRIORITY
- is '(暫不用,保留)';
- comment on column SYS_RESOURCES.MODULE
- is '所屬的子系統,比如平台里面包括10個系統,分別為成本、作業、集輸等。 (暫不用,保留)';
- alter table SYS_RESOURCES
- add constraint PK_PUB_RESOURCES primary key (RESOURCE_ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- prompt Creating SYS_AUTHORITIES_RESOURCES
- create table SYS_AUTHORITIES_RESOURCES
- (
- ID NUMBER(13) not null,
- AUTHORITY_ID VARCHAR2(32),
- RESOURCE_ID VARCHAR2(32),
- ENABLED NUMBER(1)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_AUTHORITIES_RESOURCES
- is '權限資源表';
- alter table SYS_AUTHORITIES_RESOURCES
- add constraint PK_PUB_AUTHORITIES_RE primary key (ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- alter table SYS_AUTHORITIES_RESOURCES
- add constraint FK_PUB_AUTHORITIES_RE_AU foreign key (AUTHORITY_ID)
- references SYS_AUTHORITIES (AUTHORITY_ID);
- alter table SYS_AUTHORITIES_RESOURCES
- add constraint FK_PUB_AUTHORITIES_RE_RE foreign key (RESOURCE_ID)
- references SYS_RESOURCES (RESOURCE_ID);
- prompt Creating SYS_ROLES
- create table SYS_ROLES
- (
- ROLE_ID VARCHAR2(32) not null,
- ROLE_NAME VARCHAR2(40),
- ROLE_DESC VARCHAR2(100),
- ENABLED NUMBER(1),
- ISSYS NUMBER(1),
- MODULE VARCHAR2(4)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_ROLES
- is '角色表';
- comment on column SYS_ROLES.MODULE
- is '所屬的子系統,比如平台里面包括10個系統,分別為成本、作業、集輸等。';
- alter table SYS_ROLES
- add constraint PK_PUB_ROLES primary key (ROLE_ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- prompt Creating SYS_ROLES_AUTHORITIES
- create table SYS_ROLES_AUTHORITIES
- (
- ID NUMBER(13) not null,
- ROLE_ID VARCHAR2(32),
- AUTHORITY_ID VARCHAR2(32),
- ENABLED NUMBER(1)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_ROLES_AUTHORITIES
- is '角色權限表';
- alter table SYS_ROLES_AUTHORITIES
- add constraint PK_PUB_ROLES_AUTHORITY primary key (ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- alter table SYS_ROLES_AUTHORITIES
- add constraint FK_PUB_ROLES_AUTHORITIES_AU foreign key (AUTHORITY_ID)
- references SYS_AUTHORITIES (AUTHORITY_ID);
- alter table SYS_ROLES_AUTHORITIES
- add constraint FK_PUB_ROLES_AUTHORITIES_ROLES foreign key (ROLE_ID)
- references SYS_ROLES (ROLE_ID);
- prompt Creating SYS_USERS
- create table SYS_USERS
- (
- USER_ID VARCHAR2(32) not null,
- USER_ACCOUNT VARCHAR2(30),
- USER_NAME VARCHAR2(40),
- USER_PASSWORD VARCHAR2(100),
- USER_DESC VARCHAR2(100),
- ENABLED NUMBER(1),
- ISSYS NUMBER(1),
- USER_DEPT VARCHAR2(20),
- USER_DUTY VARCHAR2(10),
- SUB_SYSTEM VARCHAR2(30)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_USERS
- is '用戶表';
- comment on column SYS_USERS.USER_PASSWORD
- is '該密碼是經加鹽值加密的,格式為password{username}。 比如用戶的密碼為user,用戶名為user,那么通過MD5進行加密的串為: user{user}';
- comment on column SYS_USERS.ISSYS
- is '是否是超級用戶';
- comment on column SYS_USERS.USER_DEPT
- is '所在單位';
- comment on column SYS_USERS.USER_DUTY
- is '經理或主任';
- comment on column SYS_USERS.SUB_SYSTEM
- is '該用戶所負責的各子系統,可多個,中間用逗號分隔。(目前暫未用,作為保留字段)';
- alter table SYS_USERS
- add constraint PK_PUB_USERS primary key (USER_ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- prompt Creating SYS_USERS_ROLES
- create table SYS_USERS_ROLES
- (
- ID NUMBER(13) not null,
- USER_ID VARCHAR2(32),
- ROLE_ID VARCHAR2(32),
- ENABLED NUMBER(1)
- )
- tablespace SCJD
- pctfree 10
- initrans 1
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- comment on table SYS_USERS_ROLES
- is '用戶角色表';
- alter table SYS_USERS_ROLES
- add constraint PK_PUB_USERS_ROLES primary key (ID)
- using index
- tablespace SCJD
- pctfree 10
- initrans 2
- maxtrans 255
- storage
- (
- initial 64K
- minextents 1
- maxextents unlimited
- );
- alter table SYS_USERS_ROLES
- add constraint FK_USERS_ROLES_ROLES foreign key (ROLE_ID)
- references SYS_ROLES (ROLE_ID);
- alter table SYS_USERS_ROLES
- add constraint FK_USERS_ROLES_USERS foreign key (USER_ID)
- references SYS_USERS (USER_ID);
- prompt Disabling triggers for SYS_AUTHORITIES
- alter table SYS_AUTHORITIES disable all triggers;
- prompt Disabling triggers for SYS_RESOURCES
- alter table SYS_RESOURCES disable all triggers;
- prompt Disabling triggers for SYS_AUTHORITIES_RESOURCES
- alter table SYS_AUTHORITIES_RESOURCES disable all triggers;
- prompt Disabling triggers for SYS_ROLES
- alter table SYS_ROLES disable all triggers;
- prompt Disabling triggers for SYS_ROLES_AUTHORITIES
- alter table SYS_ROLES_AUTHORITIES disable all triggers;
- prompt Disabling triggers for SYS_USERS
- alter table SYS_USERS disable all triggers;
- prompt Disabling triggers for SYS_USERS_ROLES
- alter table SYS_USERS_ROLES disable all triggers;
- prompt Disabling foreign key constraints for SYS_AUTHORITIES_RESOURCES
- alter table SYS_AUTHORITIES_RESOURCES disable constraint FK_PUB_AUTHORITIES_RE_AU;
- alter table SYS_AUTHORITIES_RESOURCES disable constraint FK_PUB_AUTHORITIES_RE_RE;
- prompt Disabling foreign key constraints for SYS_ROLES_AUTHORITIES
- alter table SYS_ROLES_AUTHORITIES disable constraint FK_PUB_ROLES_AUTHORITIES_AU;
- alter table SYS_ROLES_AUTHORITIES disable constraint FK_PUB_ROLES_AUTHORITIES_ROLES;
- prompt Disabling foreign key constraints for SYS_USERS_ROLES
- alter table SYS_USERS_ROLES disable constraint FK_USERS_ROLES_ROLES;
- alter table SYS_USERS_ROLES disable constraint FK_USERS_ROLES_USERS;
- prompt Deleting SYS_USERS_ROLES
- delete from SYS_USERS_ROLES;
- commit;
- prompt Deleting SYS_USERS
- delete from SYS_USERS;
- commit;
- prompt Deleting SYS_ROLES_AUTHORITIES
- delete from SYS_ROLES_AUTHORITIES;
- commit;
- prompt Deleting SYS_ROLES
- delete from SYS_ROLES;
- commit;
- prompt Deleting SYS_AUTHORITIES_RESOURCES
- delete from SYS_AUTHORITIES_RESOURCES;
- commit;
- prompt Deleting SYS_RESOURCES
- delete from SYS_RESOURCES;
- commit;
- prompt Deleting SYS_AUTHORITIES
- delete from SYS_AUTHORITIES;
- commit;
- prompt Loading SYS_AUTHORITIES
- insert into SYS_AUTHORITIES (AUTHORITY_ID, AUTHORITY_NAME, AUTHORITY_DESC, ENABLED, ISSYS, MODULE)
- values ('1303910437484', 'AUTH_xxx', 'xxx', null, null, '01');
- insert into SYS_AUTHORITIES (AUTHORITY_ID, AUTHORITY_NAME, AUTHORITY_DESC, ENABLED, ISSYS, MODULE)
- values ('AUTH_LOGIN4', 'AUTH_LOGIN', '登錄', 1, 0, '01');
- insert into SYS_AUTHORITIES (AUTHORITY_ID, AUTHORITY_NAME, AUTHORITY_DESC, ENABLED, ISSYS, MODULE)
- values ('AUTH_AFTERLOGINWELCOME5', 'AUTH_AFTERLOGINWELCOME', '登錄后歡迎界面', 1, 0, '01');
- insert into SYS_AUTHORITIES (AUTHORITY_ID, AUTHORITY_NAME, AUTHORITY_DESC, ENABLED, ISSYS, MODULE)
- values ('AUTH_XTSZ_DEPT1', 'AUTH_XTSZ_DEPT', '單位設置', 1, 0, '01');
- insert into SYS_AUTHORITIES (AUTHORITY_ID, AUTHORITY_NAME, AUTHORITY_DESC, ENABLED, ISSYS, MODULE)
- values ('AUTH_XTSZ_USER2', 'AUTH_XTSZ_USER', '用戶設置、橫向查詢', 1, 0, '01');
- insert into SYS_AUTHORITIES (AUTHORITY_ID, AUTHORITY_NAME, AUTHORITY_DESC, ENABLED, ISSYS, MODULE)
- values ('AUTH_NODE_MGR3', 'AUTH_NODE_MGR', '節點管理、縱向查詢', 1, 0, '01');
- commit;
- prompt 6 records loaded
- prompt Loading SYS_RESOURCES
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('1303909883031', 'ff', 'ff', 'action', 'b.jsp', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('1303909847687', 'ff1', 'ff1', 'action', 'b.jsp', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('node_mgr3', 'node_mgr', '節點管理', 'url', '/*/*/Tree.jsp', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('login4', 'login', '登錄', 'url', '/login.jsp', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('index5', 'index', '登錄后歡迎頁面', 'url', '/index.jsp', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('resources_mgr', 'resources_mgr', '資源管理', 'action', '/managerResource', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('horizontal_qry6', 'horizontal_qry', '橫向查詢', 'action', '/horizontalQuery', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('vertical_qry7', 'vertical_qry', '縱向查詢', 'action', '/verticalQuery', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('dep_mgr1', 'dep_mgr', '單位管理', 'action', '/UnitsManager', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('user_mgr2', 'user_mgr', '用戶管理', 'action', '/managerUser', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('authority_mgr', 'authority_mgr', '權限管理', 'action', '/managerAuthority', null, 1, 0, null);
- insert into SYS_RESOURCES (RESOURCE_ID, RESOURCE_NAME, RESOURCE_DESC, RESOURCE_TYPE, RESOURCE_STRING, PRIORITY, ENABLED, ISSYS, MODULE)
- values ('role_mgr', 'role_mgr', '角色管理', 'action', '/managerRole', null, null, null, null);
- commit;
- prompt 12 records loaded
- prompt Loading SYS_AUTHORITIES_RESOURCES
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (1, 'AUTH_AFTERLOGINWELCOME5', 'index5', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (2, 'AUTH_LOGIN4', 'login4', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (3, 'AUTH_NODE_MGR3', 'node_mgr3', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (4, 'AUTH_XTSZ_DEPT1', 'dep_mgr1', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (5, 'AUTH_XTSZ_USER2', 'user_mgr2', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (7, 'AUTH_XTSZ_USER2', 'horizontal_qry6', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (8, 'AUTH_XTSZ_DEPT1', 'vertical_qry7', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (12, 'AUTH_XTSZ_USER2', 'role_mgr', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (10, 'AUTH_XTSZ_USER2', 'resources_mgr', 1);
- insert into SYS_AUTHORITIES_RESOURCES (ID, AUTHORITY_ID, RESOURCE_ID, ENABLED)
- values (11, 'AUTH_XTSZ_USER2', 'authority_mgr', 1);
- commit;
- prompt 10 records loaded
- prompt Loading SYS_ROLES
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('1303463518765', 'ROLE_dd1', 'dd1', 1, 0, '01');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('1303463949640', 'ROLE_rr1', 'rr1', 1, 0, '02');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('ROLE_PLATFORMADMIN1', 'ROLE_PLATFORMADMIN', '可管理整個平台的用戶、單位設置。', 1, 1, '01');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('ROLE_USER2', 'ROLE_USER', '普通用戶', 1, 0, '01');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('ROLE_LOGINTOWELCOME4', 'ROLE_LOGINTOWELCOME', '僅登錄到歡迎界面!', 1, 0, '01');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('ROLE_SYSADMIN3', 'ROLE_SYSADMIN', '可管理本系統的用戶、單位設置。', 1, 0, '01');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('ROLE_WORK', 'ROLE_WORK', '作業子系統的角色(試驗)', 1, 0, '02');
- insert into SYS_ROLES (ROLE_ID, ROLE_NAME, ROLE_DESC, ENABLED, ISSYS, MODULE)
- values ('ROLE_LOGIN', 'ROLE_LOGIN', '系統登錄', 1, 0, '01');
- commit;
- prompt 8 records loaded
- prompt Loading SYS_ROLES_AUTHORITIES
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1, 'ROLE_LOGINTOWELCOME4', 'AUTH_AFTERLOGINWELCOME5', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (2, 'ROLE_PLATFORMADMIN1', 'AUTH_AFTERLOGINWELCOME5', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (3, 'ROLE_PLATFORMADMIN1', 'AUTH_LOGIN4', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (4, 'ROLE_PLATFORMADMIN1', 'AUTH_NODE_MGR3', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (5, 'ROLE_PLATFORMADMIN1', 'AUTH_XTSZ_DEPT1', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (6, 'ROLE_PLATFORMADMIN1', 'AUTH_XTSZ_USER2', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (7, 'ROLE_SYSADMIN3', 'AUTH_XTSZ_DEPT1', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (8, 'ROLE_SYSADMIN3', 'AUTH_XTSZ_USER2', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (9, 'ROLE_USER2', 'AUTH_LOGIN4', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (10, 'ROLE_LOGINTOWELCOME4', 'AUTH_LOGIN4', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (11, 'ROLE_USER2', 'AUTH_AFTERLOGINWELCOME5', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303463962718, '1303463949640', 'AUTH_LOGIN4', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303463972234, 'ROLE_WORK', 'AUTH_LOGIN4', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303463972235, 'ROLE_WORK', 'AUTH_AFTERLOGINWELCOME5', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303463972250, 'ROLE_WORK', 'AUTH_XTSZ_DEPT1', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303463972251, 'ROLE_WORK', 'AUTH_XTSZ_USER2', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303463972265, 'ROLE_WORK', 'AUTH_NODE_MGR3', 1);
- insert into SYS_ROLES_AUTHORITIES (ID, ROLE_ID, AUTHORITY_ID, ENABLED)
- values (1303287600015, 'ROLE_LOGIN', 'AUTH_LOGIN4', 1);
- commit;
- prompt 18 records loaded
- prompt Loading SYS_USERS
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('1304494573750', 'lxb', 'lxb', 'c7d3f4c857bc8c145d6e5d40c1bf23d9', null, 1, 0, '10011001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('1304490737406', 'lxb', 'lxb', 'c7d3f4c857bc8c145d6e5d40c1bf23d9', null, 1, 0, '10011001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('1304574079546', 'ddd', 'ddd', '0a4f6a961276619f7f91356bcba5a746', null, 0, 0, null, null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('1304573363921', 'lxb', '盧小兵', '09eb37d219cfa835db40e5ab587f7082', '普通僅登錄到歡迎界面!', 0, 0, '1001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('1304573484515', 'lll', 'lll', '47acedc22cef8c3762c21a435e262d67', null, 1, 0, '1001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('admin1', 'admin', '系統管理員', 'ceb4f32325eda6142bd65215f4c0f371', '超級系統管理員', 1, 1, '1001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('user2', 'user', '普通用戶', '47a733d60998c719cf3526ae7d106d13', '普通用戶', 1, 0, '1001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('sysUser3', 'sysUser', '系統設置維護', '8f0295328c34f8eedc2362e9f4a10b7e', '系統設置用戶', 1, 0, '1001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('lxb4', 'lxb', '盧小兵', 'c7d3f4c857bc8c145d6e5d40c1bf23d9', '普通僅登錄到歡迎界面!', 1, 0, '1001', null, '01');
- insert into SYS_USERS (USER_ID, USER_ACCOUNT, USER_NAME, USER_PASSWORD, USER_DESC, ENABLED, ISSYS, USER_DEPT, USER_DUTY, SUB_SYSTEM)
- values ('1304566319625', 'lxb5', 'lx5', '1abe40ed6d0da1c834586e8ecef61fe7', null, 0, 0, '10011001', null, '01');
- commit;
- prompt 10 records loaded
- prompt Loading SYS_USERS_ROLES
- insert into SYS_USERS_ROLES (ID, USER_ID, ROLE_ID, ENABLED)
- values (1, 'admin1', 'ROLE_PLATFORMADMIN1', 1);
- insert into SYS_USERS_ROLES (ID, USER_ID, ROLE_ID, ENABLED)
- values (2, 'sysUser3', 'ROLE_SYSADMIN3', 1);
- insert into SYS_USERS_ROLES (ID, USER_ID, ROLE_ID, ENABLED)
- values (3, 'user2', 'ROLE_USER2', 1);
- insert into SYS_USERS_ROLES (ID, USER_ID, ROLE_ID, ENABLED)
- values (4, 'lxb4', 'ROLE_LOGINTOWELCOME4', 1);
- insert into SYS_USERS_ROLES (ID, USER_ID, ROLE_ID, ENABLED)
- values (5, '1304573484515', '1303463518765', null);
- commit;
- prompt 5 records loaded
- prompt Enabling foreign key constraints for SYS_AUTHORITIES_RESOURCES
- alter table SYS_AUTHORITIES_RESOURCES enable constraint FK_PUB_AUTHORITIES_RE_AU;
- alter table SYS_AUTHORITIES_RESOURCES enable constraint FK_PUB_AUTHORITIES_RE_RE;
- prompt Enabling foreign key constraints for SYS_ROLES_AUTHORITIES
- alter table SYS_ROLES_AUTHORITIES enable constraint FK_PUB_ROLES_AUTHORITIES_AU;
- alter table SYS_ROLES_AUTHORITIES enable constraint FK_PUB_ROLES_AUTHORITIES_ROLES;
- prompt Enabling foreign key constraints for SYS_USERS_ROLES
- alter table SYS_USERS_ROLES enable constraint FK_USERS_ROLES_ROLES;
- alter table SYS_USERS_ROLES enable constraint FK_USERS_ROLES_USERS;
- prompt Enabling triggers for SYS_AUTHORITIES
- alter table SYS_AUTHORITIES enable all triggers;
- prompt Enabling triggers for SYS_RESOURCES
- alter table SYS_RESOURCES enable all triggers;
- prompt Enabling triggers for SYS_AUTHORITIES_RESOURCES
- alter table SYS_AUTHORITIES_RESOURCES enable all triggers;
- prompt Enabling triggers for SYS_ROLES
- alter table SYS_ROLES enable all triggers;
- prompt Enabling triggers for SYS_ROLES_AUTHORITIES
- alter table SYS_ROLES_AUTHORITIES enable all triggers;
- prompt Enabling triggers for SYS_USERS
- alter table SYS_USERS enable all triggers;
- prompt Enabling triggers for SYS_USERS_ROLES
- alter table SYS_USERS_ROLES enable all triggers;
- set feedback on
- set define on
- prompt Done.
相關配置文件:
web.xml與第一種方法同。
applicationContext-security.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <b:beans xmlns="http://www.springframework.org/schema/security"
- xmlns:b="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.0.xsd">
- <http auto-config="true" access-denied-page="/accessDenied.jsp">
- <!-- 不要過濾圖片等靜態資源 -->
- <intercept-url pattern="/**/*.jpg" filters="none" />
- <intercept-url pattern="/**/*.png" filters="none" />
- <intercept-url pattern="/**/*.gif" filters="none" />
- <intercept-url pattern="/**/*.css" filters="none" />
- <intercept-url pattern="/**/*.js" filters="none" />
- <!-- 登錄頁面和忘記密碼頁面不過濾 -->
- <intercept-url pattern="/login.jsp" filters="none" />
- <intercept-url pattern="/jsp/forgotpassword.jsp"
- filters="none" />
- <form-login login-page="/login.jsp"
- authentication-failure-url="/login.jsp?error=true"
- default-target-url="/index.jsp" />
- <!-- "記住我"功能,采用持久化策略(將用戶的登錄信息存放在數據庫表中) -->
- <remember-me data-source-ref="dataSource" />
- <!-- 檢測失效的sessionId,超時時定位到另外一個URL -->
- <session-management invalid-session-url="/sessionTimeout.jsp" />
- <!-- 增加一個自定義的filter,放在FILTER_SECURITY_INTERCEPTOR之前,
- 實現用戶、角色、權限、資源的數據庫管理。 -->
- <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR"/>
- </http>
- <!-- 一個自定義的filter,必須包含authenticationManager,
- accessDecisionManager,securityMetadataSource三個屬性。 -->
- <b:bean id="myFilter"
- class="avatar.base.security.MyFilterSecurityInterceptor">
- <b:property name="authenticationManager"
- ref="authenticationManager"/>
- <b:property name="accessDecisionManager"
- ref="myAccessDecisionManager"/>
- <b:property name="securityMetadataSource"
- ref="mySecurityMetadataSource"/>
- </b:bean>
- <!-- 注意能夠為authentication-manager 設置alias別名 -->
- <authentication-manager alias="authenticationManager">
- <authentication-provider user-service-ref="userDetailsManager">
- <password-encoder ref="passwordEncoder">
- <salt-source user-property="username" />
- </password-encoder>
- </authentication-provider>
- </authentication-manager>
- <!-- 訪問決策器,決定某個用戶具有的角色,是否有足夠的權限去訪問某個資源。 -->
- <b:bean id="myAccessDecisionManager"
- class="avatar.base.security.MyAccessDecisionManager">
- </b:bean>
- <!-- 資源源數據定義,將所有的資源和權限對應關系建立起來,即定義某一資源可以被哪些角色去訪問。 -->
- <b:bean id="mySecurityMetadataSource"
- class="avatar.base.security.MyInvocationSecurityMetadataSourceService">
- </b:bean>
- </b:beans>
- applicationContext-service.xml:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:jee="http://www.springframework.org/schema/jee"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
- http://www.springframework.org/schema/jee
- http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.0.xsd
- http://www.springframework.org/schema/util
- http://www.springframework.org/schema/util/spring-util-3.0.xsd">
- <!-- 定義上下文返回的消息的國際化。 -->
- <bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename"
- value="classpath:org/springframework/security/messages_zh_CN"/>
- </bean>
- <!--
- 事件監聽:實現了 ApplicationListener監聽接口,
- 包括AuthenticationCredentialsNotFoundEvent 事件,
- AuthorizationFailureEvent事件,AuthorizedEvent事件, PublicInvocationEvent事
- 件。 -->
- <bean
- class="org.springframework.security.authentication.event.LoggerListener" />
- <!-- 用戶的密碼加密或解密 -->
- <bean id="passwordEncoder"
- class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />
- <!-- 用戶詳細信息管理:數據源、用戶緩存(通過數據庫管理用戶、角色、權限、資源)。 -->
- <bean id="userDetailsManager" class="avatar.base.security.MyUserDetailsService">
- <property name="pubUsersHome" ref="pubUsersHome" />
- <property name="pubAuthoritiesResourcesHome" ref="pubAuthoritiesResourcesHome" />
- <property name="dataSource" ref="dataSource" />
- <property name="userCache" ref="userCache" />
- </bean>
- <!-- 啟用用戶的緩存功能 -->
- <bean id="userCache"
- class="org.springframework.security.core.userdetails.cache.EhCacheBasedUserCache">
- <property name="cache" ref="userEhCache" />
- </bean>
- <bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
- <property name="cacheName" value="userCache" />
- <property name="cacheManager" ref="cacheManager" />
- </bean>
- <bean id="cacheManager"
- class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" />
- <!-- spring security自帶的與權限有關的數據讀寫Jdbc模板 -->
- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
- <property name="dataSource" ref="dataSource" />
- </bean>
- </beans>
第三種方法擴展后Spring Security3.0.2的驗證和授權方法
為了敘述的嚴謹性,這里說的是Spring Security3.0.2,而非其他版本,這是因為我只讀過Spring Security3.0.2的代碼,並且在該版本上面擴展自定義的
動態管理用戶、角色、權限和資源成功。 估計其他版本的驗證和授權方法是差不太多的,因為沒有接觸過,也不敢大膽猜測。
在擴展后的Spring Security3.0.2中,驗證及授權的過程如下:
1、當Web服務器啟動時,通過Web.xml中對於Spring Security的配置,加載過濾器鏈,那么在加載MyFilterSecurityInterceptor類時,會注入 MyInvocationSecurityMetadataSourceService、MyUserDetailsService、 MyAccessDecisionManager類。
2、該MyInvocationSecurityMetadataSourceService類在執行時會提取數據庫中所有的用戶權限,形成權限列表;
並循環該權限列表,通過每個權限再從數據庫中提取出該權限所對應的資源列表,並將資源(URL)作為key,權限列表作為value,形成Map結構的數據。
3、當用戶登錄時,AuthenticationManager進行響應,通過用戶輸入的用戶名和密碼,然后再根據用戶定義的密碼算法和鹽值等進行計算並和數據庫比對,
當正確時通過驗證。此時MyUserDetailsService進行響應,根據用戶名從數據庫中提取該用戶的權限列表,組合成UserDetails供Spring Security使用。
4、當用戶點擊某個功能時,觸發MyAccessDecisionManager類,該類通過decide方法對用戶的資源訪問進行攔截。
用戶點擊某個功能時,實際上是請求某個URL或Action, 無論.jsp也好,.action或.do也好,在請求時無一例外的表現為URL。
還記得第2步時那個Map結構的數據嗎? 若用戶點擊了"login.action"這個URL之后,那么這個URL就跟那個Map結構的數據中的key對比,若兩者相同,
則根據該url提取出Map結構的數據中的value來,這說明:若要請求這個URL,必須具有跟這個URL相對應的權限值。這個權限有可能是一個單獨的權限,
也有可能是一個權限列表,也就是說,一個URL有可能被多種權限訪問。
那好,我們在MyAccessDecisionManager類的decide這個方法里,將通過URL取得的權限列表進行循環,然后跟第 3步中登錄的用戶所具有的權限進行比對,若相同,則表明該用戶具有訪問該資源的權利。 不大明白吧? 簡單地說, 在數據庫中我們定義了訪問“LOGIN”這個URL必須是具有ROLE_ADMIN權限的人來訪問,那么,登錄用戶恰恰具有該ROLE_ADMIN權限, 兩者的比對過程中,就能夠返回TRUE,可以允許該用戶進行訪問。就這么簡單!
不過在第2步的時候,一定要注意,MyInvocationSecurityMetadataSoruceService類的loadResourceDefine()方法中,形成以URL為key,權限列表為value的Map時,
要注意key和Value的對應性,避免Value的不正確對應形成重復,這樣會導致沒有權限的人也能訪問到不該訪問到的資源。
還有getAttributes()方法,要有 url.indexOf("?")這樣的判斷,要通過判斷對URL特別是Action問號之前的部分進行匹配,防止用戶請求的帶參數的URL與你數據庫中定義的URL不匹配,造成訪問拒絕!
第三種方法BTW
當然,你在設計了7張表之后,那么對於這些之間相互關聯的關系內容及信息內容,就得由你來進行維護了,大約有用戶、角色、權限、資源的增刪 改查,並還需要設置用戶和角色、角色和權限、權限和資源之間的關系。可考慮分為三個菜單進行維護,用戶設置、角色設置、資源設置。 在用戶設置里分別管理用戶、用戶與角色的關系;在角色設置里管理角色、角色與權限的關系; 在資源設置里分別管理權限、權限與資源的關系等。
第四種方法
第四種方法就是直接修改源碼以達到第三種方法的效果。
本來准備是直接從源碼修改來的, 但是始終認為修改源碼並非終極解決之道,有違OO的精神本質,再者由於時間關系,只是對代碼進行了研究,但並沒有進行實現或驗證。只待以后時間稍稍寬松時 再做為興趣進行研究,在次不過多的講解。但據我從代碼上來看,一是將從配置文件中獲取用戶及權限的功能修改為從數據庫中提取出來;二是將從配置文件中獲取 權限和資源的對應關系修改為從數據庫中提取;三是修改User增加相關信息等。
始終還是圍繞着JdbcDaoImpl和DefaultFilterInvocationSecurityMetadataSource還有User這3個類進行修改。
以實現從數據庫提取用戶、角色、權限和資源信息。
有興趣的就先試試吧,等試好了告訴我一聲哈。
Spring Security的優缺點
不可否認,Spring Security依賴於Spring的Ioc、AOP等機制,橫切開系統的業務組件,將通用的權限功能注入到業務組件內部,實現了通用功能和業務功能的無 縫整合,但又保證了通用功能和業務功能的實現上的分離,省卻了一部分工作量,這是其存在的最重要意義。
但又不可否認,Spring Security所具有的缺乏動態資源管理的硬傷(若是能夠提供用戶、角色、權限和資源的數據庫管理,並且提供管理界面那實在是太完美了,可惜這兩樣一樣都不能實現),又令國人用戶愛恨交加。
該何去何從,就請自己做個選擇吧!