Spring Boot,使用编码密码实现登录

Posted

技术标签:

【中文标题】Spring Boot,使用编码密码实现登录【英文标题】:Spring Boot, implement login with encoded password 【发布时间】:2019-01-04 17:49:01 【问题描述】:

我正在使用 Spring Boot、Spring Sec、mysql 开发 Java 密码管理器。 我的登录页面效果很好,我有两种用户:ADMIN 和 NORMAL。 管理员可以创建一个新用户,当它发生时,新用户将使用散列密码和明文用户名保存在 db 上。我的 webController 类如下:

@Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

@RequestMapping(value =  "/login" )
    public String login() 
        return "login";
    

@RequestMapping(value = "/insertuser", method = RequestMethod.GET)
    public String insertuser(ModelMap modelMap) 
        modelMap.put("user", new User());
        return "insertuser";
    

    @RequestMapping(value = "insertuser", method = RequestMethod.POST)
    public String insertuser(
            @ModelAttribute("user") User user, ModelMap modelMap) throws NoSuchAlgorithmException, InvalidKeySpecException 

        String encodedPassword = bCryptPasswordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);

        userService.addUser(user);
        return "home";
    

这里我们有 SecurityConfig

@Configuration
@EnableAutoConfiguration
public class SecurityConfig extends WebSecurityConfigurerAdapter  

    @Autowired
    DataSource dataSource;

    @Autowired
    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception 
        auth.jdbcAuthentication().dataSource(dataSource)
                .usersByUsernameQuery("select username,password,enabled from user where username=?")
                .authoritiesByUsernameQuery("select usernameusr, role from userroles where usernameusr=?");
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.authorizeRequests().antMatchers("/", "/home").permitAll().antMatchers("/admin", "/getrole", "/getusers", "/insertuser").hasRole("ADMIN")
                .anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and().logout()
                .permitAll();   

        http.exceptionHandling().accessDeniedPage("/403");
        

在 db 上,管理员保存的新用户的哈希值为密码。

用户名:阿纳金 密码:$2a$10$.AVpjhbsVKfGtMxiKlTts.2yiiKB0gF7xu2lrL6o3iEWqIMDgM43。 明文密码是:vader

现在,如果我注销并尝试使用用户凭据 anakin/vader 登录,则会收到错误的凭据错误。

如何使用编码密码实现正确登录? 我知道我们需要获取提交的明文密码,应用哈希函数,如果它与 db 上的哈希密码匹配,则登录成功,但我该如何实现这种方法?

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org"
    xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>PASSWORDMANAGER</title>

    <div th:replace="fragments/header :: header-css"/>
</head>
<body>
<div th:replace="fragments/header :: header"/>

    <h1 style="text-align: center">
        <font size="20" color="blue">MAIPASSWORD HOME</font>
    </h1>


    <div style="text-align: center" th:if="$param.error">
        <h1 style="color: red">Bad Credentials. Try again.</h1>
    </div>
    <div style="text-align: center" th:if="$param.logout">
        <h1 style="color: blue">Logged out.</h1>
    </div>
    <form style="text-align: center" th:action="@/login" method="post">
        <p>
            <input type="text" name="username" value="" placeholder="username" />
        </p>
        <p>
            <input type="password" name="password" value=""
                placeholder="password" />
        </p>
        <p class="submit">
            <input type="submit" value="Log In" />
        </p>
    </form>
    <div th:replace="fragments/footer :: footer"/>

</body>
</html>

【问题讨论】:

【参考方案1】:

在您的 configAuthentication 中,在您的身份验证对象末尾调用 passwordEncoder,并传入您的自动装配密码编码器。这将自动处理密码的编码并尝试使用它登录。

【讨论】:

由于您已经在 bcrypt 密码编码器中自动装配,我想这会出错,因为已经为您的 BCryptPasswordEncoder 定义了一个 bean,请尝试像在 webcontroller 类中那样自动装配它,然后只需将自动装配的变量传递给函数而不是执行该函数。 现在,如果我尝试使用在 db 上具有明确密码的用户登录,我会收到此错误“编码密码看起来不像 BCrypt”,而不是我尝试使用具有哈希密码的用户登录我得到信用不好。错误 这两个错误表明 bcrypt 编码器在您登录时正在工作。您可能想尝试重新创建用户并再次登录以防密码输入错误。您可能还想确保在创建用户时,在密码字符串被编码之前没有对密码字符串进行其他更改。顺便说一句,我还建议在密码编码器中使用与对密码进行编码时相同的自动装配方法,而不是使用创建 bcrypt 编码器新实例的函数。 @Artichoke 在我的应用程序中,管理员需要登录到用户帐户并且管理员具有编码密码。那么管理员有没有办法在登录时绕过此密码编码???请帮助我。即,在我的应用程序中,有两种方式由用户记录一种方式,通常由明文密码发生,该密码在 Spring Boot 中使用密码编码,另一种由管理员使用,其中管理员使用哈希密码,需要绕过 Spring Boot密码编码。【参考方案2】:

好的,现在一切正常。在我的 WebController Java 文件中添加以下代码。

 @Autowired
   private BCryptPasswordEncoder bCryptPasswordEncoder;
   String encodedPassword = bCryptPasswordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);

在我的 SecurityConfig

   @Autowired
   public PasswordEncoder BCryptPasswordEncoder() 
    return new BCryptPasswordEncoder();

  @Autowired
  public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception 
  auth
 .jdbcAuthentication()
 .dataSource(dataSource)
 .passwordEncoder(BCryptPasswordEncoder()
 .usersByUsernameQuery("select username,password,enabled from user where username=?")
 .authoritiesByUsernameQuery
 ("select usernameusr, role from userroles where usernameusr=?");
 )

非常感谢朝鲜蓟

【讨论】:

以上是关于Spring Boot,使用编码密码实现登录的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Security、Spring Boot 和 MongoDB 进行密码编码和解码

Spring Boot 密码 bcrypt 编码器:编码值与在线生成的不匹配

是否可以为 Spring Boot 应用程序提供 oauth 和基本用户名密码登录选项?

Spring Boot BCryptPasswordEncoder 编码密码看起来不像 BCrypt

登录表单用户凭据而不是 LDAP Spring Security 中的硬编码 UserDn 和密码

手动 Spring 安全实现,通过角度和密码编码调用