到目前為此,都是使用 inMemoryAuthentication
作為驗證授權的資料來源,當然,你可以採用其他的來源,在這邊先談一下基本的 JDBC 存取資料庫,最簡單的方式就是呼叫 AuthenticationManagerBuilder
的 jdbcAuthentication
,設定 DataSource
、使用者資料查詢 SQL 以及角色查詢 SQL:
package cc.openhome.web;
...略
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
.passwordEncoder(new BCryptPasswordEncoder())
.dataSource(dataSource())
.usersByUsernameQuery("select name, password, enabled from t_account where name=?")
.authoritiesByUsernameQuery("select name, role from t_account_role where name=?");
}
... 略
@Bean(destroyMethod="shutdown")
public DataSource dataSource(){
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:db.sql")
.build();
}
... 略
}
使用者資料查詢 SQL 主要必須取得名稱、密碼與是否可用三個欄位,而角色查詢必須取得名稱與角色對應兩個欄位,這麼一來 Spring Security 就能夠進行驗證與授權了,為此,你可以如下建立表格以及測試用的資料(為 db.sql 的部份內容):
CREATE TABLE t_account (
name VARCHAR(15) NOT NULL,
password VARCHAR(64) NOT NULL,
enabled TINYINT NOT NULL,
PRIMARY KEY (name)
);
CREATE TABLE t_account_role (
name VARCHAR(15) NOT NULL,
role VARCHAR(15) NOT NULL,
PRIMARY KEY (name, role)
);
INSERT INTO t_account(name, password, enabled) VALUES ('admin','$2a$10$PUFa4u8d434aWitf87scE.vue580tghpCU6JdPnDXQgjK1q0Ddtgu', 1);
INSERT INTO t_account(name, password, enabled) VALUES ('caterpillar','$2a$10$yh5WJetawp2KloUtEoVzRuT4/WEeR5BhPdfRZGoAvnCtKAbFBP8Sa', 1);
INSERT INTO t_account_role (name, role) VALUES ('admin', 'ROLE_ADMIN');
INSERT INTO t_account_role (name, role) VALUES ('admin', 'ROLE_MEMBER');
INSERT INTO t_account_role (name, role) VALUES ('caterpillar', 'ROLE_MEMBER');
由於使用的 PasswordEncoder
實作為 BCryptPasswordEncoder
,因此密碼資料的部份是經過 BCryptPasswordEncoder
的 encode
方法編碼過的結果,admin
的密碼原本是 admin12345678
,而 caterpillar
的密碼原本是 12345678
。
當然,如果是從既有專案重構而來,資料庫表格或者是驗證方式等,未必可以符合以上的設計,或者是有些情境下的驗證與授權更為複雜,這些情況下,可以透過實作 UserDetailsService
或 AuthenticationProvider
來實作更有彈性的驗證與授權,這留著之後,試著在 gossip 專案上套用 Spring Security 再來說明。
你可以在 JdbcAuth 找到以上的範例專案。