原文地址,转载请注明出处: https://blog.csdn.net/qq_34021712/article/details/80956047 ©王赛超
上一章搭建了单点登录的基本骨架,但是它的用户名和密码是写死的。显然,这样是不行的,用户名密码一般都存放在数据库中。本文将介绍如何让CAS支持MySQL存储用户名和密码。
https://apereo.github.io/cas/5.3.x/installation/Configuration-Properties.html
https://apereo.github.io/cas/5.3.x/installation/Configuration-Properties-Common.html#database-settings
第一步:建表sql
#表结构使用的是之前shiro用户表
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) DEFAULT '' COMMENT '用户名',
`password` varchar(256) DEFAULT NULL COMMENT '登录密码',
`name` varchar(256) DEFAULT NULL COMMENT '用户真实姓名',
`id_card_num` varchar(256) DEFAULT NULL COMMENT '用户身份证号',
`state` char(1) DEFAULT '0' COMMENT '用户状态:0:正常状态,1:用户被锁定',
PRIMARY KEY (`uid`),
UNIQUE KEY `username` (`username`) USING BTREE,
UNIQUE KEY `id_card_num` (`id_card_num`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
第二步:插入密码为明文的一条记录
#插入用户信息表
INSERT INTO user_info(uid,username,`password`,`name`,id_card_num) VALUES (null,'admin','123456','超哥','133333333333333333');
第三步:pom添加依赖
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-support-jdbc-drivers</artifactId>
<version>${cas.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
</dependency>
第四步:将默认的静态用户名和密码配置注释掉
cas.authn.accept.users=casuser::Mellon
第五步:添加jdbc认证的配置
#添加jdbc认证
cas.authn.jdbc.query[0].sql=SELECT * FROM user_info WHERE username =?
#那一个字段作为密码字段
cas.authn.jdbc.query[0].fieldPassword=password
#配置数据库连接
cas.authn.jdbc.query[0].url=jdbc:mysql://127.0.0.1:3306/testshiro?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.MySQLDialect
#数据库用户名
cas.authn.jdbc.query[0].user=root
#数据库密码
cas.authn.jdbc.query[0].password=123456
#mysql驱动
cas.authn.jdbc.query[0].driverClass=com.mysql.jdbc.Driver
现在启动程序,使用admin/123456登录成功,可以从数据库获取信息登录,但是一般情况,是不会直接在数据库中存储明文密码的,下面我们来配置MD5加密。
第五步:添加MD5加密配置
#配置加密策略
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
这个时候再次使用账号admin 密码123456登录已经无法认证通过了,将123456的MD5密文e10adc3949ba59abbe56e057f20f883e放入数据库,这个时候再登录就可以了。
第六步:对密码进行盐值处理(推荐)
https://apereo.github.io/cas/5.3.x/installation/Configuration-Properties.html#database-authentication
上一步只是对密码进行了简单的加密,两个帐号有可能相同的值,就能判断出密码是一致的,但通过此方案,大大增加了难度,所以安全系数也高了许多,推荐使用策略。
在上面的基础上,再添加如下代码,可以共存,:
#加密迭代次数
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].sql=SELECT * FROM user_info WHERE username =?
#对处理盐值后的算法
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
#数据库连接
cas.authn.jdbc.encode[0].url=jdbc:mysql://127.0.0.1:3306/testshiro?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
注意:
如果两种方式都配置的话,默认先用普通MD5验证,如果验证失败,打印异常日志,然后再使用加盐方式验证。
加盐密码生成
package com.springboot.test.shiro;
import org.apache.shiro.crypto.hash.ConfigurableHashService;
import org.apache.shiro.crypto.hash.DefaultHashService;
import org.apache.shiro.crypto.hash.HashRequest;
import org.apache.shiro.util.ByteSource;
import org.junit.Test;
/**
* @author: wangsaichao
* @date: 2018/7/7
* @description:
*/
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);
}
}
往数据库中再插入一条记录
#密码是通过上面的PasswordSaltTest 生成的
INSERT INTO user_info(uid,username,`password`,`name`,id_card_num) VALUES (null,'test','ed0290f05224a188160858124a5f5077','超哥哥','166666666666666666');
测试结果
使用admin/123456登录成功(普通MD5可用)
使用test/123456登录成功(加盐密码可用)