spring @验证主体返回空值

e4yzc0pl  于 2023-02-11  发布在  Spring
关注(0)|答案(2)|浏览(156)

我根据参考文档设置了我的Spring Security应用程序,经过几个小时的故障排除,我继续得到一个空的@AuthenticationPrincipal传入我的控制器。
身份验证机制对我的数据库中的用户工作正常,但仍然是null @AuthenticationPrincipal。我查阅了几篇互联网帖子,但仍然是null。

网络安全配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider provider(){
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(passwordEncoder());
        provider.setUserDetailsService(userService);
        return provider;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                    .authorizeRequests()
                    .antMatchers("/", "/registration").permitAll()
                    .anyRequest().authenticated()
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .permitAll()
                .and()
                    .logout()
                    .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(provider());
    }
}

消息(实体):

@Entity
@Table(name = "sweater_message")
public class Message {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String text;

    private String tag;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id")
    private User author;

    public Message(String text, String tag, User user) {
        this.author = user;
        this.text = text;
        this.tag = tag;
    }

    public Message() {
    }
    ...getters and setters

用户(单位):

@Entity
@Table(name = "sweater_user")
public class User implements UserDetails {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String password;

    private boolean active;

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(
            name = "sweater_user_role",
            joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
    )
    private Collection<Role> roles;

    public User(String username, String password, boolean active, Collection<Role> roles) {
        this.username = username;
        this.password = password;
        this.active = active;
        this.roles = roles;
    }

    public User() {
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return isActive();
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return getRoles().stream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());

   ...getters and setters
    }

用户服务

@Service
public class UserService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    public User save(User user) {
        User saveUser = new User(
                user.getUsername(),
                new BCryptPasswordEncoder().encode(user.getPassword()),
                true,
                Arrays.asList(new Role("USER")));

        return userRepository.save(saveUser);
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User findUser = userRepository.findByUsername(username);

        if (findUser == null) {
            throw new UsernameNotFoundException("There is no user with this username");
        }

        return new org.springframework.security.core.userdetails.User(
                findUser.getUsername(),
                findUser.getPassword(),
                mapRolesToAuthorities(findUser.getRoles()));
    }

    public Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles) {
        return roles.stream().map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toSet());
    }
}

控制器:

@PostMapping("/main")
    public String add(
            @AuthenticationPrincipal User user,
            @RequestParam String text,
            @RequestParam String tag,
            Map<String, Object> model
    ){
        ...user is null
    }
8ehkhllq

8ehkhllq1#

尝试将**@验证主体用户用户更改为@验证主体用户详细信息用户详细信息**,因为loadUserByUsername返回用户详细信息

kmynzznz

kmynzznz2#

在控制器中使用SecurityContextHolder.getContext().getAuthentication().getPrincipal()查看userdetails对象是否存储在正确的位置,因为@AuthenticationPrincipal(UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal()的缩写。
例如:

@GetMapping("/all")
public ResponseEntity<String> test(@AuthenticationPrincipal AuthUserDetails userDetails) {
 
    System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal());

    return ResponseEntity.ok("success");

}

如果输出不是UserDetails对象,这意味着当你在filter类中初始化你的认证时,你没有正确设置Principal。让我们以UsernamePasswordAuthenticationToken为例:

// in filter class

@Component
public class JwtFilter extends OncePerRequestFilter {
    private JwtProvider jwtProvider;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Optional<AuthUserDetails> authUserDetailOptional = jwtProvider.resolveToken(request); // extract jwt from request, generate a userdetails object

        if (authUserDetailOptional.isPresent()){
            AuthUserDetails authUserDetails = authUserDetailOptional.get();
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    authUserDetails, // set your authUserDetails here!!
                    null,
                    authUserDetails.getAuthorities()
            ); // generate authentication object

            SecurityContextHolder.getContext().setAuthentication(authentication); 
            filterChain.doFilter(request, response);
        } else {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "The token is not valid.");

        }

}

相关问题