综合

Shiro 1.2新功能DefaultPasswordService解惑

导读: 

最开始学习shiro的时候需要自己保存User的salt, 最近系统升级,使用了Shiro1.3发现在1.2的时候Shiro提供了新的DefaultPasswordService来简化Password encode/match工作。很好奇为啥不在需要自己保存User的salt,查看了defaultpasswordservice的源代码,发现了其中的奥秘,具体看Shiro的代码(关注*部分),主要是重新构建Hash,然后从Hash中获取salt来做提交密码的hash,比较计算出来的hash和存储hash是否一致。

      public boolean More ...passwordsMatch(Object submittedPlaintext, String saved) {
          ByteSource plaintextBytes = createByteSource(submittedPlaintext);

          if (saved == null || saved.length() == 0) {
              return plaintextBytes == null || plaintextBytes.isEmpty();
          } else {
              if (plaintextBytes == null || plaintextBytes.isEmpty()) {
                  return false;
              }
          }

          //First check to see if we can ***reconstitute the original hash*** - this allows us to
          //perform password hash comparisons even for previously saved passwords that don‘t
          //match the current HashService configuration values.  This is a very nice feature
          //for password comparisons because it ensures backwards compatibility even after
          //configuration changes.
          ***HashFormat discoveredFormat = this.hashFormatFactory.getInstance(saved);***

          <strong>if (discoveredFormat != null && discoveredFormat instanceof ParsableHashFormat) {

              ParsableHashFormat parsableHashFormat = (ParsableHashFormat)discoveredFormat;
              **Hash savedHash = parsableHashFormat.parse(saved);**

              return ***passwordsMatch(submittedPlaintext, savedHash)***;
          }</strong>

          //If we‘re at this point in the method‘s execution, We couldn‘t reconstitute the original hash.
          //So, we need to ***hash the submittedPlaintext using current HashService configuration and then
          //compare the formatted output with the saved string.  This will correctly compare passwords***,
          //***but does not allow changing the HashService configuration without breaking previously saved
          //passwords***:

          //The saved text value can‘t be reconstituted into a Hash instance.  We need to format the
          //submittedPlaintext and then compare this formatted value with the saved value:
          HashRequest request = createHashRequest(plaintextBytes);
          Hash computed = this.hashService.computeHash(request);
          String formatted = this.hashFormat.format(computed);

          return saved.equals(formatted);
      }
public boolean passwordsMatch(Object plaintext, Hash saved) { 
        ByteSource plaintextBytes = createByteSource(plaintext); 

        if (saved == null || saved.isEmpty()) { 
            return plaintextBytes == null || plaintextBytes.isEmpty(); 
        } else { 
            if (plaintextBytes == null || plaintextBytes.isEmpty()) { 
                return false; 
            } 
        } 

        HashRequest request = ***buildHashRequest(plaintextBytes, saved);*** 

        Hash computed = this.hashService.computeHash(request); 

        return saved.equals(computed); 
    }
    protected HashRequest buildHashRequest(ByteSource plaintext, Hash saved) { 
        //keep everything from the saved hash except for the source: 
        return new HashRequest.Builder().setSource(plaintext) 
                //now use the existing saved data: 
                .setAlgorithmName(saved.getAlgorithmName()) 
                .***setSalt(saved.getSalt())*** 
                .setIterations(saved.getIterations()) 
                .build(); 
    } 

要使用defaultpasswordService非常简单就是简单的spring bean,当然你可以通过注入改变迭代次数和加密算法。

<bean name="passwordService" class="org.apache.shiro.authc.credential.DefaultPasswordService" />

相关资讯

发表评论
网友评论0 条评论)
暂无评论