Jsp Spring Security 权限管理系统
Jsp?Spring?Security?權限管理系統?
權限管理搭建要的問題:
1、區分Authentication(驗證)與?Authorization(授權)
驗證
這個用戶是誰?
用戶身份可靠嗎?
授權
某用戶A是否可以訪問資源R
某用戶A是否可以執行M操作
某用戶A是否可以對資源R執行M操作
2、SS中的驗證特點
支持多種驗證方式
支持多種加密格式
支持組件的擴展和替換
可以本地化輸出信息
3、SS中的授權特點
支持多種仲裁方式
支持組件的擴展和替換
支持對頁面訪問、方法訪問、對象訪問的授權。
4、SS核心安全實現
Web安全
通過配置Servlet?Filter激活SS中的過濾器鏈
實現Session一致性驗證
實現免登陸驗證(Remember-Me驗證)
提供一系列標簽庫進行頁面元素的安全控制
方法安全
通過AOP模式實現安全代理
Web安全與方法安全均可以使用表達式語言定義訪問規則
5、配置SS
配置Web.xml,應用安全過濾器
配置Spring,驗證與授權部分
在web頁面中獲取用戶身份
在web頁面中應用安全標簽庫
實現方法級安全
6、配置web.xml
7、Spring配置文件中設置命名空間
8、通過數據庫驗證用戶身份
9、完善web頁面驗證規則
10、自定義驗證配置
11、本地化消息輸出(國際化)
????
根據公司項目的開發要求和集合spring?security3.0功能,公司將通過數據庫進行對用戶身份驗證和授權,系統將建立5個基礎表進行對權利的管理。
?
第一部分?數據庫設計
1、表設計
表1:用戶表(pub_users)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | User_Id | Vchar(32) | 用戶id | PK |
| 2 | user_account | Vchar(30) | 登陸用戶名(登陸號) | ? |
| 3 | User_name | Vchar(40) | 用戶姓名 | ? |
| 4 | user_Password | Vchar(100) | 用戶密碼 | ? |
| 5 | Enabled | Int | 是否被禁用 | 0禁用1正常 |
| 6 | isSys | Int | 是否是超級用戶 | 0非1是 |
| 7 | user_DESc | Vchar(100) | 描述 | ? |
| 說明:pub_users表中的登錄名和密碼用來控制用戶的登錄。 | ||||
表2:權限表(pub_authorities)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | authority_Id | Vchar(32) | 權限id | PK |
| 2 | Authority_name | Vchar(40) | 權限名稱 | ? |
| 3 | Authority_DESc | Vchar(100) | 權限描述 | ? |
| 4 | Enabled | Int | 是否被禁用 | 0禁用1正常 |
| 5 | isSys | Int | 是否是超級權限 | 0非1是 |
| 說明:pub_authorities表中描述的是系統擁有哪些權限,如果要詳細分類,可以將一個url定義一個權限,那樣就能對所有資源進行管理。 | ||||
表3:角色表(pub_roles)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | role_Id | Vchar(32) | 角色id | PK |
| 2 | role_name | Vchar(100) | 角色名稱 | ? |
| 3 | role_DESc | Vchar(100) | 角色描述 | ? |
| 4 | Enabled | Int | 是否被禁用 | 0禁用1正常 |
| 5 | isSys | Int | 是否是超級權限 | 0非1是 |
| 說明:pub_roles表中描述的是系統按用戶分類或按照功能模塊分類,將系統進行整合歸類管理。 | ||||
表4:資源表(pub_resources)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | resource_Id | Vchar(32) | 資源id | PK |
| 2 | resource_name | Vchar(100) | 資源名稱 | ? |
| 3 | resource?_type | Vchar(40) | 資源類型 | url、method |
| 4 | priority | int | 資源優先權 | 即排序 |
| 5 | resource?_string | Vchar(200) | 資源鏈接 | ? |
| 6 | resource_DESc | Vchar(100) | 資源描述 | ? |
| 7 | Enabled | Int | 是否被禁用 | 0禁用1正常 |
| 8 | isSys | Int | 是否是超級權限 | 0非1是 |
| 說明:pub_roles表中描述的是系統需要保護的資源及(url或方法)。 | ||||
以上四個表是權限管理的基礎表(用戶表、權限表、角色表、資源表)。
?
表5:用戶角色連接表(pub_users_roles)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | Id | Indetity | Id主鍵 | PK |
| 2 | user_Id | Vchar(32) | 用戶id | ? |
| 3 | role_id | Vchar(32) | 角色id | ? |
| 說明:用來管理用戶和角色的關系。 | ||||
表6:角色權限連接表(pub_roles_authorities)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | Id | Indetity | Id主鍵 | PK |
| 2 | role?_Id | Vchar(32) | 角色id | ? |
| 3 | authority_Id | Vchar(32) | 權限id | ? |
| 說明:用來管理角色和權限的關系。 | ||||
表7:權限資源連接表(pub_authorities_resources)
| 序號 | 字段 | 類型 | 含義 | 備注 |
| 1 | Id | Indetity | Id主鍵 | PK |
| 2 | authority_Id | Vchar(32) | 權限id | ? |
| 3 | resource_Id | Vchar(32) | 資源id | ? |
| 說明:用來管理角色和權限的關系。 | ||||
2、建表語句如下(數據庫采用MS?SQL?2000):
create?table?pub_users(
????user_id?varchar(32),
?user_account?varchar(30),
?user_name?varchar(40),
?user_password?varchar(100),
?user_desc?varchar(100),
?enabled?int,
?issys?int
);
alter?table?pub_users?add?constraint?pk_pub_users?primary?key(user_id);
?
create?table?pub_authorities(
??authority_id?varchar(32),
? ?authority_name?varchar(40),?
?authority_desc?varchar(100),
?enabled?int,
?issys?int
);
alter?table?pub_authorities?add?constraint?pk_pub_authorities?primary?key(authority_id);
?
create?table?pub_roles(
??role_id?varchar(32),
? ?role_name?varchar(40),?
?role_desc?varchar(100),
?enabled?int,
?issys?int
);
alter?table?pub_roles?add?constraint?pk_pub_roles?primary?key(role_id);
?
create?table?pub_resources(
??resource_id?varchar(32),
? ?resource_name?varchar(100),?
?resource_desc?varchar(100),
? ?resource_type?varchar(40),?
?resource_string?varchar(200),
?priority?int,
?enabled?int,
?issys?int
);
alter?table?pub_resources?add?constraint?pk_pub_resources?primary?key(resource_id);
?
create?table?pub_users_roles(
? ?id?numeric(12,0)?IDENTITY?NOT?NULL,?
? ?user_id?varchar(32),?
?role_id?varchar(32),
?enabled?int
);
alter?table?pub_users_roles?add?constraint?pk_pub_users_roles?primary?key(id);
alter?table?pub_users_roles?add?constraint?fk_users_roles_users?foreign?key(user_id)?references?pub_users(user_id);
alter?table?pub_users_roles?add?constraint?fk_users_roles_roles?foreign?key(role_id)?references?pub_roles(role_id);
?
?
create?table?pub_roles_authorities(
? ?id?numeric(12,0)?IDENTITY?NOT?NULL,?
?role_id?varchar(32),
? ?authority_id?varchar(32),?
?enabled?int
);
alter?table?pub_roles_authorities?add?constraint?pk_pub_roles_authorities?primary?key(id);
alter?table?pub_roles_authorities?add?constraint?fk_pub_roles_authorities_authorities?foreign?key(authority_id)?references?pub_authorities(authority_id);
alter?table?pub_roles_authorities?add?constraint?fk_pub_roles_authorities_roles?foreign?key(role_id)?references?pub_roles(role_id);
?
create?table?pub_authorities_resources(
? ?id?numeric(12,0)?IDENTITY?NOT?NULL,?
? ?authority_id?varchar(32),?
?resource_id?varchar(32),
?enabled?int
);
alter?table?pub_authorities_resources?add?constraint?pk_pub_authorities_resources?primary?key(id);
alter?table?pub_authorities_resources?add?constraint?fk_pub_authorities_resources_authorities?foreign?key(authority_id)?references?pub_authorities(authority_id);
alter?table?pub_authorities_resources?add?constraint?fk_pub_authorities_resources_resources?foreign?key(resource_id)?references?pub_resources(resource_id);
?
3、E-R圖如下:
?
?
第二部分?WEB數據庫整合
提示:相關代碼請參考項目模塊
1、將數據庫表結構和Hibernate建立映射,本系統采用annotation進行對數據庫進行零配置處理(請參考hibernate映射),如圖。
?
2、建立權限的Dao層。
?
3、建立權限的Service層
?
4、配置web.xml
???<?xml?version="1.0"?encoding="UTF-8"?>
<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">
?
<display-name>rstframe</display-name>
?
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>rstframe.root</param-value>
</context-param>
?
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
?
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
?
<!--?Spring?ApplicationContext配置文件的路徑,可使用通配符,多個路徑用,號分隔
此參數用于后面的Spring?Context?Loader?-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:/applicationContext.xml,
classpath*:/applicationContext-rstframe.xml
</param-value>
</context-param>
?
<!--?Character?Encoding?filter?-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>
org.springframework.web.filter.CharacterEncodingFilter
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
?
<!--?SpringSide's?Hibernate?Open?Session?In?View?filter-->
<filter>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<filter-class>
com.rstco.frame.modules.orm.hibernate.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>excludeSuffixs</param-name>
<param-value>js,css,jpg,gif</param-value>
</init-param>
</filter>
?
<filter-mapping>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
?
<!--?SpringSecurity?filter-->
????<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?filter,?actionPackages?-->
<filter>
<filter-name>struts2Filter</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
? <!--Spring的ApplicationContext?載入?-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.util.Log4jConfigListener
</listener-class>
</listener>
<!--?Spring?刷新Introspector防止內存泄露?-->
<listener>
<listener-class>
org.springframework.web.util.IntrospectorCleanupListener
</listener-class>
</listener>
<!--??防止多人登陸?,控制一個用戶只能登錄一次,不能在其他地方重新登錄-->
?? <listener>
<listener-class>
org.springframework.security.web.session.HttpSessionEventPublisher?
</listener-class>
</listener>
?
<!--?session超時定義,單位為分鐘?-->
<session-config>
<session-timeout>20</session-timeout>
</session-config>
?
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
?
<!--?error?page?-->
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/common/500.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/common/500.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/common/404.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/common/403.jsp</location>
</error-page>
?
<jsp-config>
<taglib>
<taglib-uri>/WEB-INF/struts-menu-el.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/struts-menu-el.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-menu.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/struts-menu.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/c.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/c.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/fmt.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/fmt.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/fn.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/fn.tld</taglib-location>
</taglib>
<!--loushang?tld-->
<taglib>
<taglib-uri>/WEB-INF/web-date.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-date.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-flex.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-flex.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-graph.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-graph.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-grid.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-grid.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-html.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-html.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-list.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-list.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-loushang.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-loushang.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-menu.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-menu.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-multitab.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-multitab.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-seltree.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-seltree.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-tab.tld</taglib-uri>
<taglib-location>/WEB-INF/tlds/web-tab.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-tree.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-tree.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-widgets.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-widgets.tld
</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/web-i18n.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/web-i18n.tld
</taglib-location>
</taglib>
<!--?loushang?end -->
<taglib>
<taglib-uri>/WEB-INF/gystudio.tld</taglib-uri>
<taglib-location>
/WEB-INF/tlds/gystudio.tld
</taglib-location>
</taglib>
</jsp-config>
?
<mime-mapping>
<extension>rar</extension>
<mime-type>application/rar</mime-type>
</mime-mapping>
?
</web-app>
5、配置spring?security3.0中的xml文件
???文件名:applicationContext-security.xml
<?xml?version="1.0"?encoding="UTF-8"?>
<beans:beans?xmlns="http://www.springframework.org/schema/security"
????xmlns:beans="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">
?
<beans:description>SpringSecurity安全配置</beans:description>
?
<!--?http安全配置?-->
? ?<http?auto-config="true">
<intercept-url?pattern="/css/**"?filters="none"?/>
<intercept-url?pattern="/images/**"?filters="none"?/>
<intercept-url?pattern="/js/**"?filters="none"?/>
<intercept-url?pattern="/login.jsp"?filters="none"?/>
<!--
<intercept-url?pattern="/index.jsp"??access="ROLE_USER"/>
<intercept-url?pattern="/main.jsp"??access="ROLE_ADAMIN"/>
????-->
<form-login?login-page="/login.jsp"?default-target-url="/index.jsp"
?authentication-failure-url="/login.jsp?error=1"?/>
<!--?嘗試訪問沒有權限的頁面時跳轉的頁面?-->???
<access-denied-handler?error-page="/common/403.jsp"/>?
?
<logout?logout-success-url="/login.jsp"?/>
?
?<session-management>
???????? <concurrency-control?max-sessions="1"?error-if-maximum-exceeded="true"?/>
??? ?</session-management>
?
<!--?增加一個filter,這點與Acegi是不一樣的,不能修改默認的filter了,
這個filter位于FILTER_SECURITY_INTERCEPTOR之前??-->
?????????<custom-filter?ref="myFilter"?before="FILTER_SECURITY_INTERCEPTOR"/>
???????
?</http>
?
<!--?一個自定義的filter,必須包含authenticationManager,accessDecisionManager,securityMetadataSource三個屬性,
???? 我們的所有控制將在這三個類中實現,解釋詳見具體配置??-->
????<beans:bean?id="myFilter"?class="com.rstco.frame.pub.security.interceptor.MyFilterSecurityInterceptor">
????????<beans:property?name="authenticationManager"
????????????ref="authenticationManager"?/>
????????<beans:property?name="accessDecisionManager"
????????????ref="myAccessDecisionManagerBean"?/>
????????<beans:property?name="securityMetadataSource"
????????????ref="mySecurityMetadataSource"?/>
????</beans:bean>
???
<!--?驗證配置?,?認證管理器,實現用戶認證的入口,主要實現UserDetailsService接口即可?-->
? <authentication-manager?alias="authenticationManager">?
? ?
<authentication-provider?user-service-ref="userDetailsService">
???<!--
<s:password-encoder?hash="sha"?/>
?-->
</authentication-provider>
?
</authentication-manager>
?
<!--?項目實現的用戶查詢服務,將用戶信息查詢出來??-->
<beans:bean?id="userDetailsService"?class="com.rstco.frame.pub.security.support.MyUserDetailService"?/>
?
<!--?訪問決策器,決定某個用戶具有的角色,是否有足夠的權限去訪問某個資源?????-->
????<beans:bean?id="myAccessDecisionManagerBean"
????????class="com.rstco.frame.pub.security.support.MyAccessDecisionManager">
????</beans:bean>
?
????<!--?資源源數據定義,將所有的資源和權限對應關系建立起來,即定義某一資源可以被哪些角色訪問? -->
????<beans:bean?id="mySecurityMetadataSource"
????????class="com.rstco.frame.pub.security.support.MyInvocationSecurityMetadataSourceService">
????</beans:bean>
????
? ????
????<!--?定義國際化?-->
????<beans:bean?id="messageSource"
??? ?class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
? ?<beans:property?name="basename"?
? ? value="classpath:org/springframework/security/messages_zh_CN"/>
</beans:bean>
</beans:beans>
?
?
第三部分?SS3.0的實現
這是項目的主體部分:
?
這四個類說明如下。
一、?用來獲得用戶驗證信息(MyUserDetailService)
代碼如下:
package?com.rstco.frame.pub.security.support;
?
import?java.util.ArrayList;
import?java.util.Collection;
import?java.util.List;
?
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.UserDetails;
import?org.springframework.security.core.userdetails.UserDetailsService;
import?org.springframework.security.core.userdetails.UsernameNotFoundException;
import?org.springframework.stereotype.Service;
?
import?com.rstco.frame.pub.security.dao.PubAuthoritiesResourcesDao;
import?com.rstco.frame.pub.security.dao.PubUsersDao;
import?com.rstco.frame.pub.security.entity.PubAuthorities;
import?com.rstco.frame.pub.security.entity.PubAuthoritiesResources;
?
//你就可以從數據庫中讀入用戶的密碼,角色信息,是否鎖定,賬號是否過期
@Service
public?class?MyUserDetailService?implements?UserDetailsService??{
@Autowired
private?PubUsersDao?pubUsersDao;
@Autowired
private?PubAuthoritiesResourcesDao?pubAuthoritiesResourcesDao;
?
public?UserDetails?loadUserByUsername(String?username)
throws?UsernameNotFoundException,?DataAccessException?{
?
Collection<GrantedAuthority>?auths=new?ArrayList<GrantedAuthority>();
//取得用戶的權限
List<PubAuthorities>?auth=pubUsersDao.findAuthByUserName(username);
String?password=null;
//取得用戶的密碼
password=pubUsersDao.findUserByname(username).get(0).getUserPassword();
?
List<PubAuthoritiesResources>?aaa=pubAuthoritiesResourcesDao.getAll();
?
????????User?user?=?new?User(username,
???????? password,?true,?true,?true,?true,?auths);
????????
????????return?user;
}
?
}
二、?最核心的地方,就是提供某個資源對應的權限定義,取得所有角色(auth)的對應資源數據(MyInvocationSecurityMetadataSourceService)
代碼如下:?
package?com.rstco.frame.pub.security.support;
?
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?javax.servlet.ServletContext;
?
import?org.hibernate.Query;
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.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?com.rstco.frame.modules.orm.hibernate.HibernateDao;
import?com.rstco.frame.pub.security.dao.PubAuthoritiesResourcesDao;
import?com.rstco.frame.pub.security.entity.PubAuthorities;
import?com.rstco.frame.pub.security.entity.PubResources;
?
/*
?*?
?*?最核心的地方,就是提供某個資源對應的權限定義,即getAttributes方法返回的結果。
?*?注意,我例子中使用的是AntUrlPathMatcher這個path?matcher來檢查URL是否與資源定義匹配,
?*?事實上你還要用正則的方式來匹配,或者自己實現一個matcher。
?*?
?*?此類在初始化時,應該取到所有資源及其對應角色的定義
?*?
?*?說明:對于方法的spring注入,只能在方法和成員變量里注入,
?*?如果一個類要進行實例化的時候,不能注入對象和操作對象,
?*?所以在構造函數里不能進行操作注入的數據。
?*/
@Service
public?class?MyInvocationSecurityMetadataSourceService??implements
FilterInvocationSecurityMetadataSource?{
?
????@Autowired
private?PubAuthoritiesResourcesDao?pubAuthoritiesResourcesDao;
?
private?UrlMatcher?urlMatcher?=?new?AntUrlPathMatcher();
private?static?Map<String,?Collection<ConfigAttribute>>?resourceMap?=?null;
?
public?MyInvocationSecurityMetadataSourceService()?{
loadResourceDefine();
}
?
/* ???private?void?loadResourceDefine()?{
????????resourceMap?=?new?HashMap<String,?Collection<ConfigAttribute>>();
????????Collection<ConfigAttribute>?atts?=?new?ArrayList<ConfigAttribute>();
????????ConfigAttribute?ca?=?new?SecurityConfig("ROLE_ADMIN");
????????atts.add(ca);
????????resourceMap.put("/index.jsp",?atts);
????????resourceMap.put("/i.jsp",?atts);
????}*/
?
private?void?loadResourceDefine()?{
ApplicationContext?context?=?new?ClassPathXmlApplicationContext("applicationContext.xml");
SessionFactory?sessionFactory?=?(SessionFactory)context.getBean("sessionFactory");
?
Session?session?=?sessionFactory.openSession();
List<String>?query=session.createSQLQuery("select?authority_name?from?pub_authorities?").list();
?
?
resourceMap?=?new?HashMap<String,?Collection<ConfigAttribute>>();
Collection<ConfigAttribute>?atts?=?new?ArrayList<ConfigAttribute>();
?
//List<PubAuthorities>?auths?=session.createQuery(arg0);?//pubAuthoritiesResourcesDao.findAuthAll();
?
for?(String?auth?:?query)?{
ConfigAttribute?ca?=?new?SecurityConfig(auth);//?"ROLE_ADMIN"
//?atts.add(ca);
?
List<String>?query1=session.createSQLQuery("select?resource_string?"?+
"from?Pub_Authorities_Resources,Pub_Resources,??Pub_authorities?"?+
"where?Pub_Authorities_Resources.resource_id=Pub_Resources.resource_id?and?"?+
"?Pub_Authorities_Resources.resource_id=Pub_authorities.authority_id??and?"?+
"???Authority_name='"+auth+"'").list();
?
for?(String?res?:?query1)?{
String?url?=?res;
//?判斷資源文件和權限的對應關系,如果已經存在,要進行增加
if?(resourceMap.containsKey(url))?{
Collection<ConfigAttribute>?value?=?resourceMap.get(url);
value.add(ca);
resourceMap.put(url,?value);
//?"log.jsp","role_user,role_admin"
}?else?{
atts.add(ca);
resourceMap.put(url,?atts);
}
?resourceMap.put(url,?atts);
}
}
}
?
//?According?to?a?URL,?Find?out?permission?configuration?of?this?URL.
public?Collection<ConfigAttribute>?getAttributes(Object?object)
throws?IllegalArgumentException?{
//?guess?object?is?a?URL.
String?url?=?((FilterInvocation)?object).getRequestUrl();
Iterator<String>?ite?=?resourceMap.keySet().iterator();
while?(ite.hasNext())?{
String?resURL?=?ite.next();
if?(urlMatcher.pathMatchesUrl(url,?resURL))?{
return?resourceMap.get(resURL);
}
}
return?null;
}
?
public?boolean?supports(Class<?>?clazz)?{
return?true;
}
public?Collection<ConfigAttribute>?getAllConfigAttributes()?{
return?null;
}
}
三、?最重要的是decide方法,如果不存在對該資源的定義,直接放行;否則,如果找到正確的角色,即認為擁有權限,并放行,否則throw?new?AccessDeniedException("no?right");這樣,就會進入上面提到的403.jsp頁面。(MyAccessDecisionManager)
代碼如下:
?
package?com.rstco.frame.pub.security.support;
?
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;
?
?
public?class?MyAccessDecisionManager?implements?AccessDecisionManager?{
?
????//In?this?method,?need?to?compare?authentication?with?configAttributes.
????//?1,?A?object?is?a?URL,?a?filter?was?find?permission?configuration?by?this?URL,?and?pass?to?here.
????//?2,?Check?authentication?has?attribute?in?permission?configuration?(configAttributes)
????//?3,?If?not?match?corresponding?authentication,?throw?a?AccessDeniedException.
????public?void?decide(Authentication?authentication,?Object?object,
????????????Collection<ConfigAttribute>?configAttributes)
????????????throws?AccessDeniedException,?InsufficientAuthenticationException?{
????????if(configAttributes?==?null){
????????????return?;
????????}
????????System.out.println(object.toString());??//object?is?a?URL.
????????Iterator<ConfigAttribute>?ite=configAttributes.iterator();
????????while(ite.hasNext()){
????????????ConfigAttribute?ca=ite.next();
????????????String?needRole=((SecurityConfig)ca).getAttribute();
????????????for(GrantedAuthority?ga:authentication.getAuthorities()){
????????????????if(needRole.equals(ga.getAuthority())){??//ga?is?user's?role.
????????????????????return;
????????????????}
????????????}
????????}
????????throw?new?AccessDeniedException("no?right");
????}
?
????public?boolean?supports(ConfigAttribute?attribute)?{
????????//?TODO?Auto-generated?method?stub
????????return?true;
????}
?
????public?boolean?supports(Class<?>?clazz)?{
????????return?true;
????}
?
?
}
四、?這個過濾器要插入到授權之前。最核心的代碼就是invoke方法中的InterceptorStatusToken?token?=?super.beforeInvocation(fi);這一句,即在執行doFilter之前,進行權限的檢查,而具體的實現已經交給accessDecisionManager了(MyFilterSecurityInterceptor)
代碼如下:
package?com.rstco.frame.pub.security.interceptor;
?
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.beans.factory.annotation.Autowired;
import?org.springframework.security.access.AccessDecisionManager;
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;
?
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)?{
System.out.println("abc=======================edf");
this.securityMetadataSource?=?securityMetadataSource;
}
public?void?destroy()?{
//?TODO?Auto-generated?method?stub
?
}
public?void?init(FilterConfig?filterconfig)?throws?ServletException?{
//?TODO?Auto-generated?method?stub
}
}
總結
以上是生活随笔為你收集整理的Jsp Spring Security 权限管理系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 塞尔达马鞍怎么用 为什么游戏《塞尔达
- 下一篇: uu加速器如何免费(网易uu加速器)