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>
Create new user
To users
</body>
</html>
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
I'm trying to make a blog w/ spring boot. I am using #Validated and groupings for certain requests. For Example hitting my signup route, I validate the email using #NotBlank and #Email on my User model
Controller:
package com.vweinert.fedditbackend.controllers;
import com.vweinert.fedditbackend.security.jwt.AuthEntryPointJwt;
import org.modelmapper.ModelMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.vweinert.fedditbackend.entities.User;
import com.vweinert.fedditbackend.request.auth.LoginRequest;
import com.vweinert.fedditbackend.request.auth.SignupRequest;
import com.vweinert.fedditbackend.dto.AuthDto;
import com.vweinert.fedditbackend.service.inter.UserService;
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#RequestMapping("/api/auth")
public class AuthController {
private final UserService userService;
private final ModelMapper modelMapper;
private static final Logger logger = LoggerFactory.getLogger(AuthController.class);
public AuthController(UserService userService, ModelMapper modelMapper) {
this.userService = userService;
this.modelMapper = modelMapper;
logger.debug("Auth controller initialized");
}
#PostMapping("/signin")
public ResponseEntity<?> loginUser(#Validated(LoginRequest.class) #RequestBody User loginRequest) {
try {
logger.debug("logging in user {},",loginRequest);
User user = userService.sigInUser(loginRequest);
AuthDto authDto = modelMapper.map(user, AuthDto.class);
return ResponseEntity.ok(authDto);
} catch (Exception e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
#PostMapping("/signup")
public ResponseEntity<?> registerUser(#Validated(SignupRequest.class) #RequestBody User signUpRequest) {
try {
logger.debug("signing up user {},", signUpRequest);
User user = userService.registerUser(signUpRequest);
AuthDto authDto = modelMapper.map(user, AuthDto.class);
return ResponseEntity.ok(authDto);
} catch (Exception e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
}
Model:
package com.vweinert.fedditbackend.entities;
import java.time.LocalDateTime;
import java.util.Set;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.JoinTable;
import jakarta.persistence.Transient;
import jakarta.persistence.FetchType;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonInclude;
import org.hibernate.annotations.CreationTimestamp;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.vweinert.fedditbackend.request.auth.LoginRequest;
import com.vweinert.fedditbackend.request.auth.SignupRequest;
#Entity
#Table(name="users")
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable=false,unique = true)
#NotBlank(groups = {SignupRequest.class}, message = "email is blank")
#Email(groups = {SignupRequest.class}, message = "invalid email")
private String email;
#Column(nullable=false,updatable = false,unique = true)
#NotBlank(groups = {LoginRequest.class, SignupRequest.class},message = "username is blank")
#Size(min = 8, max = 32, groups = {LoginRequest.class, SignupRequest.class}, message = "username must be between 8 and 32 characters")
private String username;
#Column(nullable=false)
#NotBlank(groups = {LoginRequest.class, SignupRequest.class},message = "Missing password")
#Size(min = 8, max = 32, groups = {LoginRequest.class, SignupRequest.class}, message = "password must be between 8 and 32 characters")
private String password;
#Column(columnDefinition = "text")
private String about;
#Column(nullable=false,updatable = false)
#CreationTimestamp
private LocalDateTime createdAt;
private LocalDateTime passwordChangedAt;
private LocalDateTime aboutChangedAt;
#Column(nullable = false)
#Builder.Default
private Boolean deleted = false;
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable( name = "user_roles",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
#OneToMany(mappedBy = "user",fetch = FetchType.LAZY)
private Set<Post> posts;
#OneToMany(mappedBy = "user",fetch = FetchType.LAZY)
private Set<Comment> comments;
#Transient
#JsonInclude()
private String jwt;
public User(String username, String email, String password){
this.username = username;
this.email = email;
this.password = password;
}
}
Signup request interface for the #Validated groups
package com.vweinert.fedditbackend.request.auth;
public interface SignupRequest {
}
Web Security Config:
package com.vweinert.fedditbackend.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.vweinert.fedditbackend.security.jwt.AuthEntryPointJwt;
import com.vweinert.fedditbackend.security.jwt.AuthTokenFilter;
import com.vweinert.fedditbackend.security.services.UserDetailsServiceImpl;
import com.vweinert.fedditbackend.security.jwt.JwtUtils;
#Configuration
#EnableGlobalMethodSecurity(
prePostEnabled = true)
public class WebSecurityConfig {
private final UserDetailsServiceImpl userDetailsService;
private final AuthEntryPointJwt unauthorizedHandler;
private final JwtUtils jwtUtils;
public WebSecurityConfig(JwtUtils jwtUtils, UserDetailsServiceImpl userDetailsService, AuthEntryPointJwt unauthorizedHandler) {
this.jwtUtils = jwtUtils;
this.userDetailsService = userDetailsService;
this.unauthorizedHandler = unauthorizedHandler;
}
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter(jwtUtils,userDetailsService);
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/home/**").permitAll()
.anyRequest().authenticated()
);
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
Authentication entry Point:
package com.vweinert.fedditbackend.security.jwt;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
#Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final Map<String, Object> body = new HashMap<>();
body.put("status", HttpServletResponse.SC_UNAUTHORIZED);
body.put("error", "Unauthorized");
body.put("message", authException.getMessage());
body.put("path", request.getServletPath());
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
}
}
Currently I am getting an AuthenticationException going through my commence method that implements the AuthenticationEntryPoint class. I would like to have custom exceptions that simply return the message attached to my #Email annotation, though I'm really not sure how to do this.
When I do a postman call with this (with no authorization and an intentionally invalid email):
{
"email":"emailssss",
"username":"emailsssssssss",
"password":"emailly123theemail"
}
I get:
{
"path": "/error",
"error": "Unauthorized",
"message": "Full authentication is required to access this resource",
"status": 401
}
and in the console I get:
2023-01-04T14:37:25.768-06:00 WARN 36022 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<?> com.vweinert.fedditbackend.controllers.AuthController.registerUser(com.vweinert.fedditbackend.entities.User): [Field error in object 'user' on field 'email': rejected value [emailssss]; codes [Email.user.email,Email.email,Email.java.lang.String,Email]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.email,email]; arguments []; default message [email],[Ljakarta.validation.constraints.Pattern$Flag;#49be6e2e,.*]; default message [invalid email]] ]
2023-01-04T14:37:25.774-06:00 ERROR 36022 --- [nio-8080-exec-1] c.v.f.security.jwt.AuthEntryPointJwt : Unauthorized error: Full authentication is required to access this resource
I would like to get something like:
{
"message": "invalid email"
}
added
.requestMatchers("/error").permitAll()
To my filterChain in my WebSecurityConfig file. I did not know that when #Validated fails to validate it redirects to /error
I have following problem
I have simple register and logging to the site with Spring Security after successful registration ( user added to the db i added screen below)
When i want to log in i just go in url:
http://localhost:8080/login?error
And nothing else like error i don`t know what is wrong the username and password is correct
This is my view login.html
<form method="POST" th:action="#{/login}" id="loginForm">
<div class="form-group">
<label for="username">Nazwa użytkownika: </label>
<input type="text" name="username" id="username" class="form-control">
</div>
<div class="form-group">
<label for="password">Hasło: </label>
<input type="password" name="password" id="password" class="form-control">
</div>
<br>
<div class="form-group">
<input type="submit" value="Zaloguj się" class="btn btn-primary">
</div>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
</form>
and SecurityConfig
package my.taco.web;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public PasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth
.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.authorizeRequests()
.antMatchers("/design","/orders").access("hasRole('ROLE_USER')")
.antMatchers("/","/**").access("permitAll")
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username")
.passwordParameter("password")
.defaultSuccessUrl("/design",true)
.and()
.logout()
.logoutSuccessUrl("/");
}
#Override
public void configure(WebSecurity web){
web
.ignoring()
.antMatchers("/h2/**");
}
}
I need to add something like logging controller or what? i`m newbie in Spring
Thank you for help everyone.
Added implements UserDetailsService in reply to the comment
package my.taco.services;
import my.taco.data.UserRepository;
import my.taco.models.User;
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;
#Service
public class UserRepositoryUserDetailsService implements UserDetailsService {
private UserRepository userRepo;
#Autowired
public UserRepositoryUserDetailsService(UserRepository userRepo){
this.userRepo=userRepo;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
User user=userRepo.findByUsername(username);
if(user!=null){
return user;
}
throw new UsernameNotFoundException("Użytkwonik "+username+ " nie został znaleziony");
}
}
Added User class
package my.taco.models;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Arrays;
import java.util.Collection;
#Entity
#Data
#NoArgsConstructor(access = AccessLevel.PRIVATE,force = true)
#RequiredArgsConstructor
public class User implements UserDetails {
private static final long serialVersionUID=1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private final String username;
private final String password;
private final String fullname;
private final String street;
private final String city;
private final String state;
private final String zip;
private final String phoneNumber;
#Override
public Collection<? extends GrantedAuthority> getAuthorities(){
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
#Override
public boolean isAccountNonExpired(){
return true;
}
#Override
public boolean isAccountNonLocked(){
return true;
}
#Override
public boolean isCredentialsNonExpired(){
return true;
}
#Override
public boolean isEnabled(){
return true;
}
}
Hello, in this case I would recommend you to implement UserDetailsService:
#Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
private final LoginService loginService;
#Autowired
public UserDetailsServiceImpl(LoginService loginService) {
this.loginService = loginService;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LoginDto user = loginService.findUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username + " not found");
}
return new User(user.getUsername(), user.getPassword(), List.of(new SimpleGrantedAuthority(user.getRole())));
}
}
You should debug your code in the loadUserByUsername method, which will give you a clear understanding of your problem: the required username does not come, there is no user in the database or something else. Keep in mind, the User class from the package org.springframework.security.core.userdetails. Have a nice day
i'm building a Java SpringBoot(Back-End),Vuejs(front)aplication , and im on this part of seting the web security application.
On my User Class the constructor might be like this :
package com.miniAmazon;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.security.core.GrantedAuthority;
import javax.persistence.*;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO,generator = "native")
#GenericGenerator(name="native",strategy="native")
private Long id;
#OneToMany(mappedBy = "users",fetch= FetchType.EAGER)
Set<Product> productsSet= new HashSet<>();
#OneToMany(mappedBy="users", fetch=FetchType.EAGER)
Set<Purchase> purchaseSet=new HashSet<>();
private String userRole;
private String userName;
private String userEmail;
private String userPassword;
public User(){}
public User( String userEmail,String userName,String userPassword,String userRole){
this.userName=userName;
this.userEmail=userEmail;
this.userPassword=userPassword;
this.userRole=userRole;
}
public void addPurchase(Purchase purchase){ purchaseSet.add(purchase);}
public Set<Purchase>getUserPurchaseSet(){
return purchaseSet;
}
////////////////////////////////////////////setter/////////////////////////////////////////////
///////////////////////////////////////////getters////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
#Override
xxxxx
}
}
user repository like this:
package com.miniAmazon;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
#RepositoryRestResource
public interface UserRepository extends JpaRepository<User,String> {
User findByuserName (String usertName);
}
and the web security application code was settled in this way:
package com.miniAmazon;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
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.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
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.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Date;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Bean
public CommandLineRunner initData(ProductRepository productRepository, UserRepository userRepository, PurchaseRepository purchaseRepository){
return(args)->{
User user1=new User("lolo#gmail.com","lolo gomex",passwordEncoder().encode("24"),"buyer");
User user2=new User("jhony#gmail.com","Jack Ripper",passwordEncoder().encode("mole"),"buyer");
User user3=new User("gothic#gmail.com","demo gago",passwordEncoder().encode("adu"),"seller");
User user4=new User("grau#gmail.com","grau gomex",passwordEncoder().encode("24"),"seller");
User user5=new User("goiy#gmail.com","divan Ripper",passwordEncoder().encode("mole"),"buyer");
User user6=new User("gatti#gmail.com","guti gago",passwordEncoder().encode("adu"),"admin");
userRepository.save(user1);
userRepository.save(user2);
userRepository.save(user3);
userRepository.save(user4);
userRepository.save(user5);
userRepository.save(user6);
};
}
}
#Configuration
#EnableWebSecurity
class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
#Autowired
UserRepository userRepository;
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inputName-> {
User user =userRepository.findByuserName(inputName);
if (user != null) {
return new User(user.getUserName(), user.getUserPassword(),
AuthorityUtils.createAuthorityList("USER"));--------------------ERROR
} else {
throw new UsernameNotFoundException("Unknown user: " + inputName);
}
});
}
}
#Configuration
#EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// http.cors();///de heroku tambien
http.authorizeRequests()
.antMatchers("/mini/all_products").permitAll()
.antMatchers("mini/all_products/user_dashboard/purchase/{id}").permitAll()
.antMatchers("/mini/all_product/registering").permitAll()
.antMatchers("/h2-console/**").permitAll()
.antMatchers("/rest/**").hasAuthority("ADMIN")
.antMatchers("/**").hasAuthority("USER")
.anyRequest().fullyAuthenticated();
/////Autorizaciones y permisos para los distintos niveles de seguridad que tendria el usuario segun su casificacion
http.formLogin()
.usernameParameter("name")
.passwordParameter("password")
.loginPage("/api/login");
//
http.logout().logoutUrl("/api/logout");
http.csrf().disable();
http.exceptionHandling().authenticationEntryPoint((req, res, exc) -> res.sendError(HttpServletResponse.SC_UNAUTHORIZED));
http.formLogin().successHandler((req, res, auth) -> clearAuthenticationAttributes(req));
http.formLogin().failureHandler((req, res, exc) -> res.sendError(HttpServletResponse.SC_UNAUTHORIZED));
http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
// http.headers().frameOptions().disable();
http.headers().frameOptions().sameOrigin();
}
private void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session != null) {
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
}
}
but keeps throwing me an error in the first WebSecurityConfiguration in the cosntructor of the new User, saying once i hover it
Cannot resolve constructor 'User(java.lang.String, java.lang.String, java.util.List<org.springframework.security.core.GrantedAuthority>)'
Any idea about why this is happening .Really sorry for having exposed all this code!!.
And thanks in advance!!!
I have checked your code. In your WebSecurityConfig class
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(inputName-> {
User user =userRepository.findByuserName(inputName);
if (user != null) {
return new User(user.getUserName(), user.getUserPassword(),
AuthorityUtils.createAuthorityList("USER"));--------------------ERROR
}
});
}
You are returning user object like this :
return new User(user.getUserName(),
user.getUserPassword(),
AuthorityUtils.createAuthorityList("USER"));
which is wrong.
Because you have created constructor with different argument:
public User(String userEmail,
String userName,
String userPassword,
String userRole);
So pass arguments correctly. It will work.
You can also return like this:
return new User(null, user.getUserName(), user.getUserPassword(),
AuthorityUtils.createAuthorityList("USER"));
You should return org.springframework.security.core.userdetails.User instead of your com.miniAmazon.User:
if (user != null) {
return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getUserPassword(),
AuthorityUtils.createAuthorityList("USER"));
} else {
throw new UsernameNotFoundException("Unknown user: " + inputName);
}
since the loadUserByUsername method from UserDetailsService return a org.springframework.security.core.userdetails.UserDetails instance and org.springframework.security.core.userdetails.User implements org.springframework.security.core.userdetails.UserDetails.
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
This question already has answers here:
Springboot Security hasRole not working
(3 answers)
Closed 4 years ago.
I am using spring security in my spring boot app.
My app works well with in-memory authentication.
But when users are loaded from the database it does not authenticate. It returns 403 access denied error code. UserDetailsService is able to fetch the user information from the database but I dont know where it is going wrong. I am new to spring.
here is my complete code related to security
User.java
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import lombok.Data;
#Entity
#Table(name = "user")
#Data
public class User {
#Id
#NotNull
#GeneratedValue(strategy = GenerationType.AUTO)
private Long userId;
#Column(name = "USERNAME", unique = true)
#NotNull
private String username;
#Column(name = "PASSWORD")
#NotNull
private String password;
#Column(name = "DISPLAY_NAME")
private String displayName;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "id")
private Set<Role> userRoles;
private String profilePicturePath;
}
Role.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name = "roles")
#Data
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String role;
}
UserRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.cloudsofts.cloudschool.people.users.pojos.User;
#Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
RoleRepository.java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
#Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
}
UserService.java
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import com.cloudsofts.cloudschool.people.users.pojos.User;
import com.cloudsofts.cloudschool.people.users.repositories.UserRepository;
#Service
public class UserService {
#Autowired
UserRepository userRep;
#Autowired
private PasswordEncoder passwordEncoder;
public List<User> getAllUsers() {
List<User> users = userRep.findAll();
return users;
}
public void addUser(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
userRep.save(user);
}
public void updateUser(User user) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
userRep.save(user);
}
public void deleteUser(Long id) {
userRep.delete(id);
}
public User getUser(Long id) {
return userRep.findOne(id);
}
}
RoleService.java
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import com.cloudsofts.cloudschool.people.users.repositories.RoleRepository;
#Service
public class RoleService {
#Autowired
RoleRepository userRoleRep;
public void addUserRole(Role role) {
userRoleRep.save(role);
}
public void updateUserRole(Role role) {
userRoleRep.save(role);
}
public void deleteUserRole(Long id) {
userRoleRep.delete(id);
}
public Role getUserRole(Long id) {
return userRoleRep.findOne(id);
}
public List<Role> getAllUserRoles() {
return userRoleRep.findAll();
}
}
CustomUserDetails.java
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import lombok.Data;
#Data
public class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 1L;
private User user;
public CustomUserDetails(final User user) {
this.user = user;
}
public CustomUserDetails() {
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
final Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
Set<Role> roles = null;
if (user != null) {
roles = user.getUserRoles();
}
if (roles != null) {
for (Role role : roles) {
authorities.add(new SimpleGrantedAuthority(role.getRole()));
}
}
return authorities;
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getUsername();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
CustomUserDetailsService.java
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.cloudsofts.cloudschool.people.users.pojos.CustomUserDetails;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import com.cloudsofts.cloudschool.people.users.pojos.User;
import com.cloudsofts.cloudschool.people.users.repositories.UserRepository;
#Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
} else {
System.out.println("______________________________________________________________");
System.out.println("username: " + user.getUsername());
System.out.println("password: " + user.getPassword());
System.out.println("Roles: ");
for (Role role : user.getUserRoles()) {
System.out.println(role.getRole());
}
System.out.println("______________________________________________________________");
return new CustomUserDetails(user);
}
}
}
SecurityConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import com.cloudsofts.cloudschool.security.CustomUserDetailsService;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Qualifier("userDetailsService")
#Autowired
CustomUserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
try {
auth.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());
System.out.println("_________________________________________________");
String username = SecurityContextHolder.getContext().getAuthentication().getName();
System.out.println("_________________________________________________");
System.out.println("You have logged in as " + username);
System.out.println("_________________________________________________");
} catch (Exception e) {
System.out.println("_________________________________________________");
System.out.println(e.getMessage());
System.out.println("_________________________________________________");
}
}
#Bean(name = "passwordEncoder")
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/*
* #Autowired public void configureGlobal(AuthenticationManagerBuilder auth)
* throws Exception {
* auth.inMemoryAuthentication().withUser("student").password("student").roles(
* "student").and().withUser("admin") .password("admin").roles("admin"); }
*/
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// http.authorizeRequests().anyRequest().permitAll();
// http.authorizeRequests().antMatchers("/api/**").permitAll();
http.authorizeRequests().antMatchers("/student/**").hasAnyRole("student", "admin");
http.authorizeRequests().antMatchers("/api/admin/**").hasRole("admin");
http.authorizeRequests().antMatchers("/library/**").hasAnyRole("librarian", "admin");
http.httpBasic();
// http.formLogin().and().logout().logoutSuccessUrl("/login?logout").permitAll();
}
}
Screenshots
Postman Screenshot
Browser Screenshot
Users in the db
Roles in the db
User-Role mapping
Console output after giving the credentials
You seems to using the BCryptPasswordEncoder to encrypt and decrypt password. But 'Users' table screenshot shows the password in plain text. Can you validate the place where you are saving or updating the user, it is actually encoding the password and also the password encoder bean is of type 'BCryptPasswordEncoder'
I got the problem solved.
I had to add ROLE_ as a prefix to the roles.
Now everything works fine
I am going to implement spring security on my spring boot application. For that I usually follow Spring boot and Spring Security integration for Rest API's and I got details at SpringSecurity : Authenticate User with Custom UserDetailsService.
Entity: User and Role creates 3 tables into database (user, role & user_roles)
User
package com.maxpro.entity;
import javax.persistence.*;
import java.util.Set;
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String username;
private String password;
private boolean enabled;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinTable(joinColumns = #JoinColumn(name = "user_id"), inverseJoinColumns = #JoinColumn(name = "role_id"))
private Set<Role> roles;
// getters, setters & toString
}
Role
package com.maxpro.entity;
import javax.persistence.*;
import java.util.Set;
#Entity
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String role;
#ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
private Set<User> users;
// getters, setters & toString
}
Repository: UserRepository
package com.maxpro.repository;
import com.maxpro.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository("userRepository")
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
Config: WebSecurityConfigurer uses WebUserDetailsService custom authentication builder
WebSecurityConfigurer
package com.maxpro.security;
import com.maxpro.repository.UserRepository;
import com.maxpro.security.service.WebUserDetailsService;
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.core.userdetails.UserDetailsService;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
#Configuration
#EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
#Autowired
private UserRepository userRepository;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsServiceBean());
}
#Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return new WebUserDetailsService(userRepository);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/img/**", "/js/**").permitAll()
.antMatchers("/", "/home").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user/**").hasAuthority("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("username").passwordParameter("password").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
// .and()
// .exceptionHandling().accessDeniedPage("/403")
// .and()
// .csrf();
;
}
}
WebUserDetailsService
package com.maxpro.security.service;
import com.maxpro.entity.Role;
import com.maxpro.entity.User;
import com.maxpro.repository.UserRepository;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import javax.transaction.Transactional;
import java.util.HashSet;
import java.util.Set;
#Transactional
public class WebUserDetailsService implements UserDetailsService {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(WebUserDetailsService.class);
private UserRepository userRepository;
public WebUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
User user = userRepository.findByUsername(username);
if (user == null) {
LOGGER.debug("user not found with the provided username");
return null;
}
LOGGER.debug(" user from username " + user.toString());
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user));
}
catch (Exception e){
throw new UsernameNotFoundException("User not found");
}
}
private Set<GrantedAuthority> getAuthorities(User user){
Set<GrantedAuthority> authorities = new HashSet<>();
for(Role role : user.getRoles()) {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getRole());
authorities.add(grantedAuthority);
}
LOGGER.debug("user authorities are " + authorities.toString());
return authorities;
}
}
Problems: Sometime it can authenticate and sometime not. Why?
Questions: Is there any problem with loadUserByUsername() in WebUserDetailsService custom authentication builder?
Notes: I figured out that username is passed to loadUserByUsername() in WebUserDetailsService class. I think UserRepository returns null User even though I passed correct username to the repository.
Resources: Here is my codes on Github.