本章節(jié)的內(nèi)容為JDBC認(rèn)證忌栅,查找數(shù)據(jù)庫(kù)進(jìn)行驗(yàn)證扑庞,其中包括:
- 密碼加密策略(無(wú)密碼淡溯,簡(jiǎn)單加密读整,加鹽處理)
- 認(rèn)證策略(jdbc)
業(yè)務(wù)需求
在不同公司,可能有很多業(yè)務(wù)需求或者架構(gòu)不一樣導(dǎo)致我們實(shí)現(xiàn)驗(yàn)證的方式不一樣咱娶,那么cas為我們提供了很多認(rèn)證的模式(當(dāng)然也可以自定義)米间,其中常用的有:
- JDBC認(rèn)證
- LDAP認(rèn)證
- Basic認(rèn)證
- Shiro認(rèn)證
- Pac4j認(rèn)證
- MongoDB認(rèn)證
- Rest認(rèn)證
- IP黑白名單
還有可能交給第三方認(rèn)證,例如:微信膘侮、QQ屈糊、新浪等等
當(dāng)然也有一些公司或者企業(yè)也非常的變態(tài),如:
- 認(rèn)證中心不能直接訪問(wèn)賬號(hào)庫(kù)琼了,cas也提供功能逻锐,可以考慮用REST認(rèn)證模塊來(lái)處理這個(gè)事情
- 老系統(tǒng)賬號(hào)唯一性不確定夫晌,例如 組織+賬號(hào) 才是唯一值,這時(shí)候只能自定義認(rèn)證器(后面章節(jié)會(huì)有教程)
- 業(yè)務(wù)系統(tǒng)要求返回用戶密碼(多屬性返回/ClearPass)
加密方案
cas支持jdbc校驗(yàn)方案:
- 根據(jù)sql給予用戶名進(jìn)行查詢昧诱,根據(jù)密碼字段進(jìn)行鑒定(
select * from table_users where username=?
)可判斷有效等 - 通過(guò)鹽等手段進(jìn)行編碼加密再進(jìn)行匹配(推薦)
- 根據(jù)sql給予用戶名以及密碼進(jìn)行查詢(
select count(x) from tables_users where username = ? and password=?
)晓淀,不可判斷有效期,若數(shù)量大于0則成功 - 根據(jù)用戶名密碼連接數(shù)據(jù)庫(kù)盏档,原理是通過(guò)jdbc凶掰,若連接成功則成功
JDBC驗(yàn)證
采用mysql數(shù)據(jù)庫(kù)存儲(chǔ)用戶數(shù)據(jù)。
修改pom.xml
sso-server/pom.xml:
<!--新增支持jdbc驗(yàn)證-->
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc</artifactId>
<version>${cas.version}</version>
</dependency>
<!-- mysql驅(qū)動(dòng) 根據(jù)不同的數(shù)據(jù)庫(kù)使用不同驅(qū)動(dòng)-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.16</version>
</dependency>
<!--
若不想找驅(qū)動(dòng)可以直接寫下面的依賴即可蜈亩,其中包括
HSQLDB懦窘、Oracle、MYSQL稚配、PostgreSQL畅涂、MariaDB、Microsoft SQL Server
-->
<!--
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc-drivers</artifactId>
<version>${cas.version}</version>
</dependency>
-->
表結(jié)構(gòu)
sys_user:
create table sys_user
(
id int not null auto_increment,
username varchar(40),
password varchar(200),
expired int comment '1為過(guò)期 需要修改密碼',
disable int comment '1為不可用道川,禁用',
email varchar(200),
primary key (id)
);
CAS Authentication Credentials
根據(jù)sql給予用戶名進(jìn)行查詢午衰,根據(jù)密碼字段進(jìn)行鑒定(
select * from sys_user where username=?
)
程序新增配置
##
# CAS Authentication Credentials
#
#cas.authn.accept.users=casuser::Mellon
#Query Database Authentication 數(shù)據(jù)庫(kù)查詢校驗(yàn)用戶名開(kāi)始
#查詢賬號(hào)密碼sql,必須包含密碼字段
cas.authn.jdbc.query[0].sql=select * from sys_user where username=?
#指定上面的sql查詢字段名(必須)
cas.authn.jdbc.query[0].fieldPassword=password
#指定過(guò)期字段愤惰,1為過(guò)期苇经,若過(guò)期不可用
cas.authn.jdbc.query[0].fieldExpired=expired
#為不可用字段段,1為不可用宦言,需要修改密碼
cas.authn.jdbc.query[0].fieldDisabled=disabled
#數(shù)據(jù)庫(kù)方言hibernate的知識(shí)
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
#數(shù)據(jù)庫(kù)驅(qū)動(dòng)
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
#數(shù)據(jù)庫(kù)連接
cas.authn.jdbc.query[0].url=jdbc:mysql://localhost/sso?characterEncoding=utf8
#數(shù)據(jù)庫(kù)用戶名
cas.authn.jdbc.query[0].user=root
#數(shù)據(jù)庫(kù)密碼
cas.authn.jdbc.query[0].password=123456
#Query Database Authentication 數(shù)據(jù)庫(kù)查詢校驗(yàn)用戶名結(jié)束
以上配置,如驅(qū)動(dòng)商模,查詢數(shù)據(jù)庫(kù)等等需要根據(jù)不同的場(chǎng)景進(jìn)行調(diào)整
常用單向加密算法:MD5奠旺、SHA、HMAC施流。
一般我們常用的加密算法就這幾種响疚。在JDBC認(rèn)證中我們也可以選擇配置加密算法,加密算法一般為上面的三種瞪醋,MD5忿晕、SHA、HMAC银受,加密類型為NONE|DEFAULT|STANDARD|BCRYPT|SCRYPT|PBKDF2
這幾種践盼,我們?cè)谂渲梦募羞x擇加密類型,指定加密算法宾巍。
普通MD5加密配置
前面配置不變指定JDBC配置咕幻,后面的配置為密碼加密策略,配置如下:
#默認(rèn)加密策略顶霞,通過(guò)encodingAlgorithm來(lái)指定算法肄程,默認(rèn)NONE不加密
cas.authn.jdbc.query[0].passwordEncoder.type=DEFAULT
cas.authn.jdbc.query[0].passwordEncoder.characterEncoding=UTF-8
cas.authn.jdbc.query[0].passwordEncoder.encodingAlgorithm=MD5
執(zhí)行流程(如輸入賬號(hào)密碼為 admin/123):
登陸成功:
然后我們啟動(dòng)應(yīng)用。當(dāng)我們運(yùn)行起CAS,輸入原來(lái)的用戶名和密碼admin/123456
蓝厌,并不能登錄玄叠,因?yàn)槲覀兏拿艽a驗(yàn)證為MD5加密模式了。將123456
使用md5加密后拓提,填入數(shù)據(jù)庫(kù)诸典,再次登錄,可以發(fā)現(xiàn)登錄成功崎苗。由此驗(yàn)證我們加密成功狐粱!
對(duì)密碼進(jìn)行鹽值處理(推薦)官方實(shí)例
上一步只是對(duì)密碼進(jìn)行了簡(jiǎn)單的加密,兩個(gè)帳號(hào)有可能相同的值胆数,就能判斷出密碼是一致的肌蜻,但通過(guò)此方案,大大增加了難度必尼,所以安全系數(shù)也高了許多蒋搜,推薦使用策略。
在上面的基礎(chǔ)上判莉,再添加如下代碼豆挽,可以共存,:
#加密迭代次數(shù)
cas.authn.jdbc.encode[0].numberOfIterations=2
#該列名的值可替代上面的值,但對(duì)密碼加密時(shí)必須取該值進(jìn)行處理
cas.authn.jdbc.encode[0].numberOfIterationsFieldName=
#鹽值固定列
cas.authn.jdbc.encode[0].saltFieldName=username
#靜態(tài)鹽值
cas.authn.jdbc.encode[0].staticSalt=.
cas.authn.jdbc.encode[0].sql=SELECT * FROM sys_user WHERE username =?
#對(duì)處理鹽值后的算法
cas.authn.jdbc.encode[0].algorithmName=MD5
cas.authn.jdbc.encode[0].passwordFieldName=password
cas.authn.jdbc.encode[0].expiredFieldName=expired
cas.authn.jdbc.encode[0].disabledFieldName=disabled
#數(shù)據(jù)庫(kù)連接
cas.authn.jdbc.encode[0].url=jdbc:mysql://127.0.0.1:3306/sso?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
cas.authn.jdbc.encode[0].dialect=org.hibernate.dialect.MySQL5Dialect
cas.authn.jdbc.encode[0].driverClass=com.mysql.jdbc.Driver
cas.authn.jdbc.encode[0].user=root
cas.authn.jdbc.encode[0].password=123456
加密生成類:
//固定鹽生成類
public class PasswordSaltTest {
private String staticSalt = ".";
private String algorithmName = "MD5";
private String encodedPassword = "123456";
private String dynaSalt = "test";
@Test
public void test() throws Exception {
ConfigurableHashService hashService = new DefaultHashService();
hashService.setPrivateSalt(ByteSource.Util.bytes(this.staticSalt));
hashService.setHashAlgorithmName(this.algorithmName);
hashService.setHashIterations(2);
HashRequest request = new HashRequest.Builder()
.setSalt(dynaSalt)
.setSource(encodedPassword)
.build();
String res = hashService.computeHash(request).toHex();
System.out.println(res);
}
}
測(cè)試結(jié)果
使用test/123456登錄成功(加鹽密碼可用)
說(shuō)明:
除此之外如果我們要自定義加密類型券盅,就需要實(shí)現(xiàn)org.springframework.security.crypto.password.PasswordEncoder
接口帮哈,并且把類名配置在passwordEncoder.type
。
這種方式我們?cè)谶@里就不做嘗試了锰镀,接下來(lái)我們結(jié)合SpringSecurity提供的加密方法娘侍,完成自定義認(rèn)證校驗(yàn)策略(推薦使用
)