添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
坏坏的眼镜  ·  【Unity】2D ...·  1 周前    · 
强健的南瓜  ·  DoCmd.Close 方法 ...·  1 年前    · 
乖乖的牛腩  ·  VS 2015 出现 ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I use SpringSecurity in my web-project. When I try to login with username and password, I have this error in my stacktrace :

 class org.springframework.security.core.userdetails.User cannot be cast to class com.cesi.cuberil.service.JwtUser (org.springframework.security.core.userdetails.User and com.cesi.cuberil.service.JwtUser are in unnamed module of loader 'app')
    at com.cesi.cuberil.controller.AuthController.login(AuthController.java:116) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.2.jar:5.3.2]

Below, I will put classes where I think the problem comes from. Here my JwtUser.java :

package com.cesi.cuberil.service;
import com.cesi.cuberil.model.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
@Data
public class JwtUser implements UserDetails {
    private final String username;
    private final String password;
    private final boolean enabled;
    private final Collection<? extends GrantedAuthority> authorities;
    private static final long serialVersionUID = 1L;
    private User user;
    public JwtUser(String username, String password, Boolean enabled,  Collection<? extends GrantedAuthority> authorities) {
        this.username = username;
        this.password = password;
        this.enabled = enabled;
        this.authorities = authorities;
    public User getUser() {
        return user;
    public void setUser(User user) {
        this.user = user;
    @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;

Here my AuthController.java :

@RestController
@RequestMapping("/api/v1/auth")
@AllArgsConstructor
public class AuthController {
    @Autowired
    AuthenticationManager authenticationManager;
    @Autowired
    PasswordEncoder encoder;
    @Autowired
    JwtUtils jwtUtils;
    @PostMapping("/login")
    public ResponseEntity<?> login(@Valid @RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);
        JwtUser myUserDetails = (JwtUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        List<String> roles = myUserDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());
        return ResponseEntity.ok(new JwtResponse(jwt, myUserDetails.getUser().getUserId(), myUserDetails.getUsername(), myUserDetails.getUser().getEmail(), roles));

Here my UserDetailsServiceImpl.java :

@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    public User getByUsername(String username) {
        return userRepository.findByUsername(username);
    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = this.getByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("user not found");
        } else {
            List<GrantedAuthority> listAuthorities = new ArrayList<GrantedAuthority>();
            listAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            return new org.springframework.security.core.userdetails.User(username, user.getPassword(), true, true, true, true, listAuthorities);

For information, I use java 11 and the lastest version of Spring Boot.

The problem lies on the return statement of UserDetailsServiceImpl.loadUserByUsername(..). Of course you can not cast User to JwtUser object since they are completely different. You should return the object you created extending UserDetails, which in your case is JwtUser. The following will solve it:

@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    User user = this.getByUsername(username);
    if (user == null) {
        throw new UsernameNotFoundException("user not found");
    } else {
        List<GrantedAuthority> listAuthorities = new ArrayList<GrantedAuthority>();
        listAuthorities.add(new SimpleGrantedAuthority("ROLE_USER"));
        return new JwtUser(username, user.getPassword(), true, listAuthorities); // NOTE here

I think you should return JwtUser instance instead of org.springframework.security.core.userdetails.User. Cause JwtUser already implements UserDetails interface.

Here's an sample.

a cast from one object to another is only possible if there exists a inheritance relationship between these two classes. In your case both classes implements the same interface but there is no inheritance relationship between the class org.springframework.security.core.userdetails.User and your JwtUser.

I think the problem here is a bad use of Spring Security. You are setting the the Authentication in the SecurityContextHolder, calling directly the AuthenticationManager and later calling even the Principal instead of the Authentication from the SecurityContextHolder. I recommend you to do it more in a Standard way, using LoginAuthentication and adding in the Spring Security configuration the successHandler() event, where you can write your own implementation that writes the JwtResponse in the response object.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.