首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Shiro鉴权失败

Shiro鉴权失败
EN

Stack Overflow用户
提问于 2014-08-09 12:44:03
回答 1查看 2.5K关注 0票数 1

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

我使用的代码类似于:

代码语言:javascript
复制
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“函数创建一个管理员,然后将其存储在数据库中,如下所示:

代码语言:javascript
复制
UsernamePasswordToken u = new UsernamePasswordToken("foo","qwerty") ;
Admin admin = createAdmin(u);
query.save(admin);

保存的密码类似于:

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

我不知道为什么它没有通过认证:

代码语言:javascript
复制
 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:

代码语言:javascript
复制
 [main]
 customSecurityRealm=cl.fooproyect.CustomRealm

已解决:

为了解决这个问题,我必须更改shiro.ini和createAdmin。我把责任交给shiro去制造盐。这个解决方案对我很有效。

shiro.ini中的更改

代码语言:javascript
复制
 [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中的更改:

代码语言:javascript
复制
 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;
}
EN

回答 1

Stack Overflow用户

发布于 2014-08-09 20:44:52

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

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

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

首先创建密码服务:

代码语言:javascript
复制
@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;
    }

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

代码语言:javascript
复制
@Service
public class OurRealmImpl extends AuthorizingRealm {

    @Autowired
    private CredentialsMatcher credentialsMatcher;

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25215274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档