Подтвердить что ты не робот

Spring Безопасность: кодирование пароля в БД и в applicationContext

У вас есть config (applicationContext-security.xml):

<authentication-manager alias="authenticationManager">
    <authentication-provider>
    <password-encoder hash="sha"/>
        <jdbc-user-service data-source-ref="dataSource"/>
    </authentication-provider>
</authentication-manager>

с другой стороны имеют SQL-запросы из моего dataSource (это JdbcDaoImpl):

...
    public static final String DEF_USERS_BY_USERNAME_QUERY =
            "select username,password,enabled " +
            "from users " +
            "where username = ?";
...

В этом коде есть слово о sha, поэтому пароль, выбранный из стандартной таблицы Spring Security users, не закодирован.

Возможно, я должен указать атрибут sha для столбца password в моей конфигурации сопоставления hibernate:

<class name="model.UserDetails" table="users">
    <id name="id">
        <generator class="increment"/>
    </id>
    <property name="username" column="username"/>
    <property name="password" column="password"/>
    <property name="enabled" column="enabled"/>
    <property name="mail" column="mail"/>
    <property name="city" column="city"/>
    <property name="confirmed" column="confirmed"/>
    <property name="confirmationCode" column="confirmation_code"/>

    <set name="authorities" cascade="all" inverse="true">
        <key column="id" not-null="true"/>
        <one-to-many class="model.Authority"/>
    </set>

</class>

Теперь пароль сохраняется в DB как есть, но должен быть закодирован.

Как настроить applicationContext конфигурационные и DB-запросы на одно и то же кодирование пароля?

4b9b3361

Ответ 1

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

Хорошим выбором является bcrypt, который мы теперь поддерживаем непосредственно в Spring Security 3.1 через BCryptPasswordEncoder (реализовано с помощью jBCrypt). Это автоматически генерирует соль и объединяет ее с хеш-значением в одной строке.

Некоторые базы данных имеют встроенную поддержку хеширования (например, Postgres). В противном случае вы должны сами хешировать пароль, прежде чем передавать его в JDBC:

String password = "plaintextPassword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);

Это все, что вам нужно сделать для кодирования паролей при создании пользователя.

Для аутентификации вы должны использовать что-то вроде:

<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

<bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  <property name="userDetailsService" ref="yourJdbcUserService" />
  <property name="passwordEncoder" ref="encoder" />
</bean>

Ответ 2

Немного больше объяснений принятого ответа. Надеюсь, это поможет кому-то.

Сбросьте пароль самостоятельно перед тем, как поместить его в базу данных:

String password = "plaintextPassword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);

Добавьте BCryptPasswordEncoder bean в свой файл security-config.xml    

Добавить passwordEncoder в качестве свойства класса Provider Authentication. Autowire или предоставить методы setter и getter.

@AutoWired
private BCryptPasswordEncoder passwordEncoder;

Получить свойство, пока вы аутентифицируете пользователя для входа

<bean id="dbAuthenticationProvider" class="mypackage.auth.spring.DBAuthenticationProvider" >
    <property name="dataSource" ref="routingDataSource"></property>
    <property name="passwordEncoder" ref="encoder" />
    <property name="passwordQuery"
        value="select password as password from tbl where username=:username">
    </property> 
</bean>

И в аутентификационном классе совпадают оба пароля

 new BCryptPasswordEncoder().matches(plainTextPasswdFromUserInput, hashedPasswdFromDb)

Ответ 3

Используя Spring Security 3.1, попробуйте следующее:

<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="service">
        <password-encoder hash="sha"/>
        <jdbc-user-service data-source-ref="dataSource"/>
    </authentication-provider>
</authentication-manager>

<beans:bean id="dataSource" ...>
    ...
</beans:bean>

<beans:bean id="service" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        <beans:property name="dataSource" ref="dataSource"/>
        ...
</beans:bean>

Что нового: authentication-provider указывает на service и service указывает на datasource.

Изменить: В Java вам придется закодировать пароль с помощью чего-то вроде этого:

DigestUtils.sha(request.getParameter("password"));

Предупреждать: Будьте осторожны! Не смешивайте SHA с MD5!

Если вы установили password-encoder в authentication-provider как SHA, вам необходимо закодировать на Java таким же образом, чтобы поддерживать последовательность. Но если вы входите в Java как MD5, как образец, который вы нашли, не забудьте установить хеш на "md5". DigestUtils также предоставляет кодировщик md5:

DigestUtils.md5(request.getParameter("password"));

Ответ 4

Простым способом вы можете сделать что-то вроде applicationContext-security.xml

<authentication-manager alias="authenticationManager">
   <authentication-provider>
    <password-encoder ref="encoder"/>
    <jdbc-user-service data-source-ref="dataSource"
       users-by-username-query="
          select username,password, enabled 
          from principal where username=?" 
       authorities-by-username-query="
          select p.username, a.authority from principal p, authority a
          where p.id = a.principal_id and p.username=?" 
    />
   </authentication-provider>
</authentication-manager> 

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

В Java

public static String encodePasswordWithBCrypt(String plainPassword){
    return new BCryptPasswordEncoder().encode(plainPassword);
}

Затем проверьте его

System.out.println(encodePasswordWithBCrypt("fsdfd"));

Ответ 5

Принятый ответ правильный. Я протестировал его с помощью алгоритма spring 3.1 и BCrypt.

При создании пользователя.

PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword()));
userDao.save(userEntity);

При входе пользователя в систему, помните, используйте простой пароль (не хешировать). как:

Authentication request = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);

Здесь находится security-config:

    <bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userService" />
        <property name="hideUserNotFoundExceptions" value="false" />
        <property name="passwordEncoder" ref="encoder" />
    </bean>

Надеюсь, это поможет кому-то!

Ответ 6

Просто подсказка для этого с аннотациями

@Configuration
@EnableWebSecurity
@PropertySource("classpath://configs.properties")
public class SecurityContextConfig extends WebSecurityConfigurerAdapter {


@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
}


@Bean(name = "passwordEncoder")
public PasswordEncoder getPasswordEncoder(){
    return new BCryptPasswordEncoder();     
 }

}

Ответ 7

с 3.1.x это сопоставление не работает для auth. Рабочий путь:

<beans:bean id='bCryptPasswordEncoder' class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder'></beans:bean>

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