之前介绍过在application.properties文件中,修改默认的静态用户名和密码。这节分析下,取消静态登陆方式,该用从数据库链接获取用户进行登录认证。
CAS支持各种数据库,我这里选用MySQL进行实践。
加密方案
cas支持jdbc校验方案:
-
根据sql给予用户名进行查询,根据密码字段进行鉴定(
select * from table_users where username=?
)可判断有效等 -
通过盐等手段进行编码加密再进行匹配(推荐)
-
根据sql给予用户名以及密码进行查询(
select count(x) from tables_users where username = ? and password=?
),不可判断有效期,若数量大于0则成功 -
根据用户名密码连接数据库,原理是通过jdbc,若连接成功则成功
常用单向加密算法:MD5、SHA、HMAC
一般的加密策略的三种:
-
单项加密算法(密码)
-
单向加密算法(密码+动态盐+私有盐)*加密次数(推荐)
-
不加密(不推荐)
一、数据库脚本
创建表
create table sys_user ( `id` int(11) not null auto_increment, `username` varchar(30) not null, `password` varchar(64) not null, `email` varchar(50), `address` varchar(100), `age` int, `expired` int, // 是否过期 `disabled` int, // 是否禁用 `locked` int, // 是否锁定 primary key (`id`) ) engine=innodb auto_increment=1 default charset=utf8;
未加密数据
insert into sys_user values ('6', 'tingfeng', 'tingfeng', 'admin@foxmail.com', '郑州东区', 24, 0, 0, 0);
明文MD5数据
/*123*/ insert into sys_user values ('1', 'admin', '202cb962ac59075b964b07152d234b70', 'admin@foxmail.com', '广州天河', 24, 0, 0, 0); /*12345678*/ insert into sys_user values ('2', 'zhangsan', '25d55ad283aa400af464c76d713c07ad', 'zhangsan@foxmail.com', '广州越秀', 26, 0, 0, 0); /*1234*/ /*禁用账户*/ insert into sys_user values('3', 'zhaosi','81dc9bdb52d04dc20036dbd8313ed055', 'zhaosi@foxmail.com', '广州海珠', 25, 0 , 1, 0); /*12345*/ /*过期账户*/ insert into sys_user values('4', 'wangwu','827ccb0eea8a706c4c34a16891f84e7b', 'wangwu@foxmail.com', '广州番禺', 27, 1 , 0, 0); /*123*/ /*锁定账户*/ insert into sys_user values('5', 'boss','202cb962ac59075b964b07152d234b70', 'boss@foxmail.com', '深圳', 30, 0 , 0, 1);
二、pom.xml 配置
我们需要在原来的pom.xml基础上,添加数据库驱动,以及 jdbc的支持
<!-- 数据库驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> <!--jdbc认证需要添加的,这个是cas的依赖包--> <dependency> <groupId>org.apereo.cas</groupId> <artifactId>cas-server-support-jdbc</artifactId> <version>${cas.version}</version> </dependency>
若不想找驱动可以直接写下面的依赖即可,其中包括 HSQLDB、Oracle、MYSQL、PostgreSQL、MariaDB、Microsoft SQL Server
<!-- 若不想找驱动可以直接写下面的依赖即可,其中包括 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>
三、application.properties 配置
1、禁用默认静态用户名和密码
2、增加如下配置
## # CAS Authentication Credentials # # cas.authn.accept.users=tingfeng::tingfeng ## # Query Database Authentication 数据库查询校验用户名开始 # # 查询账号密码sql,必须包含密码字段 cas.authn.jdbc.query[0].sql=select * from sys_user where username=? cas.authn.jdbc.query[0].fieldPassword=password cas.authn.jdbc.query[0].fieldExpired=expired cas.authn.jdbc.query[0].fieldDisabled=disabled cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver cas.authn.jdbc.query[0].url=jdbc:mysql://127.0.0.1:3306/cas_sso_record?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false cas.authn.jdbc.query[0].user=casuser cas.authn.jdbc.query[0].password=casuser #默认加密策略,通过encodingAlgorithm来指定算法,默认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
除了上面常用的配置外,还有很多各种各样的参数配置,比如健康查询,线程池,加密策略等
详情参考官方文档:https://apereo.github.io/cas/5.2.x/installation/Database-Authentication.html
以上配置,如驱动,查询数据库等等需要根据不同的场景进行调整
-
若密码无加密,调整
passwordEncoder.type=NONE
-
若密码加密策略为SHA,调整
passwordEncoder.encodingAlgorithm=SHA
-
若算法为自定义,实现
org.springframework.security.crypto.password.PasswordEncoder
接口,并且把类名配置在passwordEncoder.type
自定义算法示例图
详情内容参考链接:https://www.youcl.com/info/2270
四、测试访问
登录帐号
1、静态账号无效
2、admin账号,123密码登录成功
3、zhaosi 用户被禁用,不能登录
4、wangwu 用户过期,提示修改密码
5、boss 用户锁定
五、Encode Database Authentication 编码加密
对密码进行盐值处理再加密,增加了反查难度,如上面的例子,对密码只是简单的加密,不同的帐号有可能相同的值,能判断出密码是一致,但通过此方案,大大增加了难度,所以安全系数也高了许多,推荐策略
A JDBC querying handler that will pull back the password and the private salt value for a user and validate the encoded password using the public salt value. Assumes everything is inside the same database table. Supports settings for number of iterations as well as private salt.
This password encoding method combines the private Salt and the public salt which it prepends to the password before hashing. If multiple iterations are used, the bytecode hash of the first iteration is rehashed without the salt values. The final hash is converted to hex before comparing it to the database value.
一个JDBC查询处理程序,它将撤回用户的密码和私有salt值,并使用公共盐值验证编码密码。 假设一切都在同一个数据库表内。 支持迭代次数以及私有盐的设置。
这种密码编码方法结合了私有的Salt和它在散列之前预先输入密码的公共盐。 如果使用多次迭代,则第一次迭代的字节码散列在没有盐值的情况下重新排列。 在将其与数据库值进行比较之前,最终的哈希转换为十六进制。
1、数据库新增表
/* * 账号加盐表 */ create table sys_user_encode ( `id` int(11) not null auto_increment, `username` varchar(30) not null, `password` varchar(64) not null, `email` varchar(50), `address` varchar(100), `age` int, `expired` int, `disabled` int, primary key (`id`) ) engine=innodb auto_increment=1 default charset=utf8;
数据
// 明文密码 123 insert into sys_user_encode values ('1', 'admin_en', 'bfb194d5bd84a5fc77c1d303aefd36c3', 'huang.wenbin@foxmail.com', '江门蓬江', 24, 0, 0); // 明文密码 12345678 insert into sys_user_encode values ('2', 'zhangsan_en', '68ae075edf004353a0403ee681e45056', 'zhangsan@foxmail.com', '深圳宝安', 21, 0, 0); // 明文密码 1234 insert into sys_user_encode values ('3', 'zhaosi_en', 'd66108d0409f68af538301b637f13a18', 'zhaosi@foxmail.com', '清远清新', 20, 0, 1); // 明文密码 1234 insert into sys_user_encode values ('4', 'wangwu_en', '44b907d6fee23a552348eabf5fcf1ac7', 'wangwu@foxmail.com', '佛山顺德', 19, 1, 0);
2、application.properties 修改
在上面的基础上,再添加如下代码,可以共存
## # Encode Database Authentication 开始 # cas.authn.jdbc.encode[0].sql=select * from sys_user_encode where username=? cas.authn.jdbc.encode[0].passwordFieldName=password cas.authn.jdbc.encode[0].expiredFieldName=expired cas.authn.jdbc.encode[0].disabledFieldName=disabled cas.authn.jdbc.encode[0].driverClass=com.mysql.jdbc.Driver cas.authn.jdbc.encode[0].dialect=org.hibernate.dialect.MySQLDialect cas.authn.jdbc.encode[0].url=jdbc:mysql://127.0.0.1:3306/cas_sso_record?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false cas.authn.jdbc.encode[0].user=casuser cas.authn.jdbc.encode[0].password=casuser #加密迭代次数 cas.authn.jdbc.encode[0].numberOfIterations=2 #该列名的值可替代上面的值,但对密码加密时必须取该值进行处理 cas.authn.jdbc.encode[0].numberOfIterationsFieldName= #盐值固定列 cas.authn.jdbc.encode[0].saltFieldName=username #静态盐值 cas.authn.jdbc.encode[0].staticSalt=. #对处理盐值后的算法 cas.authn.jdbc.encode[0].algorithmName=MD5
3、测试
六、我的源码
https://github.com/X-rapido/CAS_SSO_Record
七、参考文档
http://www.cnblogs.com/flying607/p/7600947.html
https://blog.csdn.net/u010475041/article/details/77943965
https://apereo.github.io/cas/5.2.x/installation/Database-Authentication.html