AuthenticationPrincipal is empty when using EnableWebSecurity

As Spring Security Status doc all: 34.1 @EnableWebMvcSecurity , @EnableWebMvcSecuritywas replaced by @EnableWebSecurity.

But when I try to get UserDetailsin the controller using @AuthenticationPrincipal, I got an empty object: username "". I also tried @EnableWebMvcSecurity, but unfortunately UserDetails- null.

But I can get in the UserDetailstraditional way, for example:

SecurityContextHolder.getContext().getAuthentication().getPrincipal();

My question is: what is the right way to get my custom UserDetails( Account) when I use @EnableWebSecurity?

Below is the corresponding source code:

Controller:

@RequestMapping(method = RequestMethod.POST)
@Secured("ROLE_USER")
public String postRoom(@Valid @ModelAttribute Room room, BindingResult result, Model model, @AuthenticationPrincipal Account principal) {
    if (result.hasErrors()) {
        return "room_form";
    }

    Account account = accountRepository.findByUsername(principal.getUsername());
    room.setAccountId(account.getId());
    room.setLastModified(new Date());
    roomRepository.save(room);
    return "room_list";
}

Security Configuration:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource;

    @Autowired
    private SecurityProperties security;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().anyRequest().permitAll()
            .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
            .and().logout().permitAll()
            .and().rememberMe()
            .and().csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            auth.jdbcAuthentication().dataSource(this.dataSource).passwordEncoder(new BCryptPasswordEncoder(8));
    }
}

And Account.java:

@Entity
@Table(name = "users")
public class Account implements Serializable {
    @Id
    @GeneratedValue
    private Long id;

    private String username;
    private String password;
    private boolean enabled;

    @Lob
    private byte[] avatar;

// getter / setter ...
}
+3
4

, authentication.getPrincipal(), , UserDetails ( ), org.springframework.security.core.userdetails.User . Java API doc UserDetails .

@AuthenticationPrincipal User, , , .

, , UserDetails , .

@EnableWebSecurity, HandlerMethodArgumentResolver, .

. Spring Boot

jdbcAuthentication , (, , , , , ), ( ). configureGlobal.... .

auth.userDetailsService(userService).passwordEncoder...

UserDetailsService, public UserDetails loadUserByUsername(String username) Spring . loadUserByUsername , org.springframework.security.core.userdetails.User, , User . .

return new User(user.getUsername(), user.getPassword(), permissions);

User, UserDetails, @AuthenticationPrincipal User user .

, permissions , GrantedAuthority . public String getAuthority(), , ( / ).

, , Spring Security . , Spring Security ( , , ), + . , groups rights , GrantedAuthority. "" .

@AuthenticationPrincipal , , , - Account ( ) - UserDetails. .

, . ( , ), , CRUD, .

+2

, :

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Bean
    public AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver(){
        return new AuthenticationPrincipalArgumentResolver();
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(requestEntityMethodArgumentResolver);
        argumentResolvers.add(authenticationPrincipalArgumentResolver());
    }
}
+1

AuthenticationPrincipal .
UserDetails , :

SecurityContextHolder.getContext().getAuthentication().getPrincipal();

argument-resolvers

<mvc:annotation-driven>
    <mvc:argument-resolvers>
        <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver"/>
    </mvc:argument-resolvers>
</mvc:annotation-driven>

34.2 @AuthenticationPrincipal

AuthenticationPrincipalArgumentResolver Spring Spring MVC.

, resolver .

34.1, "@EnableWebMvcSecurity", Spring MVC

0

. HandlerMethodArgumentResolver .

@Target({ ElementType.PARAMETER, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser{}

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "x.x.x")
public class ApplicationConfiguration extends WebMvcConfigurerAdapter{

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new HandlerMethodArgumentResolver() {

            public boolean supportsParameter(MethodParameter parameter) {
                return findMethodAnnotation(CurrentUser.class, parameter) != null;
            }

            public Object resolveArgument(
                    MethodParameter parameter,
                    ModelAndViewContainer mavContainer,
                    NativeWebRequest webRequest,
                    WebDataBinderFactory binderFactory) throws Exception
            {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                Object principal = authentication.getPrincipal();

                if(principal != null && !parameter.getParameterType().isAssignableFrom(principal.getClass()))
                    throw new ClassCastException(principal + " is not assignable to " + parameter.getParameterType());

                return principal;
            }

            <T extends Annotation> T findMethodAnnotation(Class<T> annotationClass, MethodParameter parameter) {
                T annotation = parameter.getParameterAnnotation(annotationClass);
                if(annotation != null) {
                    return annotation;
                }
                Annotation[] annotationsToSearch = parameter.getParameterAnnotations();
                for(Annotation toSearch : annotationsToSearch) {
                    annotation = AnnotationUtils.findAnnotation(toSearch.annotationType(), annotationClass);
                    if(annotation != null) {
                        return annotation;
                    }
                }
                return null;
            }
        });
    }
}

@RequestMapping("/userget")
public User message(@CurrentUser User user){
    return user;
}

, User UserDetails anyamore. , (-)

0

Source: https://habr.com/ru/post/1608254/


All Articles