Apache Shiro是否支持bCrypt?

时间:2015-08-27 19:28:25

标签: java shiro jbcrypt

Apache Shiro Authentication Framework是否支持使用bCrypt密码哈希算法?如果没有,有没有办法让它与Shiro一起工作?

除了Spring Security之外,是否还有像Shiro支持bCrypt的其他身份验证框架?

2 个答案:

答案 0 :(得分:3)

在Apache Shiro JIRA(SHIRO-290)上有关于这一点的开放式功能请求。

根据这个问题,它将在1.3.0版本中实现。

答案 1 :(得分:2)

我们的解决方案:(来自org.soluvas.security.shiro.BCryptPasswordService

package org.soluvas.security.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashingPasswordService;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.crypto.hash.Hash;
import org.mindrot.jbcrypt.BCrypt;
import org.soluvas.security.SecurityException;

/**
 * Inspired by <a href="https://coderwall.com/p/ohycpq/using-bcrypt-with-shiro">Coderwall: Using BCrypt with Shiro</a>. Please vote for <a href="https://issues.apache.org/jira/browse/SHIRO-290">SHIRO-290</a>.
 *
 * <p>Requires:</p>
 *
 * <pre>{@code
 *     <dependency>
 *         <groupId>de.svenkubiak</groupId>
 *         <artifactId>jBCrypt</artifactId>
 *         <version>0.4.1</version>
 *     </dependency>
 * }</pre>
 *
 * <p>Usage:</p>
 *
 * <pre>{@code
 * @Bean
 * public JdbcRealm jdbcRealm() {
 *     final JdbcRealm jdbcRealm = new JdbcRealm();
 *     jdbcRealm.setDataSource(dataSource);
 *     // jdbcRealm.setAuthenticationQuery(Person2.SHIRO_AUTHENTICATION_QUERY);
 *     final PasswordMatcher passwordMatcher = new PasswordMatcher();
 *     passwordMatcher.setPasswordService(new BCryptPasswordService());
 *     jdbcRealm.setCredentialsMatcher(passwordMatcher);
 *     return jdbcRealm;
 * }
 * }</pre>
 */
public class BCryptPasswordService implements PasswordService {

    @Override
    public String encryptPassword(Object plaintextPassword) throws IllegalArgumentException {
        final String str;
        if (plaintextPassword instanceof char[]) {
            str = new String((char[]) plaintextPassword);
        } else if (plaintextPassword instanceof String) {
            str = (String) plaintextPassword;
        } else {
            throw new SecurityException("Unsupported password type: " + plaintextPassword.getClass().getName());
        }
        return BCrypt.hashpw(str, BCrypt.gensalt());
    }

    @Override
    public boolean passwordsMatch(Object submittedPlaintext, String encrypted) {
        return BCrypt.checkpw(new String((char[]) submittedPlaintext), encrypted);
    }
}