it-swarm-pt.tech

Spring Security: codificação de senha no DB e no applicationContext

Tenha 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>

do outro lado tem SQLs do meu dataSourceJdbcDaoImpl ):

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

Agora existe o Word sobre sha neste código, portanto, a senha selecionada na tabela padrão Spring Security users não está codificada.

Talvez eu deva fornecer algum atributo sha para a coluna password na minha configuração de mapeamento de hibernação aqui:

<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>

Por enquanto, a senha salva no DB como está, mas deve ser codificada.

Como amigo applicationContext config e consultas de banco de dados para ter a mesma codificação de senha?

33
sergionni

Se você mesmo escolher um sistema de hash, em vez de criar um aplicativo usando um banco de dados existente que já contenha senhas com hash, verifique se o algoritmo de hash também usa sal. Não basta usar um resumo simples.

Uma boa opção é o bcrypt, que agora suportamos diretamente no Spring Security 3.1 através do BCryptPasswordEncoder (implementado usando jBCrypt ). Isso gera automaticamente um salt e o concatena com o valor de hash em uma única String.

Alguns bancos de dados têm suporte interno para hash (por exemplo, Postgres ). Caso contrário, você precisará fazer o hash da senha antes de passá-la ao JDBC:

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

É tudo o que você precisa fazer para codificar as senhas ao criar um usuário.

Para autenticação, você usaria algo como:

<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>
77
Shaun the Sheep

Um pouco mais de explicação sobre a resposta aceita. Espero que ajude alguém.

Hash a senha você mesmo antes de colocá-lo no banco de dados:

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

Adicione o feijão BCryptPasswordEncoder ao seu security-config.xml

Adicione passwordEncoder como uma propriedade à classe Provedor de Autenticação. Conecte-o automaticamente ou forneça os métodos setter e getter.

@AutoWired
private BCryptPasswordEncoder passwordEncoder;

Obter a propriedade enquanto você autentica o usuário para login

<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>

E na classe de autenticação, correspondam as duas senhas

 new BCryptPasswordEncoder().matches(plainTextPasswdFromUserInput, hashedPasswdFromDb)
8
false9striker

Usando o Spring Security 3.1, tente o seguinte:

<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>

O que há de novo: authentication-provider Aponta para service e service aponta para datasource.

Edit: Em Java, você terá que codificar a senha com algo como isto:

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

Aviso: Cuidado! Não misture [~ # ~] sha [~ # ~] com MD5!

Se você definir o password-encoder Do authentication-provider Como [~ # ~] sha [~ # ~], será necessário codificar Java da mesma maneira para manter a consistência, mas se você configurar Java como MD5, como a amostra encontrada, não se esqueça de definir o hash para "md5". DigestUtils também fornece codificador md5:

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

De uma maneira simples, você pode fazer algo como em 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"/>

Em Java

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

Então teste

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

Apenas uma dica para fazer isso com anotações

@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();     
 }

}
4
Alireza Fattahi

A resposta aceita está certa. Eu testei com o algoritmo de codificação spring 3.1 e BCrypt.

Quando criar um usuário.

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

Quando o login do usuário, Lembre-se, use a senha simples (sem hash). Assim como:

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

Aqui está a configuração de segurança:

    <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>

Espero que ajude alguém!

2
maoyang

com 3.1.x esse mapeamento não funciona para autenticação. Maneira de trabalho é:

<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>
1
z0mb1ek