如何从 PostMapping 方法控制器获取认证用户

how get authfication user from PostMapping method controller

我无法从控制器中的 post 请求方法获取身份验证用户。我尝试使用 @AuthficationPrincipal UserDetails、Principal 和 SecurityContextHolder,但他的 returns 为 null。需要我将图像上传到数据库。请帮我解决这个问题。 (禁用 .csrf)

控制器:

@Controller
@RequestMapping("/images")
public class ImageController {
    private final ImageService imageService;
    private final UserService userService;

    @Autowired
    public ImageController(ImageService imageService,
                       UserService userService) {
       this.imageService = imageService;
       this.userService = userService;
    }

    @PostMapping("/load-image")
    public String loadImage(@RequestParam("image") MultipartFile image,
                        @AuthenticationPrincipal UserDetails user){
        User authUser = userService.findUserByNickname(user.getUsername());
        imageService.load(image, authUser);
        return "redirect:/users/show/"+authUser.getId();
    }
}

安全配置:

@Configuration
@EnableWebSecurity
public class SecurityCFG extends WebSecurityConfigurerAdapter {
     private final BCryptPasswordEncoder bCryptPasswordEncoder;
     private final MyUserDetailsService userDetailsService;

     @Autowired
     public SecurityCFG(BCryptPasswordEncoder bCryptPasswordEncoder, 
                        MyUserDetailsService userDetailsService) {
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
        this.userDetailsService = userDetailsService;
     }

     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userDetailsService)
            .passwordEncoder(bCryptPasswordEncoder);
     }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http.
            csrf().disable()
            .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/orders/**").authenticated()
                .antMatchers("/users/orders").authenticated()
                .antMatchers("/admin/**").hasRole("ADMIN")
            .and()
                .formLogin().loginPage("/users/login")
                .usernameParameter("login")
                .passwordParameter("password")
            .and()
                .logout().logoutSuccessUrl("/users/login?logout").permitAll();

   }
}

用户详细信息服务:

@Service
public class MyUserDetailsService implements UserDetailsService {
    private final UserService userService;

    @Autowired
    public MyUserDetailsService(UserService userService) {
        this.userService = userService;
    }

    @Override
    @Transactional
    public UserDetails loadUserByUsername(final String login){
        User user;
        if(login.contains("@")){
            user = userService.findUserByEmail(login);
        }else{
            user = userService.findUserByNickname(login);
        }
        if(user!=null){
           List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
           return buildUserForAuthentication(user, authorities);
        }
        throw new BadCredentialsException(String.format("Логин %s неверный",login));
    }


    private List<GrantedAuthority> getUserAuthority(Set<Role> userRoles) {
        Set<GrantedAuthority> roles = new HashSet<>();
        for (Role role : userRoles) {
            roles.add(new SimpleGrantedAuthority(role.getRole()));
        }
        return new ArrayList<>(roles);
    }

    private UserDetails buildUserForAuthentication(User user,
                      List<GrantedAuthority> authorities) {
        UserDetails userDetails = new 
        org.springframework.security.core.userdetails.User(user.getNickname(),
            user.getPassword(),user.isActive(), true,true,
            user.isAccountNonLocked(), authorities);
        new AccountStatusUserDetailsChecker().check(userDetails);
        return userDetails;
    }
}

从控制器中删除 @RequestMapping("/images") 解决了这个问题,但我不明白为什么会这样。

这是因为您使用的是 @Controller 而不是 @RestController

如果你想让你的控制器正常工作,你应该使用 @RestController 而不是只在你的其余控制器 类 上使用 @Controller@RestController 实际上是 @Controller@ResponseBody 的 shorthand,它基本上告诉 spring 您想要将函数的所有响应序列化为 json 之类的东西, 或 xml 等等等等

您可以阅读有关注释的更多信息 here