Shiro采用HashedCredentialsMatcher进行密码匹配。
启用Shiro的密码匹配
采用Shiro的密码认证首先需要在Realm中配置
1 2 3 4 5 6 7 8 9 10 11
| <bean id="userRealm" class="com.hello.UserRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"/> </bean> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 散列算法名 --> <property name="hashAlgorithmName" value="SHA-512"></property> <property name="hashIterations" value="1024"></property> <!-- 密码采用Base64解码 --> <property name="storedCredentialsHexEncoded" value="false"></property> </bean>
|
原理分析
只要配置了HashedCredentialsMatcher就会进入到该类的doCredentialsMatch()方法中
1 2 3 4 5
| public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { Object tokenHashedCredentials = this.hashProvidedCredentials(token, info); Object accountCredentials = this.getCredentials(info); return this.equals(tokenHashedCredentials, accountCredentials); }
|
hashProvidedCredentials()是对本次登录的token进行hash。
1 2 3 4 5 6 7 8 9 10 11
| protected Object hashProvidedCredentials(AuthenticationToken token, AuthenticationInfo info) { Object salt = null; if(info instanceof SaltedAuthenticationInfo) { //从info中获取salt salt = ((SaltedAuthenticationInfo)info).getCredentialsSalt(); } else if(this.isHashSalted()) { salt = this.getSalt(token); } //对密码进行hash return this.hashProvidedCredentials(token.getCredentials(), salt, this.getHashIterations()); }
|
这里需要注意的是,在你的Realm中doGetAuthenticationInfo()返回的必须是SaltedAuthenticationInfo。
此方法是数据库中存储的密码信息解码成SHA-512
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| protected Object getCredentials(AuthenticationInfo info) { Object credentials = info.getCredentials(); byte[] storedBytes = this.toBytes(credentials); if(credentials instanceof String || credentials instanceof char[]) { if(this.isStoredCredentialsHexEncoded()) { storedBytes = Hex.decode(storedBytes); } else { storedBytes = Base64.decode(storedBytes); } } AbstractHash hash = this.newHashInstance(); hash.setBytes(storedBytes); return hash; }
|