今天要介紹Spring Security最後一個主題,JDBC User Service,透過Spring security提供的query方法以及建議Table Schema來驗證使用者,其實在前面我們在實作UserDetailsService的時候也是在作類似的事,只是透過更複雜的ORM以及UserDetailsService coding,只是Spring Security提供的JDBC User Service設定比較簡單,寫的程式碼也少很多,首先需要加入相關的Dependency
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
<scope>compile</scope>
</dependency>
<properties>
<spring.version>4.1.1.RELEASE</spring.version>
</properties>
Spring Spring建議的建立兩個table,一個user table,一個authorities table,user table之前已經建立,即原本的dneuser table,authorities table schema如下,我是用Navicat Execute SQL File。
CREATE TABLE `authorities` (
`username` varchar(100) NOT NULL,
`authority` varchar(50) NOT NULL,
UNIQUE KEY `ix_auth_username` (`username`,`authority`),
CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `dneuser` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
authorities跟dneuser table的username 是一對一的關係,dneuser裡面本來就有user的資料,現在要補authorities table資料,sql語法如下,在透過Navicat execute SQL File後即可新增資料到該table
INSERT INTO `authorities` VALUES ('admin', 'ROLE_ADMIN');
INSERT INTO `authorities` VALUES ('admin', 'ROLE_USER');
INSERT INTO `authorities` VALUES ('John', 'ROLE_USER');
INSERT INTO `authorities` VALUES ('Patrick', 'ROLE_USER');<img src="http://ithelp.ithome.com.tw/upload/images/20141028/20141028205241544f919945cea_resize_600.png" style="height:317px; width:508px"></img>
注意的是,如果一個user有多個role,就要每一個role都要一筆資料。
接著更新SecurityConfig,將原本的UserDetailsService註解掉,換成jdbcAuthentication並需要指定datasource,DataSource用@Autowired BoneCP dataSource即可輕鬆解決,接著是要設定Query方法:usersByUsernameQuery及authoritiesByUsernameQuery,參數為Query username的sql語法,是官方建議的寫法,最後密碼加密的部分不能註解掉,不然jdbcAuthentication會不認得原本之前已經註冊的使用者加密後的密碼。
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private BoneCPDataSource dataSource;
........
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
// TODO Auto-generated method stub
auth //Builder Design Pattern
.jdbcAuthentication().dataSource(dataSource) //要指定datasource
.usersByUsernameQuery("select username,password, enabled from dneuser where username=?")
.authoritiesByUsernameQuery("select username, authority from authorities where username=?")
// .userDetailsService(dneUserDetailsService) //換成userDetailsService
.passwordEncoder(new BCryptPasswordEncoder()); //密碼加密
}
啟動Server來測試jdbcAuthentication coding是否正確以及原本的使用者權限是否跟之前使用DneUserDetailsService一樣
先以Patrick登入,成功登入畫面如下
點選User List,只有admin可以存取,故出現Customized Access Denied網頁
存取DCN List,出現的紀錄也是篩選過的
修改DefaultController、DneUserRepository及User List.jsp將Authorities資料顯示在網頁上,以admin登入,User List可以存取,畫面如下
如果要新增使用者,則表單要重新設計,要將user對應的authority寫進資料庫,另外DAO也要修改,這方面就不在贅述,Spring Security本身就是個蠻複雜的專案,Spring Security還有所多進階功能未介紹,如Access Control List (ACL)以及Spring OAuth,還有Session management等,希望有機會再跟大家分享。明日就是個人 IT鐵人賽最後一天,想以簡單介紹Spring Boot作個結尾。