1. 程式人生 > >【Spring Security實戰系列】Spring Security實戰(三)

【Spring Security實戰系列】Spring Security實戰(三)

Spring Security實戰(二)中講解了用Spring Security自帶的預設資料庫儲存使用者和許可權的資料,但是Spring Security預設提供的表結構太過簡單了,其實就算預設提供的表結構很複雜,也不一定能滿足專案對使用者資訊和許可權資訊管理的要求。那麼接下來就講解如何自定義資料庫實現對使用者資訊和許可權資訊的管理。 一 自定義表結構 這裡還是用的mysql資料庫,所以pom.xml檔案都不用修改。這裡只要新建三張表即可,user表、role表、user_role表。其中user使用者表,role角色表為儲存使用者許可權資料的主表,user_role為關聯表。user使用者表,role角色表之間為多對多關係,就是說一個使用者可以有多個角色。建表語句並插入資料:
- - 角色  
create table role(  
    id bigint,  
    `name` varchar(50),  
    descn varchar(200)  
);  
alter table role add constraint pk_role primary key(id);  
- - alter table role alter column id int generated by default as identity(1, 1); 
  
- - 使用者  
create table `user`(  
    id bigint,  
    username varchar(50),  
    `password` varchar(50),  
    `status` integer,  
    descn varchar(200)  
);  
alter table `user` add constraint pk_user primary key(id);  
- - alter table `user` alter column id bigint generated by default as identity(start with 1);  
  
- - 使用者角色連線表  
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-security.xml) 現在我們要在這樣的資料結構基礎上使用Spring Security,Spring Security所需要的資料無非就是為了處理兩種情況,一是判斷登入使用者是否合法,二是判斷登陸的使用者是否有許可權訪問受保護的系統資源。因此我們所要做的工作就是在現有資料結構的基礎上,為Spring Security提供這兩種資料。 在jdbc-user-service標籤中有這樣兩個屬性: 1. users-by-username-query為根據使用者名稱查詢使用者,系統通過傳入的使用者名稱查詢當前使用者的登入名,密碼和是否被禁用這一狀態。
2.authorities-by-username-query為根據使用者名稱查詢許可權,系統通過傳入的使用者名稱查詢當前使用者已被授予的所有許可權。 所以 users-by-username-query屬性要的是通過username來查詢使用者名稱、密碼和是否可用;authorities-by-username-query屬性是通過username來查詢使用者許可權,所以在我們自定義的表結構的基礎上對sql語句進行修改,得到如下配置:
<!-- 預設資料庫對使用者進行儲存 Spring Security預設情況下需要兩張表,使用者表和許可權表。-->
    <authentication-manager>
        <authentication-provider>
            <jdbc-user-service data-source-ref="mysqlDataSource"
                  users-by-username-query="select username,`password`,`status` as enabled from `user` where username = ?"
                  authorities-by-username-query="select `user`.username,role.`name` from `user`,role,user_role where `user`.id=user_role.user_id and user_role.role_id=role.id and `user`.username = ?" />

        </authentication-provider>
    </authentication-manager>

這樣最終得到的配置檔案如下:

<?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"
             xmlns:sec="http://www.springframework.org/schema/security"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-3.1.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
                        http://www.springframework.org/schema/security
                        http://www.springframework.org/schema/security/spring-security.xsd">


    <!-- 配置不過濾的資源(靜態資源及登入相關).是忽略攔截某些資源的意思,主要是針對靜態資源 -->
    <http pattern="/**/*.css" security="none"></http>
    <http pattern="/**/*.jpg" security="none"></http>
    <http pattern="/**/*.jpeg" security="none"></http>
    <http pattern="/**/*.gif" security="none"></http>
    <http pattern="/**/*.png" security="none"></http>
    <http pattern="/js/*.js" security="none"></http>

    <http pattern="/login.jsp" security="none"></http>
    <http pattern="/getCode" security="none" /><!-- 不過濾驗證碼 -->
    <http pattern="/test/**" security="none"></http><!-- 不過濾測試內容 -->

    <http auto-config="true">
        <!-- 表示訪問app.jsp時,需要ROLE_SERVICE許可權 -->
        <intercept-url pattern="/adminPage.jsp" access="hasRole('ROLE_ADMIN')"></intercept-url>
        <!--表示訪問任何資源都需要ROLE_ADMIN許可權。-->
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')"></intercept-url>
    </http>

    <!-- 匯入資料來源 -->
    <beans:import resource="applicationContext-dataSource.xml"></beans:import>

    <!-- 預設資料庫對使用者進行儲存 Spring Security預設情況下需要兩張表,使用者表和許可權表。-->
    <authentication-manager>
        <authentication-provider>
            <jdbc-user-service data-source-ref="mysqlDataSource"
                  users-by-username-query="select username,`password`,`status` as enabled from `user` where username = ?"
                  authorities-by-username-query="select `user`.username,role.`name` from `user`,role,user_role where `user`.id=user_role.user_id and user_role.role_id=role.id and `user`.username = ?" />

        </authentication-provider>
    </authentication-manager>
</beans:beans>

和配置(如applicationContext.xml、pplicationContext-dataSource.xml、logback.xml、datasource.properties)和前面的實戰二(Spring Security實戰(二))完全一樣,請參考前面的實戰吧!

三 結果 由於只是換了使用者資訊和許可權資訊儲存的方式,其他的都沒有改變,效果和實戰一的效果是一樣的