源码分析Shiro框架的密码加密及校验

前言

         我们知道Shiro框架有提供凭证匹配器类HashedCredentialsMatcher来实现密码校验的,在该类中可以自定义加密方式、加密次数、编码规则等

//权限管理
@Bean
public SecurityManager securityManager() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();	
    securityManager.setRealm(myShiroRealm(hashedCredentialsMatcher()));
    return securityManager;
}

//凭证匹配器
public HashedCredentialsMatcher hashedCredentialsMatcher() {
    HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
    //采用SHA-512方式加密
    hashedCredentialsMatcher.setHashAlgorithmName("SHA-512");
    //设置加密次数
    hashedCredentialsMatcher.setHashIterations(1024);
    //true加密用的hex编码,false用的base64编码
    hashedCredentialsMatcher.setStoredCredentialsHexEncoded(false);
    return hashedCredentialsMatcher;
}

如上图,假如我们采用SHA-512的加密方式,加密次数为1024次,采用base64的编码方式,来看一下是如何实现密码校验的

打开HashedCredentialsMatcher类的源码

可以看到,他是通过doCredentialsMatch方法来进行判断的,其中参数AuthenticationToken包含用户输入的密码信息,AuthenticationInfo包含用户的身份认证信息(如库中存入的密码、盐值等信息)

先进入hashProvidedCredentials方法看一下他的实现

这里先进行判断,取到用户设置的盐值salt,然后调用了hashProvidedCredentials方法

发现最后是通过new SimpleHash方法,分别传入加密方式、用户输入的密码、库中存入的盐值、加密次数,来生成加密后的密码

再进入getCredentials方法看一下他的实现

这里先判断在凭证匹配器中设置的编码方式,由于前面setStoredCredentialsHexEncoded方法设置的false,所以这里采用Base64的方式来进行解码,最终返回库中密码进行Base64解码后的值,所以我们库中存入的密码是加密后再进行Base64编码后的值

模拟Shiro框架的密码校验

import org.apache.shiro.codec.Base64;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.stereotype.Controller;
 
@Controller
public class EncodePassTest {
	
    public static void main(String[] args) throws Exception {
    	String password = "123456";//原密码
    	String hashAlgorithmName = "SHA-512";//加密方式
        int hashIterations = 1024; //加密次数
    	//生成随机盐值
    	String salt = new SecureRandomNumberGenerator().nextBytes().toBase64();
    	//密码和盐值加密并转为Base64
    	String dbPassord = new SimpleHash(hashAlgorithmName, password, salt, hashIterations).toBase64();
    	System.out.println("加密后需入库的密码:"+dbPassord);
    	/*校验密码*/
    	//库中的密码Base64解密后,对应shiro的getCredentials方法
    	SimpleHash dbPassordDecode = new SimpleHash(hashAlgorithmName);
    	dbPassordDecode.setBytes(Base64.decode(dbPassord));
    	System.out.println("库中的密码Base64解密后:"+dbPassordDecode);
    	//用户输入的密码加密后,对应shiro的hashProvidedCredentials方法
        SimpleHash tokenHashedCredentials = new SimpleHash(hashAlgorithmName, password, salt, hashIterations);
        System.out.println("用户输入的密码加密后:"+tokenHashedCredentials);
    }
    
}
发布了95 篇原创文章 · 获赞 131 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/rexueqingchun/article/details/103288532