Home > OS >  Encoded password does not look like BCrypt. How to fix?
Encoded password does not look like BCrypt. How to fix?

Time:09-14

I try to realise an authorization, but cannot get the cause of this problem: Encoded password does not look like BCrypt My actions sequence: open localhost:8080/login, write "user" in login input and "password" in password (user with such login and password is guaranteed to exist), submit, here the problem appears (Encoded password does not look like BCrypt is written in console), login is failed. I am new at Spring, so I need your experienced advice. I guess, the reason is in the auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); in protected void configure(AuthenticationManagerBuilder auth) method in WebSecurityConfig.java, but I cannot apply any solution I've found.

WebSecurityConfig.java

package com.todo.todo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import com.todo.todo.services.UserService;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig{
    @Autowired
    private UserService userService;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((requests) -> requests
                .antMatchers("/",
                "/index",
                "/users",
                "/registrate",
                "/deleteuser/**",
                "/webjars/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin((form) -> form
                .loginPage("/login")
                .permitAll()
            )
            .logout((logout) -> logout.permitAll());

        return http.build();
    }
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

UserService.java

package com.todo.todo.services;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.todo.todo.repositories.UserRepository;

@Service
public class UserService implements UserDetailsService{
    @Autowired
    private UserRepository userRepository;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserDetails userDetails = userRepository.findByUsername(username);
        if(userDetails == null) throw new UsernameNotFoundException("No such username");
        return userDetails;
    }
}

UserRepository.java

package com.todo.todo.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import com.todo.todo.models.User;

public interface UserRepository extends JpaRepository<User, Long>{
    User findByUsername(String username);
}

UserController.java

package com.todo.todo.controllers;

import java.time.Instant;
import java.util.Collections;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;
import com.todo.todo.models.Role;
import com.todo.todo.models.User;
import com.todo.todo.repositories.UserRepository;

@Controller
public class UserController {

    private final String registratePage = "registrate";
    // private final String loginPage = "login";
    private final String redirectLoginPage = "redirect:/login";
    private final String redirectUsersPage = "redirect:/users";

    @Autowired
    private UserRepository userRepository;

    @GetMapping("/users")
    public ModelAndView getHomePage(@AuthenticationPrincipal User user){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("users");
        modelAndView.addObject("users", userRepository.findAll());
        return modelAndView;
    }

    @GetMapping("/deleteuser/{id}")
    public String deleteTask(@PathVariable("id") Long id, Model model){
        User user = userRepository.findById(id).orElseThrow(() -> new NoSuchElementException("User not found by id = "   id));
        userRepository.delete(user);
        return redirectUsersPage;
    }
    
    @GetMapping("/registrate")
    public String getRegistratePage(){
        return registratePage;
    }

    @PostMapping("/registrate")
    public String registrateUser(@Valid User user, Map<String, Object> map){
        User userFromDatabase = userRepository.findByUsername(user.getUsername());
        if(userFromDatabase != null){
            map.put("message", "User has been already registrated!");
            return registratePage;
        }
        user.setCreatedDate(Instant.now());
        user.setRoles(Collections.singleton(Role.USER));
        userRepository.save(user);
        map.put("message", "User has been successfully registrated!");
        return redirectLoginPage;
    }
}

User.java

package com.todo.todo.models;

import java.time.Instant;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
@Entity
@Table(name = "usr")
public class User implements UserDetails{

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @NotBlank(message = "Fill username")
    private String username;

    @NotBlank(message = "Fill password")
    private String password;

    private Instant createdDate;

    @ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
    @CollectionTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"))
    @Enumerated(EnumType.STRING)
    private Set<Role> roles;

    public User() {
    }
    public User(String username, String password) {
        this.username = username;
        this.password = password;
        this.createdDate = Instant.now();
        this.roles = new HashSet<>();
    }
    @Override
    public String toString() {
        return String.format("User{id=%d, username='%s', password='%s', createdDate='%s'}",
        id, username, password, createdDate);
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return getRoles();
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    } 
}

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"
      xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>LOGIN</title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <span th:text="${message}"></span>
        <form th:action="@{/login}" method="POST">
            <div><label> Username : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
        </form>
        <a href="/registrate">Create new user</a>
        <a href="/users">To users</a>
    </body>
</html>

CodePudding user response:

I solved this

WebSecurityConfig.java

package com.todo.todo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.todo.todo.services.UserService;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserService userService;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests((requests) -> requests
                .antMatchers("/",
                "/index",
                "/tasks",
                "/users",
                "/registrate",
                "/logout",
                "/deleteuser/**",
                "/create",
                "/delete/**",
                "/update/**",
                "/create_task",
                "/update_task",
                "/h2-console/**",
                "/webjars/**").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin((form) -> form
                .loginPage("/login")
                .permitAll()
            )
            .logout((logout) -> logout.permitAll());
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .userDetailsService(userService)
        .passwordEncoder(new BCryptPasswordEncoder());
    }
}

UserController.java Added encoding password in @PostMapping("/registrate")

// some imports here
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

// some methods here

@PostMapping("/registrate")
    public String registrateUser(@Valid User user, Map<String, Object> map){
        User userFromDatabase = userRepository.findByUsername(user.getUsername());
        if(userFromDatabase != null){
            map.put("message", "User has been already registrated!");
            return registratePage;
        }
        String encodedPassword = new BCryptPasswordEncoder().encode(user.getPassword());
        user.setPassword(encodedPassword);
        user.setCreatedDate(Instant.now());
        user.setRoles(Collections.singleton(Role.USER));
        userRepository.save(user);
        map.put("message", "User has been successfully registrated!");
        return redirectLoginPage;
    }
  • Related