首页 文章

Spring Security:DB和applicationContext中的密码编码

提问于
浏览
33

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

从另一边有我的 dataSource 的SQL(它的JdbcDaoImpl):

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

现在这个代码中有关于 sha 的字样,所以从标准的Spring Security users 表中选择的密码没有编码 .

也许,我应该在我的hibernate映射配置中为 password 列提供一些 sha 属性:

<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 配置和数据库查询作为相同的密码编码?

7 回答

  • 5

    如果您自己选择散列系统,而不是使用已包含散列密码的现有数据库构建应用程序,则应确保散列算法也使用盐 . 不要只使用简单的摘要 .

    一个不错的选择是bcrypt,我们现在通过 BCryptPasswordEncoder (使用jBCrypt实现)直接在Spring Security 3.1中支持 . 这会自动生成一个salt,并将其与单个String中的哈希值连接起来 .

    某些数据库内置支持散列(例如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作为属性添加到Authentication Provider类 . 自动装配或提供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)
    
  • 1

    您可以通过简单的方式执行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"));
    
  • 4

    使用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 指向 serviceservice 指向 datasource .

    Edit: 在Java中,您必须使用以下内容对密码进行编码:

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

    Warn: 小心!不要将SHA与MD5混合使用!

    如果将 authentication-providerpassword-encoder 设置为SHA,则需要使用相同的方式在Java中进行编码以保持一致 . 但是,如果您在Java中使用MD5作为您发现的样本,请不要忘记将哈希值设置为"md5" . DigestUtils还提供md5编码器:

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

    只是提示注释

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

    接受的答案是正确的 . 我用 spring 3.1BCrypt 编码算法测试了它 .

    创建用户时 .

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

    当用户登录时,请记住,使用普通密码( not hashed ) . 就像:

    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>
    

    希望它能帮到别人!

  • 76

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

相关问题