shiro用户加密默认方式_shiro验证加密过程是怎样的

shiro类方法调用示意图

1.getAuthenticationInfo核心方法

public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

//传入的AuthenticationToken token为表单提交参数封装的类,存储了用户名、明文密码、记住我我、主机IP。

AuthenticationInfo info = getCachedAuthenticationInfo(token);

if (info == null) {

//从自定义的UserRealm中获取AuthenticationInfo(一般是数据库),当作一个比较标本,用途把token生成的密文是与这个标本的密码、密文进行比较,若一致则算登录成功。

//otherwise not cached, perform the lookup:

info = doGetAuthenticationInfo(token);

log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);

if (token != null && info != null) {

cacheAuthenticationInfoIfPossible(token, info);

}

} else {

log.debug("Using cached authentication info [{}] to perform credentials matching.", info);

}

if (info != null) {

//比较在这个方法体内进行

assertCredentialsMatch(token, info);

} else {

log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}]. Returning null.", token);

}

return info;

}

2.doGetAuthenticationInfo,自定义realm,根据token中的用户名,从数据库中获得密文、salt、realm名封装成info

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

String username = (String)token.getPrincipal();

User user = userService.findByUsername(username);

if(user == null) {

throw new UnknownAccountException();//没找到帐号

}

if(Boolean.TRUE.equals(user.getLocked())) {

throw new LockedAccountException(); //帐号锁定

}

//交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现

SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(

user.getUsername(), //用户名

user.getPassword(), //密码

ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt

getName() //realm name

);

return authenticationInfo;

}

3.assertCredentialsMatch,凭证匹配器,提交的凭证和存储的凭证进行匹配比较

//Asserts that the submitted AuthenticationToken's credentials match the stored account AuthenticationInfo's credentials

//我的理解翻译是提交的凭证和存储的凭证进行匹配比较

protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {

//返回设定的凭证匹配器(匹配规则),包含了hashAlgorithmName(加密方式名如md5)、hashIterations(加密次数)、storedCredentialsHexEncoded(密文进行16进制存储)、hashSalted(默认值false)、passwordRetryCache(密码重试缓存)5个属性。

CredentialsMatcher cm = getCredentialsMatcher()

if (cm != null) {

//执行密文匹配,在此时此地,token中的密码还是明文的,未加密

if (!cm.doCredentialsMatch(token, info)) {

//not successful - throw an exception to indicate this:

String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";

throw new IncorrectCredentialsException(msg);

}

} else {

throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +

"credentials during authentication. If you do not wish for credentials to be examined, you " +

"can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");

}

}

4.doCredentialsMatch,密码错误次数后父类HashedCredentialsMatcher的doCredentialsMatch

//在自定义的RetryLimitHashedCredentialsMatcher的doCredentialsMatch方法中加入密码错误次数判断后进入父类HashedCredentialsMatcher的doCredentialsMatch。

//父类的doCredentialsMatch

@Override

public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

Object tokenHashedCredentials = hashProvidedCredentials(token, info);

Object accountCredentials = getCredentials(info);

return equals(tokenHashedCredentials, accountCredentials);

}

5.hashProvidedCredentials,从info中取出salt,和表单提交的密码一个需认证的Hash

//取出盐

protected Object hashProvidedCredentials(AuthenticationToken token, AuthenticationInfo info) {

Object salt = null;

if (info instanceof SaltedAuthenticationInfo) {

salt = ((SaltedAuthenticationInfo) info).getCredentialsSalt();

} else {

//retain 1.0 backwards compatibility:

if (isHashSalted()) {

salt = getSalt(token);

}

}

return hashProvidedCredentials(token.getCredentials(), salt, getHashIterations());

}

//生成hash

//Object credentials 用户名

//Object salt 盐

//int hashIterations hash次数

protected Hash hashProvidedCredentials(Object credentials, Object salt, int hashIterations) {

//算法名,如md5

String hashAlgorithmName = assertHashAlgorithmName();

//创建用户账号时生成的密文也是生成一个SimpleHash,构造参数多一个hashIterations

return new SimpleHash(hashAlgorithmName, credentials, salt, hashIterations);

}

6.getCredentials,从存储的info中提取密文,转换成一个hash对象

// protected Object getCredentials(AuthenticationInfo info) {

Object credentials = info.getCredentials();

byte[] storedBytes = toBytes(credentials);

if (credentials instanceof String || credentials instanceof char[]) {

//account.credentials were a char[] or String, so

//we need to do text decoding first:

if (isStoredCredentialsHexEncoded()) {

storedBytes = Hex.decode(storedBytes);

} else {

storedBytes = Base64.decode(storedBytes);

}

}

AbstractHash hash = newHashInstance();

hash.setBytes(storedBytes);

return hash;

}

//两个hash对象进行比较

7.equals,两个hash对象进行比较

protected boolean equals(Object tokenCredentials, Object accountCredentials) {

if (log.isDebugEnabled()) {

log.debug("Performing credentials equality check for tokenCredentials of type [" +

tokenCredentials.getClass().getName() + " and accountCredentials of type [" +

accountCredentials.getClass().getName() + "]");

}

if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {

if (log.isDebugEnabled()) {

log.debug("Both credentials arguments can be easily converted to byte arrays. Performing " +

"array equals comparison");

}

//最终都转换成字节数组进行比较

byte[] tokenBytes = toBytes(tokenCredentials);

byte[] accountBytes = toBytes(accountCredentials);

return Arrays.equals(tokenBytes, accountBytes);

} else {

return accountCredentials.equals(tokenCredentials);

}

}

大小: 31 KB

分享到:

2017-11-06 14:49

浏览 3617

评论

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值