0

I have a problem with my spring boot application. I'm sending a request to get the key, but i get an error


java.lang.ClassCastException: class org.springframework.security.core.userdetails.User cannot be cast to class com.spring.springBlogProject.model.User (org.springframework.security.core.userdetails.User and com.spring.springBlogProject.model.User are in unnamed module of loader 'app')
    at com.spring.springBlogProject.security.JwtProvider.generateToken(JwtProvider.java:28) ~[classes/:na]

I can’t understand what the problem is, I work with spring for the first time. I see that the received data cannot be reduced to the class that I created. What could be the problem? Below are my classes, I'm using Spring Boot (v2.3.1.RELEASE)

Thanks for your help.

public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
       User user = userRepository.findByUsername(username).orElseThrow(()->
                new UsernameNotFoundException("No user found with " + username));

        return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(),
                true,true,true,true,
                getAuthorities("ROLE_USER"));
    }

    private Collection<? extends GrantedAuthority> getAuthorities(String role_user) {
        return Collections.singletonList(new SimpleGrantedAuthority(role_user));
    }
}
@Table
public class User {
    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private Long id;

    @Column
    private String username;

    @Column
    private String password;

    @Column
    private String email;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
public class AuthService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtProvider jwtProvider;

    public void signUp(RegisterRequest registerRequest) {
        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(encodePassword(registerRequest.getPassword()));
        user.setEmail(registerRequest.getEmail());

        userRepository.save(user);
    }

    private String encodePassword(String password) {
        return passwordEncoder.encode(password);
    }

    public String login(LoginRequest loginRequest) {
       Authentication authenticate =  authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(),
                loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        return jwtProvider.generateToken(authenticate);
    }
}

1 Answer 1

1

You have to convert it in UserDetails following way,

public class JwtUser implements UserDetails {

    private final long id;
    private final String email;
    private final String phoneNo;
    private final String username;
    private final String password;
    private final boolean enabled;
    private final Collection<? extends GrantedAuthority> authorities;

    public JwtUser(long userId, String email, String username, String phoneNo, String password, Boolean enabled,  Collection<? extends GrantedAuthority> authorities) {
        this.id = userId;
        this.email = email;
        this.phoneNo = phoneNo;
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.authorities = authorities;
    }

    public long getId() {
        return id;
    }

    public String getEmail() {
        return email;
    }

    public String getPhoneNo() {
        return phoneNo;
    }

    @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 enabled;
    }
}

Replace :

return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(),
                true,true,true,true,
                getAuthorities("ROLE_USER"));

with :

return new JwtUser(user.get().getUserId(), user.get().getEmail(), user.get().getUsername(),
                user.get().getPhoneNo(), user.get().getPassword(), Boolean.TRUE, grantedAuthoritySet(user.get().getAuthorities()));
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you! It's work, but i don't understand how. We create class and implements userDetails interface. Can i implements this interface in class User or we need create JwtUser?
Currently I'm in office i'll answer you asap.
It turns out, wherever I need to use user, I use JwtUser? Right?
Sorry for the late reply actually i forget it. Comes to the point Security library works with UserDetails which contain some pre-define data member & getter setter and it has configured with security internal process accordingly. So, when you want to use it you have to convert your user data in userdetails entity(Because your user have many column which is unnecessary for security check). So that i maintain class named JWTUser which perform this action and convert it to UserDetails. You can manage it at you own way in same class using anonymous method.
If it is okay from your side can you please upvote this answer?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.