【问题标题】:failed in the authentication using Shiro使用 Shiro 认证失败
【发布时间】:2014-10-02 15:05:05
【问题描述】:

我必须在 Shiro 中创建一个自定义领域,并且我必须使用带有“salt”的密码

我使用的代码是这样的:

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken  authenticationToken) 
        throws AuthenticationException {
    ...
    Admin admin = query.getByUsername(username);    
    String passwordSalted = admin.getPassword();

    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, passwordSalted, new SimpleByteSource(MY_PRIVATE_SALT), getName());
    return info;
}

public Admin createAdmin(AuthenticationToken authenticationToken){
    DefaultHashService hashService = new DefaultHashService();
    hashService.setHashIterations(500000);
    hashService.setHashAlgorithmName(Sha256Hash.ALGORITHM_NAME);
    hashService.setPrivateSalt(new SimpleByteSource(MY_PRIVATE_SALT)); // Same salt as in shiro.ini, but NOT base64-encoded.
    hashService.setGeneratePublicSalt(true);

    DefaultPasswordService passwordService = new DefaultPasswordService();
    passwordService.setHashService(hashService);
    String encryptedPassword = passwordService.encryptPassword(authenticationToken.getCredentials());

    Admin admin = new Admin();
    String principal = authenticationToken.getPrincipal().toString();
    admin.setUsername(principal);
    admin.setPassword(encryptedPassword);
    return admin;
}

我使用函数“createAdmin”创建一个Admin,然后我把它存入数据库,像这样:

UsernamePasswordToken u = new UsernamePasswordToken("foo","qwerty") ;
Admin admin = createAdmin(u);
query.save(admin);

保存的密码是这样的:

$shiro1$SHA-256$50000$M7T93MZ65TCxXBsD7JFa9A==$gJcEf2oSKE/RKXifwYiJCaHU7X10ng1PxqL3AEMvmjE=

不知道为什么验证失败:

 Factory<SecurityManager> factory = 
            new IniSecurityManagerFactory("classpath:shiro.ini");
 SecurityManager securityManager = factory.getInstance();
 SecurityUtils.setSecurityManager(securityManager);
 AuthenticationToken authenticationToken = new UsernamePasswordToken("foo", "qwerty");

 Subject usr = SecurityUtils.getSubject();
 try {
    securityManager.login(usr, authenticationToken);
 } catch (Exception e) {
        log.error("error");
 }

还有我的 shiro.ini:

 [main]
 customSecurityRealm=cl.fooproyect.CustomRealm

已解决:

为了解决这个问题,我必须更改 shiro.ini 和 createAdmin。我让 shiro 负责创造盐。 这个解决方案对我有用。

shiro.ini 的变化

 [main]

 passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
 passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
 passwordMatcher.passwordService = $passwordService

 customSecurityRealm=cl.doman.punto.vaadin.shiro.CustomRealm
 customSecurityRealm.credentialsMatcher = $passwordMatcher

 securityManager.realms = $customSecurityRealm

createAdmin 的变化:

 public Admin createAdmin(AuthenticationToken authenticationToken){
    DefaultHashService hashService = new DefaultHashService();

    DefaultPasswordService passwordService = new DefaultPasswordService();
    String encryptedPassword =      passwordService.encryptPassword(authenticationToken.getCredentials());

    Admin admin = new Admin();
    String principal = authenticationToken.getPrincipal().toString();
    admin.setUsername(principal);
    admin.setPassword(encryptedPassword);
    return admin;
}

【问题讨论】:

  • 您的代码看起来不错。如果您使用 shiro 源代码调试登录方法,通常速度足够快,但实际上无法通过身份验证。
  • “提交的令牌 [org.apache.shiro.authc.UsernamePasswordToken ... 的凭据与预期的凭据不匹配。” :S,凭证失败。
  • AuthenticationToken 了解密码“$shiro1$sha...”的当前格式吗?我有很多问题,我找不到程序员创建加盐密码然后使用它的示例
  • 我很久没有使用 shiro,但我看到你使用自定义哈希服务来编码密码,而不是用于身份验证。我的建议:确认它与标准哈希服务一起使用,然后搜索文档以查看在哪里以及如何使用 login 中的自定义哈希服务
  • 我们使用的配置与您大致相同,但我们使用的是 spring,它工作正常。我看不到您如何配置 securityManager,您确定它使用与您创建用户时相同的哈希/盐设置吗?

标签: java shiro


【解决方案1】:

您需要确保您的领域使用与创建用户时相同的密码散列设置。

如果你使用 spring,你可以用它们制作 bean,但如果你不使用类似的东西,你可以使用下面的想法来创建某种工厂来为所需的每个服务创建一个对象。

无论如何,这就是我们配置密码/散列/自定义领域的方式。

首先创建密码服务:

@Configuration
public class SecurityConfiguration {

    private static final String PRIVATE_SALT = "ourprivatesalt";

    private PasswordService passwordService;

    private PasswordMatcher credentialsMatcher = new PasswordAndSystemCredentialsMatcher();


    private AuthenticatingSecurityManager securityManager;

    @Bean
    public PasswordService passwordService() {
        if (passwordService == null) {
           DefaultPasswordService defaultPasswordService = new DefaultPasswordService();
           passwordService = defaultPasswordService;
           DefaultHashService defaultHashService = (DefaultHashService) defaultPasswordService.getHashService();
           defaultHashService.setPrivateSalt(new SimpleByteSource(PRIVATE_SALT));
        }
        return passwordService;
    }

    @Bean
    public CredentialsMatcher credentialsMatcher() {
        credentialsMatcher.setPasswordService(passwordService());
        return credentialsMatcher;
    }

然后是我们的自定义领域:

@Service
public class OurRealmImpl extends AuthorizingRealm {

    @Autowired
    private CredentialsMatcher credentialsMatcher;

    @PostConstruct
    private void configure() {
        setCredentialsMatcher(credentialsMatcher);
    }

查看您的代码,我认为缺少的是您没有更改自定义领域中的凭据匹配器。

【讨论】:

    猜你喜欢
    • 2015-10-17
    • 2014-10-06
    • 1970-01-01
    • 2015-05-17
    • 2021-03-07
    • 2019-09-03
    • 2016-05-30
    • 2014-07-19
    • 2021-05-11
    相关资源
    最近更新 更多