JspSpringSecurity許可權管理系統
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
}
}
本文轉自農夫山泉別墅部落格園部落格,原文連結:http://www.cnblogs.com/yaowen/archive/2013/03/28/2985852.html,如需轉載請自行聯絡原作者
相關文章
- 【JavaWeb】許可權管理系統JavaWeb
- 企業許可權管理系統
- Winner許可權管理系統3.0
- OA管理系統,有哪些許可權管理?
- Oracle的物件許可權、角色許可權、系統許可權Oracle物件
- 使用者許可權系統管理
- Vue2.0 + ElementUI 手寫許可權管理系統後臺模板(二)——許可權管理VueUI
- 基於RBAC的許可權管理系統
- 有效管理Windows系統帳戶許可權Windows
- Android系統許可權和root許可權Android
- SpringSecurity許可權管理系統實戰—九、資料許可權的配置SpringGse
- 許可權系統:一文搞懂功能許可權、資料許可權
- MySQL許可權系統MySql
- Oracle系統許可權Oracle
- Oracle 使用者、物件許可權、系統許可權Oracle物件
- Linux命令-使用者、許可權管理、系統管理Linux
- 許可權系統:許可權應用服務設計
- 基於tp3.2.3開發的許可權管理系統,路由,微信,cdn,許可權路由
- 使用者許可權設計(三)——通用資料許可權管理系統設計
- Confluence6對比系統管理員許可權和Confluence管理員許可權
- mongodb 的許可權系統MongoDB
- 有贊許可權系統
- Android系統許可權Android
- 許可權系統設計
- 許可權系統跟進
- Linux-許可權管理(ACL許可權)Linux
- 作業系統---IO許可權管理和敏感指令作業系統
- Juniper裝置系統安全許可權管理評估
- Java寫圖書管理系統(四、管理員功能許可權)Java
- 許可權系統:6個許可權概念模型設計模型
- 許可權系統:許可權應用服務設計Tu
- PostgreSQL:許可權管理SQL
- Mysql——許可權管理MySql
- Mysql 許可權管理MySql
- oracle 許可權管理Oracle
- 4、許可權管理
- sql許可權管理SQL
- 許可權管理策略