Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java apache shiro saltedauthentication有问题。hashProvidedCredentials未提供预期哈希_Java_Spring_Security_Shiro_Saltedhash - Fatal编程技术网

Java apache shiro saltedauthentication有问题。hashProvidedCredentials未提供预期哈希

Java apache shiro saltedauthentication有问题。hashProvidedCredentials未提供预期哈希,java,spring,security,shiro,saltedhash,Java,Spring,Security,Shiro,Saltedhash,这是我第二次在项目中使用ApacheShiro,但第一次使用密码。我在一个web应用程序中使用shiro,使用jsp、spring、JPA(spring数据JPA),并在保存到数据库之前使用SHA256进行加密,然后使用base64。我有一个SaltedJPARealm,一个Sha256CredentialMatcher,它实现了一个HashedCredentialMatcher。我就是这样做的 在我的控制器中创建用户 RandomNumberGenerator rng = new Secure

这是我第二次在项目中使用ApacheShiro,但第一次使用密码。我在一个web应用程序中使用shiro,使用jsp、spring、JPA(spring数据JPA),并在保存到数据库之前使用
SHA256
进行加密,然后使用
base64
。我有一个
SaltedJPARealm
,一个
Sha256CredentialMatcher
,它实现了一个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());
 Subject currentUser = SecurityUtils.getSubject();
 if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken(loginForm.getEmail(), loginForm.getPassword(), loginForm.isRememberMe());
  SecurityUtils.getSubject().login(token);
        }
因此,假设我的密码是
password1234
,生成的salt是
/ZFfGOcSxYhy+g=
,那么在我的数据库中,我有密码:
whb+0AihIGJ4n8QwULj1tR6qSwCrA+1BUvnoe4q4Cy4=
数据库中
salt字段中的salt是相同的

在我的spring配置中:

<!--....-->
 <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>
<!--....-->
saltedjparelm的doGetAuthenticationInfo(AuthenticationToken at)
从数据库获取用户后返回
SaltedAuthenticationInfo

ByteSource salt = ByteSource.Util.bytes(user.getSalt());           
return new SimpleAuthenticationInfo(user, user.getPassword().toCharArray(),salt,this.getName());
Sha256CredentialMatcher的
doCredentialsMatch
如下所示:

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

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

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

密码服务是一个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>
我认为您会发现Spring配置和代码的使用比低级随机数生成器和HashService+HashAPI更好/更干净


你不使用PasswordMatcher和PasswordService有什么原因吗?它们自动使用安全随机生成的SALT,并直接执行密码比较。
passwordService
use per default
sha-256
加密和50000次迭代(我认为是这样)我还没有找到任何方法来更改这些默认值。尝试时,在生成密码的调试过程中,速度似乎很慢。所以我回到了自定义实现。谢谢。我在下面回答了您关于密码服务用法的问题。我知道它不能解决您最初发布的问题,但我认为您会发现它更容易/更好地使用。谢谢您的回复。根据你的建议,这个领域是一样的吗<代码>受保护的AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken位于)/。。。。。返回新的SimpleAuthenticationInfo(user,user.getPassword().toCharray(),this.getName());}
@blacksensei P.S.这种方法假设您首先使用PasswordService在数据存储中设置密码(如上面第二个代码块所示)。然后,在登录时可以使用存储的值进行比较。如何获得PasswordService?它是由SecurityManager所有吗?@JessBowers如上面的代码示例所示,它只是手动实例化(

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

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