Пользовательская аутентификация и кодирование паролей Spring Security

Есть ли там учебник или есть ли у кого-нибудь указатели, как сделать следующее с помощью Spring-Security?

Задача:

Мне нужно получить соль из моей базы данных для аутентификации имени пользователя и использовать ее для шифрования предоставленного пароля (со страницы входа в систему), чтобы сравнить его с сохраненным зашифрованным паролем (он же аутентифицирует пользователя).

дополнительная информация:

Я использую нестандартную структуру базы данных. Объект UserDetails создается с помощью настраиваемого UserDetailsService, который, в свою очередь, использует настраиваемый DAOProvider для получения информации из базы данных.

мой security.xml файл на данный момент:

<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
    </authentication-provider>
</authentication-manager>

теперь я думаю мне понадобится

        <password-encoder hash="sha" />

а что еще? Как сообщить Spring Security использовать соль, предоставленную базой данных, для кодирования пароля?


изменить:

Я нашел Это сообщение SO информативным, но недостаточным: если я определю источник соли в моем xml, который будет использоваться кодировщиком паролей, например:

        <password-encoder ref="passwordEncoder">                
            <salt-source ref="saltSource"/>
        </password-encoder>

Мне нужно будет написать собственный SaltSource, чтобы использовать свою собственную соль. Но этого нельзя найти внутри объекта UserDetails. Так...

Альтернатива 1:

Могу ли я использовать настраиваемую реализацию UserDetails, которая может иметь свойство соли?

<beans:bean id="saltSource" class="path.to.MySaltSource"
    p:userPropertyToUse="salt"/>

и

@Service("userDetailsService") 
public class UserDetailsServiceImpl implements UserDetailsService {
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {

        // ...
        return buildUserFromAccount(account);
    }

    @Transactional(readOnly = true)

    UserDetailsImpl buildUserFromAccount(Account account){

        // ... build User object that contains salt property
}

пользовательский класс пользователя:

public class UserDetailsImpl extends User{

    // ...

    private String salt;

    public String getSalt() { return salt; }

    public void setSalt(String salt) { this.salt = salt; }
}

security.xml:

<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="sha">                
        <salt-source ref="saltSource"/>
    </password-encoder>
    </authentication-provider>
</authentication-manager>

<beans:bean id="saltSource" class="org.springframework.security.authentication.dao.ReflectionSaltSource" p:userPropertyToUse="salt"/>


Альтернатива 2:

В противном случае мне пришлось бы ввести свой accountDAO в SaltSource, чтобы извлечь соль для данного userName из базы данных.

НО: Как Spring Security вызывает SaltSource? Всегда с saltSource.getSalt(userDetails)?

Тогда мне просто нужно убедиться, что мой SaltSource использует userDetails.accountName на моем accountDAO для извлечения соли.


Edit2:

Только что узнал, что мой подход ... унаследованный .. :( Так что, думаю, я просто буду использовать StandardPasswordEncoder (который мне еще предстоит выяснить, как именно использовать).

Кстати: я реализовал первый вариант с помощью настраиваемого класса UserDetails, расширяющего класс User и просто добавляя свойство соли, которое затем передается в SaltSource как userPropertyToUse, как это было предложено в сообщении SO, упомянутом в Edit 1 ...


ИЗМЕНИТЬ 3:

Только что заработал StandardPasswordEncoder, поэтому я оставлю здесь несколько указателей:

Используйте StandardPasswordEncoder для аутентификации:

<beans:bean id="encoder" 
    class="org.springframework.security.crypto.password.StandardPasswordEncoder">
</beans:bean>


<authentication-manager>
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder ref="encoder" />         
    </authentication-provider>
</authentication-manager>

Для этого требуется модуль spring -security-crypto версии 3.1.0.RC? насколько я знаю. Не удалось найти репозиторий с версией 3.0. версия (хотя где-то там были перечисленные версии, включая 3.0.6 и так далее). Также в документации говорится о Spring Security 3.1, так что я решил, что буду просто придерживаться этого.

При создании пользователя (для меня это может делать только администратор) я просто использую

        StandardPasswordEncoder encoder = new StandardPasswordEncoder();
        String result = encoder.encode(password);

и я закончил.

Безопасность Spring случайным образом создаст соль и добавит ее в строку пароля перед сохранением в базе данных, поэтому столбец соли больше не нужен.

Однако можно также предоставить глобальную соль в качестве аргумента конструктора (new StandardPasswordEncoder("12345");), но я не знал, как настроить мою конфигурацию безопасности для получения этого значения из bean-компонента вместо предоставления статической строки с <constructor-arg name="secret" value "12345" />. Но я все равно не знаю, сколько это нужно.


person Pete    schedule 05.10.2011    source источник


Ответы (3)


Я отмечу это как ответ, так как я решил свою проблему и никаких других комментариев или ответов не было:

Изменить 1 - альтернатива 1 отвечает на исходный вопрос.

НО Мне пришлось узнать, что индивидуализированное слияние паролей - это устаревший подход, который больше не нужен в Spring Security 3.1, как я описываю в

Редактировать 3, где я оставил несколько указаний о том, как использовать StandardPasswordEncoder для автоматических солей, которые хранятся с паролем.

person Pete    schedule 18.10.2011
comment
Ваш пост действительно помог мне, у меня была очень похожая проблема. +1 за самостоятельное решение ^^ - person user1431729; 21.06.2012
comment
Я бы предложил BCryptPasswordEncoder вместо StandardPasswordEncoder. BCryptPasswordEncoder - лучший выбор как с точки зрения безопасности, так и с точки зрения взаимодействия с другими языками. - person Farm; 09.04.2014

Как бы то ни было, я написал это сообщение в блоге, в котором подробно описывается то, что вы описали: http://rtimothy.tumblr.com/post/26527448708/spring-3-1-security-and-salting-passwords

person rooftop    schedule 05.07.2012

Чтобы получить глобальную соль из bean-компонента, используйте Spring Expression Language или SpEL.

<beans:bean id="encoder" 
        class="org.springframework.security.crypto.password.StandardPasswordEncoder">
    <constructor-arg value="#{someotherBean.somePropertyWithAGetterMethod"/>
</beans:bean>
person paulchapman    schedule 02.06.2013