[英]@AuthenticationPrincipal return empty User
I have this controller where I save the post information associated with the currently authenticated user: 我有一个控制器,用于保存与当前经过身份验证的用户相关联的帖子信息:
@PostMapping("/create")
public String processPost(
@CurrentUser User activeUser,
@ModelAttribute @Valid Post post,
Errors errors){
if(errors.hasErrors()){
return "admin/post/create";
}
User user2 = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
logger.info("Información del usuario mediate @CurrentUser: " + activeUser.toString());
logger.info("Información del usuario mediate SecurityContextHolder: " + user2.toString());
post.setAuthor(activeUser);
postService.create(post);
return "redirect:/admin/posts/all";
}
@CurrentUser
definition is here: @CurrentUser
定义在这里:
package services.security;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
/**
*
* @author sergio
*/
@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {}
When the controller is executed the user obtained by @AuthenticationPrincipal
is empty and the one obtained by SecurityContextHolder
contains all the information: 当执行控制器时,通过@AuthenticationPrincipal
获得的用户为空,而通过SecurityContextHolder
获得的用户包含所有信息:
2016-12-10 19:37:52 INFO PostController:62 - Información del usuario mediate @CurrentUser: User{id=null, username=null, passwordClear=null, confirmPassword=null, password=null, email=null, enabled=true, fullName=null, posts=[]}
2016-12-10 19:37:52 INFO PostController:63 - Información del usuario mediate SecurityContextHolder: User{id=1, username=sergio11, passwordClear=null, confirmPassword=null, password=$2a$10$LJvYTNacIvqZWDQWjF7xaeheK1MrF.FkXxovb2QgcF2CMudA1mM/., email=sss4esob@gmail.com, enabled=true, fullName=Sergio Sánchez Sánchez, posts=[]}
As I understand using @EnableWebSecurity
already enable in the context the resolver argument for the @AuthenticationPrincipal
据我了解,使用@EnableWebSecurity
已经在上下文中启用了@AuthenticationPrincipal
的resolver参数。
My Spring Security Configuration is this: 我的Spring Security配置是这样的:
package config.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.DefaultAuthenticationEventPublisher;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import services.security.CustomUserDetailsService;
/**
*
* @author sergio
*/
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DefaultAuthenticationEventPublisher defaultAuthenticationEventPublisher;
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationEventPublisher(defaultAuthenticationEventPublisher)
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/signup").anonymous()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/admin/login").permitAll()
.usernameParameter("username").passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
.logoutSuccessUrl("/admin/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
@Bean
public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
return new DefaultAuthenticationEventPublisher(applicationEventPublisher);
}
}
I am using Spring Security 4.2.0.RELEASE 我正在使用Spring Security 4.2.0.RELEASE
thanks :) 谢谢 :)
This issue is because DelegatingFlashMessagesConfiguration
from CustomFlashMessagesConfigurer
eagerly initializes the handlerExceptionResolver which prevents the AuthenticationPrincipalArgumentResolver from being registered until after Spring MVC has constructed the DispatcherServlets custom argument resolvers. 这是因为从CustomFlashMessagesConfigurer
DelegatingFlashMessagesConfiguration
CustomFlashMessagesConfigurer
急切地初始化handlerExceptionResolver,这将阻止AuthenticationPrincipalArgumentResolver的注册,直到Spring MVC构建了DispatcherServlets自定义参数解析器。
Therefore I have changed: 因此我改变了:
@Configuration
@EnableWebMvc
@ComponentScan(value = { "controllers", "services", "listeners" })
@Import(value = { ThymeleafConfig.class, i18nConfig.class, CustomFlashMessagesConfigurer.class })
public class WebConfig extends WebMvcConfigurerAdapter
For this another: 为此:
@Configuration
@ComponentScan(value = { "controllers", "services", "listeners" })
@Import(value = { ThymeleafConfig.class, i18nConfig.class, CustomFlashMessagesConfigurer.class })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter
This solves the problem. 这样就解决了问题。
The error message is quite clear. 错误消息很清楚。 Your CustomerUserDetails
object sounds to be an entity object. 您的CustomerUserDetails
对象听起来像是一个实体对象。 Add a default constructor in it: 在其中添加默认构造函数:
public class CustomUserDetails extends User implements UserDetails {
//..
public CustomUserDetails(){}
//..
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.