簡體   English   中英

@AuthenticationPrincipal返回空用戶

[英]@AuthenticationPrincipal return empty 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定義在這里:

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 {}

當執行控制器時,通過@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=[]}

據我了解,使用@EnableWebSecurity已經在上下文中啟用了@AuthenticationPrincipal的resolver參數。

我的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);
    }
}

我正在使用Spring Security 4.2.0.RELEASE

謝謝 :)

這是因為從CustomFlashMessagesConfigurer DelegatingFlashMessagesConfiguration CustomFlashMessagesConfigurer急切地初始化handlerExceptionResolver,這將阻止AuthenticationPrincipalArgumentResolver的注冊,直到Spring MVC構建了DispatcherServlets自定義參數解析器。

因此我改變了:

@Configuration
@EnableWebMvc
@ComponentScan(value = { "controllers", "services", "listeners" })
@Import(value = { ThymeleafConfig.class, i18nConfig.class, CustomFlashMessagesConfigurer.class })
public class WebConfig extends WebMvcConfigurerAdapter

為此:

@Configuration
@ComponentScan(value = { "controllers", "services", "listeners" })
@Import(value = { ThymeleafConfig.class, i18nConfig.class, CustomFlashMessagesConfigurer.class })
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter

這樣就解決了問題。

錯誤消息很清楚。 您的CustomerUserDetails對象聽起來像是一個實體對象。 在其中添加默認構造函數:

public class CustomUserDetails extends User implements UserDetails {
//..
   public CustomUserDetails(){}
//..
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM