@KGirman

Encoded password does not look like BCrypt. Как исправить?

Я пытаюсь реализовать авторизацию, но не могу понять причину этой проблемы: *Encoded password does not look like BCrypt*.
Порядок моих действий: Открываю localhost:8080/login, ввожу "user" и "password" в поля username и password (пользователь с такими данными существует в базе данных), нажимаю submit, тут появляется ошибка Encoded password does not look like BCrypt (она отображается в консоли), и логин фейлится. Я не опытен в Spring, поэтому прошу Вашего совета.
Мне кажется, причина в строке the auth.userDetailsService(userService).passwordEncoder(passwordEncoder()); в методе protected void configure(AuthenticationManagerBuilder auth) в классе WebSecurityConfig.java, но никакие решения из гугла мне не помогают.

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>
  • Вопрос задан
  • 1488 просмотров
Решения вопроса 1
@KGirman Автор вопроса
Нашел решение

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
Добавил кодирование пароля в @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;
    }
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы