如何从 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。
我无法从控制器中的 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。