cas单点登录时,mongo中用户密码采用明文密码,很显然,这种模式不符合我们日常开发。为解决此问题,我们来利用自定义密码解决此问题。
一、cas-5.0.x中的密码加密规则
1.cas-5.0.x默认提供了四中配置
# cas.authn.mongo.passwordEncoder.type=NONE|DEFAULT|STANDARD|BCRYPT
可以参考文档:
PasswordEncoderProperties.PasswordEncoderTypes - cas-server 5.1.0-RC1 javadoc
这四种方式其实脱胎于spring security中的加密方式。
spring security先后提供了MD5PasswordEncoder和SHAPasswordEncoder加密以及比较新的StandardPasswordEncoder和BCryptPasswordEncoder。
MD5PasswordEncoder和SHAPasswordEncoder加密是编码算法加密。现在cas把他们归属于DefaultPasswordEncoder。
2.配置如下:
NONE
public static final PasswordEncoderProperties.PasswordEncoderTypes NONE
No password encoding will take place.
说明对密码不做任何加密,也就是保留明文。
DEFAULT
public static final PasswordEncoderProperties.PasswordEncoderTypes DEFAULT
Uses an encoding algorithm and a char encoding algorithm.
说明启用DefaultPasswordEncoder,但是DefaultPasswordEncoder需要带参数encodingAlgorithm,如下
# cas.authn.accept.passwordEncoder.encodingAlgorithm=MD5或者SHA或者SHA1(需要看看版本中支持哪些)
STANDARD
public static final PasswordEncoderProperties.PasswordEncoderTypes STANDARD
Uses StandardPasswordEncoder.
说明启用了StandardPasswordEncoder加密方式
BCRYPT
public static final PasswordEncoderProperties.PasswordEncoderTypes BCRYPT
Uses BCryptPasswordEncoder.
说明启用了BCryptPasswordEncoder加密方式
3.使用NONE模式
NONE是对密码不加密,跟不配置是一样的效果,验证时明文对比。
修改cas-server-webapp\src\main\webapp\WEB-INF下的cas.properties,增加
cas.authn.mongo.passwordEncoder.type=NONE
如下:
数据库中的用户名/密码是:dai/258369,如下:
我们再次打包运行,发现用dai/258369成功登录。
4.使用DEFAULT的MD5模式
DEFAULT模式有细分,所以这里需要指定为MD5模式。修改cas-server-webapp\src\main\webapp\WEB-INF下的cas.properties,增加
cas.authn.mongo.passwordEncoder.type=DEFAULT
cas.authn.mongo.passwordEncoder.encodingAlgorithm=MD5
如下:
然后我们直接在数据库中修改数据库中的用户密码,修改为258369进行md5加密后的结果(25d687e2c7e715b2f1c9bc30a47b0863),如下:
我们再次打包运行,用dai/258369登录,同样可以登录成功。
cas-5.0.x的版本以上其他DEFAULT的SHA1模式和STANDARD模式以及BCRYPT模式根据上面的情况配置即可。
二、cas-4.2.7配置自定义加密规则
1.上面我们说了cas-5.0.x的版本的加密配置。但是!,我们现在用的是cas-4.2.7,看了下源码发现cas-4.2.x并不支持这四种参数的配置,也就是说cas-5.0.x中这些关于mongo的加密方式是不适合cas-4.2.x的版本使用的。
cas-4.2.x的版本中使用的配置参数是mongoPac4jPasswordEncoder,只支持BasicSaltedSha512PasswordEncoder和PasswordEncoder这两种方式。
cas-4.2.7源码中如下图:
那么我们如果要实现跟cas-5.0.x版本一样的几种加密方式或者 自定义的加密方式,则需要对这部分的代码和配置进行修改。
2.新建一个类实现org.pac4j.http.credentials.password.PasswordEncoder接口,然后让MongoAuthenticator验证的时候使用这个加密class即可。具体代码如下:
package org.jasig.cas.authentication;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.pac4j.http.credentials.password.PasswordEncoder;
public class DefaultPasswordEncoderMD5 implements PasswordEncoder {
@Override
public String encode(final String password) {
return MD5.hexDigestSalt(password);
}
}
class MD5 {
private static final String SALT = "dhj888888";
public static String hexDigest(String str) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
return bytesToHex(md5.digest(str.getBytes("utf-8")));
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static String hexDigestSalt(String str) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
return bytesToHex(md5.digest((str + SALT).getBytes("utf-8")));
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
private static String bytesToHex(byte[] bytes) {
StringBuffer md5str = new StringBuffer();
int digital;
for (int i = 0; i < bytes.length; i++) {
digital = bytes[i];
if (digital < 0) {
digital += 256;
}
if (digital < 16) {
md5str.append("0");
}
md5str.append(Integer.toHexString(digital));
}
return md5str.toString();
}
}
代码说明:代码中有此行:
private static final String SALT = "dhj888888";
此属性为盐值,若密码加密采用MD5加盐加密,则此属性的值就是你的盐的值。上述代码中就是利用MD5加盐对密码进行加密,若只是单纯MD5加密,无盐值,就将那个盐值属性直接写成空字符串即可。
附见:
3.将新建的类放置于D:\casoverlay\cas-4.2.7\cas-server-support-mongo\src\main\java\org\jasig\cas\authentication路径下,如图:
4.打开D:\casoverlay\cas-4.2.7\cas-server-support-mongo\src\main\java\org\jasig\cas\authentication路径下的MongoAuthenticationHandler.java,将
private org.pac4j.http.credentials.password.PasswordEncoder mongoPasswordEncoder = new NopPasswordEncoder();
修改成:
private org.pac4j.http.credentials.password.PasswordEncoder mongoPasswordEncoder = new DefaultPasswordEncoderMD5();
然后将
final MongoAuthenticator mongoAuthenticator = new MongoAuthenticator(client, this.attributes);
修改成:
final MongoAuthenticator mongoAuthenticator = new MongoAuthenticator(client, this.attributes,mongoPasswordEncoder );
5.修改数据库中用户密码成258369加密后的结果(利用我们的加密规则加密),我代码中采用的加密方式是:MD5(密码+盐值),加密的结果是:85920b07070b49bec17d15b1abe6618e
数据库中修改后是:
6.重新打包,部署,运行。用dai/258369登录,发现同样登录成功。
如此,我们就实现了自定义加密,具体的加密规则,可根据自己的业务灵活变动。