【问题标题】:Get actual user details with spring boot使用 Spring Boot 获取实际用户详细信息
【发布时间】:2020-07-17 18:17:15
【问题描述】:

实际上,我正在使用 Spring boot、Mongodb 和 Vue.js 构建一个论坛项目。

当我尝试发布新评论并使用 SecurityContextHolder 获取用户数据并将其转换为从 Spring boot 提供的 UserDetails 类实现的 UsersDetailImpl 时,它会引发以下错误: org.springframework.security.web.authentication.webauthenticationdetails 不能转换为 .... UserDetailsImpl

我真的不知道这个错误的原因,因为如果我从 Postman 测试它不会报告错误。

UserDetailsImpl.java

public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;

private String id;

private String username;

private String email;

@JsonIgnore
private String password;

private Collection<? extends GrantedAuthority> authorities;

public UserDetailsImpl(String id, String username, String email, String password,
                       Collection<? extends GrantedAuthority> authorities) {
    this.id = id;
    this.username = username;
    this.email = email;
    this.password = password;
    this.authorities = authorities;
}

public static UserDetailsImpl build(User user) {
    List<GrantedAuthority> authorities = user.getRoles().stream()
            .map(role -> new SimpleGrantedAuthority(role.getName().name()))
            .collect(Collectors.toList());

    return new UserDetailsImpl(
            user.getId(),
            user.getUsername(),
            user.getEmail(),
            user.getPassword(),
            authorities);
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    return authorities;
}

public String getId() {
    return id;
}

public String getEmail() {
    return email;
}

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

@Override
public boolean equals(Object o) {
    if (this == o)
        return true;
    if (o == null || getClass() != o.getClass())
        return false;
    UserDetailsImpl user = (UserDetailsImpl) o;
    return Objects.equals(id, user.id);
}
}

CommentController.java

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/comments")
public class CommentController {
@Autowired
CommentRepository commentRepository;

@Autowired
RoleRepository roleRepository;

@PostMapping("/ask")
public ResponseEntity<?> ask (@Valid @RequestBody AskRequest askRequest) {

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();

    HashSet<String> strRoles = userDetails.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toCollection(HashSet::new));

    Set<Role> roles = new HashSet<>();
    strRoles.forEach(role -> {
        int cutPoint = role.indexOf("_");
        role = role.substring(cutPoint + 1).toLowerCase();

        findRole(roles, role, roleRepository);
    });

    User user = new User(userDetails.getUsername(),  userDetails.getEmail(), roles);
    ObjectId discussion_id = ObjectId.get();
    String slug =  new Slugify().slugify(askRequest.getTitle());

    Comment comment = new Comment(discussion_id, askRequest.getTitle(),
            askRequest.getText(),slug, "full_slug_test", Instant.now(),user);

    String info = comment.getDiscussion_id().toString() +  comment.getPosted() + comment.getTitle()
            + comment.getText() + comment.getAuthor().getUsername() + comment.getAuthor().getEmail()
            + comment.getAuthor().getId() + comment.getAuthor().getRoles();

    commentRepository.save(comment);

    return ResponseEntity.ok(new MessageResponse(info));
}
}

我是所有这些技术的新手,可能存在严重错误。所有的建议都会对我有很大的帮助,因为这个项目是学术性的。

如果有人需要更多信息,请询问。

谢谢大家:)

【问题讨论】:

    标签: spring spring-boot spring-security


    【解决方案1】:

    authentication.getDetails() 更改为getAuthentication().getPrincipal()

    您将拥有: UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();

    【讨论】:

    • 程序仍然抛出同样的错误:java.lang.ClassCastException: java.lang.String cannot be cast to es.cifpcm.techforum.security.services.authorization.UserDetailsImpl at es.cifpcm.techforum .controllers.CommentController.ask(CommentController.java:44)
    • 这是另一个问题,我的回答解决了您最初的问题。成功身份验证后,您是否将 UserDetailsImpl 对象存储在安全上下文中?我认为您有自定义身份验证提供程序,它将用户名设置为主体而不是您的 UserDetailsImpl 对象,这就是您得到 ClassCastException 的原因。
    • 对不起,我以为是同样的问题。我对 Spring Security 不太了解。我只是在 Authentication 对象中设置了一个 UsernamePasswordAuthenticationToken,然后将其设置到 SecurityContextHolder 中。我将更新我的帖子并删除前端代码,并添加有关唱入控制器和 Web 安全配置的更多有用信息。我等待回复,谢谢。
    • 使用UsernamePasswordAuthenticationToken 3 参数构造函数new UsernamePasswordAuthenticationToken(userDetailsObject,null,userDetailsObject.getAuthorities()) 并且 this 作为身份验证对象存储在 Spring 安全上下文持有者中。您不需要控制器进行身份验证,因为身份验证是在请求之前在过滤器级别执行的到达任何控制器以获取受保护的资源。阅读stackoverflow.com/a/61018409/10597309,其中显示了身份验证的基本流程,从 1 到 5 读取步骤
    【解决方案2】:

    最后我发现了错误,它在前端。我以这种方式使用 JWT 发送 de 标头。

    import axios from 'axios';
    import authHeader from './auth-header';
    
    const API_URL = 'http://localhost:8080/comments/';
    
    class CommentsService {
    ask(post){
        return axios.post(API_URL + 'ask', {
            title: post.title,
            text: post.text,
            headers: authHeader()
        });
      }
    }
    export default new CommentsService();
    

    这是完全错误的,所以我找到了这样做的方法。

    import axios from 'axios';
    import authHeader from './auth-header';
    
    const API_URL = 'http://localhost:8080/comments/';
    
    class CommentsService {
    ask(post){
        return axios.post(API_URL + 'ask', {
            title: post.title,
            text: post.text
        },{headers: authHeader()});
      }
    }
    export default new CommentsService();
    

    我还添加了挂载标题的代码。

    export default function authHeader() {
    let user = JSON.parse(localStorage.getItem('user'));
    
    if (user && user.accessToken) {
      return { Authorization: 'Bearer ' + user.accessToken };
    } else {
      return {};
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-02
      • 2014-11-08
      • 2016-12-31
      • 2013-01-19
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多