上面的一個 Spring Security 的 demo 雖然使用了數據庫來實現權限的控制,但是對於在項目中的應用來說這樣的表結構過於簡單,遠遠無法滿足我們的需求。現在來實現自定義數據表從而達到權限的控制。下面給出創建自定義數據表的SQL(MySQL)語句。
SQL語句:
-- 角色
create table role(
id bigint,
name varchar(50),
descn varchar(200)
);
ALTER TABLE `role` MODIFY COLUMN `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY (`id`);
-- 用戶
create table user(
id bigint,
username varchar(50),
password varchar(50),
status integer,
descn varchar(200)
);
ALTER TABLE `user` MODIFY COLUMN `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
ADD PRIMARY KEY (`id`);
-- 用戶角色連接表
create table user_role(
user_id bigint,
role_id bigint
);
alter table user_role add constraint pk_user_role primary key(user_id, role_id);
alter table user_role add constraint fk_user_role_user foreign key(user_id) references user(id);
alter table user_role add constraint fk_user_role_role foreign key(role_id) references role(id);
insert into user(id,username,password,status,descn) values(1,'admin','admin',1,'管理員');
insert into user(id,username,password,status,descn) values(2,'user','user',1,'用戶');
insert into role(id,name,descn) values(1,'ROLE_ADMIN','管理員角色');
insert into role(id,name,descn) values(2,'ROLE_USER','用戶角色');
insert into user_role(user_id,role_id) values(1,1);
insert into user_role(user_id,role_id) values(1,2);
insert into user_role(user_id,role_id) values(2,2);
如何通過Spring Security來讀取自己定義的表實現權限控制,下面給出applicationContext.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"> <!-- 指定被拒絕的頁面 --> <http auto-config='true' access-denied-page="/accessDenied.jsp"> <!-- login-page表示用戶登陸時顯示我們自定義的login.jsp authentication-failure-url表示用戶登陸失敗時,跳轉到哪個頁面,並添加一個error=true參數作爲登陸失敗的標示 default-target-url表示登陸成功時,跳轉到哪個頁面 --> <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?error=true" default-target-url="/index.jsp" /> <!--登錄頁面不進行過濾,後面加一個*那是因爲請求頁面後面會帶參數--> <intercept-url pattern="/login.jsp*" filters="none"/> <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" /> <intercept-url pattern="/**" access="ROLE_USER" /> <!-- 檢測失效的sessionId,超時時定位到另外一個URL --> <session-management invalid-session-url="/sessionTimeout.jsp" > <!-- 防止第二次登錄 如果想讓第一次登錄失效第二次登錄啓用則不要配置error-if-maximum-exceeded="true" --> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/> </session-management> </http> <authentication-manager> <authentication-provider> <!-- (1) users-by-username-query:根據條件用戶名查找用戶的:username,passwd和enabled狀態; (2) authorities-by-username-query: 根據條件用戶名查找用戶被授予的權限; --> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT username,password,status as enabled FROM user where username=?" authorities-by-username-query="select u.username,r.name as authority from user u join user_role ur on u.id=ur.user_id join role r on r.id=ur.role_id where u.username=?" /> </authentication-provider> </authentication-manager> <!-- 國際化 --> <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <!-- 如果不加載自己的國際化文件,去加載 Security 內部的國際化文件classpath:org/springframework/security/messages_zh_CN --> <beans:property name="basename" value="classpath:messages_zh_CN"/> </beans:bean> </beans:beans>
關鍵的配置在此:
<jdbc-user-service data-source-ref="dataSource" users-by-username-query="SELECT username,password,status as enabled FROM user where username=?" authorities-by-username-query="select u.username,r.name as authority from user u join user_role ur on u.id=ur.user_id join role r on r.id=ur.role_id where u.username=?" />
在上一個的例子基礎之上進行如下的配置,運行程序達到自定義user用戶表與role角色表,並通過兩張表的中間表進行關聯實現權限控制。