не удалось пройти аутентификацию с помощью Широ

Мне нужно создать пользовательскую область в Широ, и я должен использовать пароль с «солью».

Код, который я использую, выглядит примерно так:

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 для создания администратора, а затем сохраняю его в базе данных, например:

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.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;
}

person Troncador    schedule 09.08.2014    source источник
comment
Ваш код выглядит нормально. Если вы отлаживаете метод входа в систему, используя исходный код shiro, вы обычно достаточно быстро выполняете проверку подлинности.   -  person Wouter    schedule 09.08.2014
comment
Представленные учетные данные для токена [org.apache.shiro.authc.UsernamePasswordToken... не соответствуют ожидаемым учетным данным. :S, учетные данные недействительны.   -  person Troncador    schedule 09.08.2014
comment
AuthenticationToken понимает текущий формат пароля $shiro1$sha... ? У меня много вопросов, и я не могу найти пример, когда программист создает соленый пароль, а затем использует его.   -  person Troncador    schedule 09.08.2014
comment
Я не использовал shiro в течение длительного времени, но я вижу, что вы используете специальную хеш-службу для кодирования пароля, а не для аутентификации. Мой совет: убедитесь, что он работает со стандартной хэш-службой, а затем выполните поиск в документе, чтобы узнать, где и как вы можете использовать пользовательский хеш-сервис в login   -  person Serge Ballesta    schedule 09.08.2014
comment
Мы используем примерно ту же конфигурацию, что и вы, но мы используем пружину, и она отлично работает. Я не вижу, как вы настраиваете securityManager, вы уверены, что он использует те же настройки хэша/соли, что и при создании пользователя?   -  person Wouter    schedule 09.08.2014
comment
@Wouter Я завершаю вопрос конфигурацией securityManager и файлом shiro.ini.   -  person Troncador    schedule 09.08.2014


Ответы (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);
    }

Глядя на ваш код, я думаю, что недостающая вещь заключается в том, что вы не изменили средство сопоставления учетных данных в своей пользовательской области.

person Wouter    schedule 09.08.2014