Issue
I have a table in my database which contains such informations :
Nom = name. Prénom = firstname.
I am trying, once the user is logged in, to retrieve the whole user's fields, besides : password.
So for instance,
If I type my username and my password on the logging page, I would like to retrieve :
- My name
- My firstname
- My email
- My username
Also,
I already know how to simply retrieve the username, however I'm stuck getting the mthe whole user's fields..
Here are my files,
User Entity
@Entity
@Table(name = "users")
@NoArgsConstructor
@Getter @Setter
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "nom", length = 50)
private String name;
@Column(name = "prenom", length = 50)
private String firstname;
@Column(name = "username", length = 50, unique = true)
private String username;
@Column
private String email;
@Column
private String role;
@Column()
private String password;
}
AuthUserDetails | Custom UserDetails
public class AuthUserDetails implements UserDetails {
private final String name;
private final String firstname;
private final String username;
private final String email;
private final String password;
private final List<GrantedAuthority> authorities;
public AuthUserDetails(User user) {
this.name = user.getUsername();
this.firstname = user.getFirstname();
this.username = user.getUsername();
this.email = user.getEmail();
this.password = user.getPassword();
this.authorities = Arrays.stream(user.getRole().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@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;
}
}
AuthUserDetailsService | Custom UserDetailsService
// Handle UserAuthentication from Database | Personal User's credentials
@Service
public class AuthUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public AuthUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// ************************ By | Username ************************ //
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// Find the username in the DB
Optional<User> user = userRepository.findByUsername(username);
user.orElseThrow(() -> new UsernameNotFoundException("Not found " + username));
return user.map(AuthUserDetails::new).get();
}
}
UserService
@Service
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
private final JwtProvider jwtProvider;
@Autowired
public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder,
AuthenticationManager authenticationManager, JwtProvider jwtProvider) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.authenticationManager = authenticationManager;
this.jwtProvider = jwtProvider;
}
// ****************************** Login ***************************** //
public AuthenticationResponse login(AuthMapping authMapping) {
Authentication authenticate = authenticationManager.authenticate(new
UsernamePasswordAuthenticationToken(authMapping.getUsername(), authMapping.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authenticate);
String authenticationToken = jwtProvider.generateToken(authenticate);
return new AuthenticationResponse(authenticationToken, authMapping.getUsername());
}
}
AuthMapping | This is what the user types to log in
@Getter @Setter
public class AuthMapping {
private String username;
private String password;
}
AuthenticationResponse | This is what is retrieved once we are successfully logged in
@Data
@AllArgsConstructor
public class AuthenticationResponse {
private String authenticationToken;
private String username;
}
SecurityConfig
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// *************************************************************************** //
private final UserDetailsService userDetailsService;
private final PasswordEncoder passwordEncoder;
private final JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
public SecurityConfig(@Qualifier("authUserDetailsService") UserDetailsService userDetailsService, PasswordEncoder passwordEncoder, JwtAuthenticationFilter jwtAuthenticationFilter) {
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
this.jwtAuthenticationFilter = jwtAuthenticationFilter;
}
// *************************************************************************** //
// Authorization
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/users/register").permitAll()
.antMatchers("/api/users/login").permitAll()
.anyRequest().authenticated();
// JWT Authentication
http.addFilterBefore(this.jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
// CORS
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
}
// *************************************************************************** //
/**
* Handle The Authentication in Spring | InMemory/LDAP/JDBC
* The handle is made through a service : UserDetailsService
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(this.passwordEncoder);
/*
* Read user from the database
* Spring needs to decode the password before performing the authentication
*/
}
// *************************************************************************** //
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
UserController | Login
// User | Login
@PostMapping("/login")
public AuthenticationResponse login(@RequestBody AuthMapping authMapping) {
return userService.login(authMapping);
}
How to solve it please?
Thank you in advance.
Solution
You can write another custom method for retrieve your result: I present my piece of code written in Kotlin.
fun currentUser(): UserDto {
val auth = SecurityContextHolder.getContext().authentication
//auth.principal this is username
val optional = repository.findByEmail(auth.principal.toString())
if (!optional.isPresent) throw ErrorWithUserTokenException(auth.principal.toString())
return UserDto.toDto(optional.get())
}
data class UserDto(
var id: Long,
var username: String
) {
companion object {
fun toDto(user: User): UserDto {
return user.run { UserDto(id!!, username) }
}
}
}
I think that at least, this answer gives you an idea for resolving your problem:)
Answered By - Shavkat Turakulov
Answer Checked By - Gilberto Lyons (JavaFixing Admin)