0

这是我第二次apache shiro在项目中使用,但第一次是salting密码。这次我使用apache shiro 1.2.0. 我在使用 jsp、spring、JPA(spring-data-jpa) 的 Web 应用程序中使用 shiro,然后在保存到数据库之前使用它SHA256进行加密。base64我有一个SaltedJPARealmSha256CredentialMatcher它实现了一个 HashedCredentialMatcher。我就是这样做的

在我的控制器中创建用户

RandomNumberGenerator rng = new SecureRandomNumberGenerator();
ByteSource salt = rng.nextBytes(10);              
        String hashedPasswordBase64 = new Sha256Hash(signupForm.getPassword(),salt).toBase64();

userService.createUser(signupForm.getFullName(), signupForm.getEmail(), hashedPasswordBase64, salt.toBase64());

所以假设我的密码是password1234并且生成的盐/ZFfGOcSxYhy+g==在我的数据库中所以我有密码:whb+0AihIGJ4n8QwULj1tR6qSwCrA+1BUvnoe4q4Cy4=salt field in the database是相同的。

在我春天的配置中是:

<!--....-->
 <bean id="saltedJPARealm" class="bla.bla.webapp.security.SaltedJPARealm">
    <constructor-arg  ref="credMatcher"/>
</bean>

    <bean id="credMatcher" class="bla.bla.webapp.security.Sha256CredentialMatcher">
        <property name="storedCredentialsHexEncoded" value="false" />
        <property name="hashAlgorithmName" value="SHA-256" />
        <!--<property name="hashIterations" value="1024" />-->
    </bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on="userRepository">
    <property name="realm" ref="saltedJPARealm" />
</bean>
<!--....-->

登录用户

 Subject currentUser = SecurityUtils.getSubject();
 if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken(loginForm.getEmail(), loginForm.getPassword(), loginForm.isRememberMe());
  SecurityUtils.getSubject().login(token);
        }

从数据库中获取用户后的SaltedJPARealm's doGetAuthenticationInfo(AuthenticationToken at)返回:SaltedAuthenticationInfo

ByteSource salt = ByteSource.Util.bytes(user.getSalt());           
return new SimpleAuthenticationInfo(user, user.getPassword().toCharArray(),salt,this.getName());

Sha256CredentialMatcherdoCredentialsMatch看起来像:

    Object tokenfromSubmition = hashProvidedCredentials(token.getCredentials(),((SaltedAuthenticationInfo)info).getCredentialsSalt(),0);
    Object passwordFromStorage =this.getCredentials(info);

    Boolean match = equals(tokenfromSubmition, passwordFromStorage);
    return match;

完整的代码可在 paste 上找到,但身份验证失败。但是当我更改代码不加盐密码(创建帐户时)并返回 AuthenticationInfo 而不是 SaltedAuthenticationInfo。它适用于同一类。我想知道到底做错了什么?

4

1 回答 1

1

PasswordService是一个 POJO(带有嵌套属性),它的嵌套属性也可以使用 Spring 进行配置:

<bean id="passwordService" class="org.apache.shiro.authc.credential.DefaultPasswordService">
  <property name="hashService.hashAlgorithmName" value="SHA-512"/>
  <property name="hashService.hashIterations" value="500000"/>
</bean>

<bean id="myRealm" class="...">
  <property name="credentialsMatcher">
    <bean class="org.apache.shiro.authc.credential.PasswordMatcher">
      <property name="passwordService" ref="passwordService"/>
    </bean>
  </property>
</bean>

这允许实例在登录尝试期间myRealm使用 PasswordService 进行凭据检查。

要在最终用户设置密码时(即在帐户注册或密码重置期间)使用 PasswordService 加密密码,您可以注入PasswordServicebean 然后使用它:

String encryptedPassword = passwordService.encryptPassword(signupForm.getPassword());

userService.createUser(signupForm.getFullName(), signupForm.getEmail(), encryptedPassword);

我认为您会发现 Spring 配置和代码使用比较低级别的随机数生成器和 HashService + Hash API 更好/更干净。

于 2012-10-17T18:21:57.730 回答