@AuthenticationPrincipal 与 Spring Boot 不工作

Posted

技术标签:

【中文标题】@AuthenticationPrincipal 与 Spring Boot 不工作【英文标题】:@AuthenticationPrincipal with Spring Boot not working 【发布时间】:2016-05-11 10:19:57 【问题描述】:

使用 Spring Boot 1.3.1,@AuthenticationPrincipal 出现问题。

这是我的控制器:

@RestController
@RequestMapping("/api/user")
public class UserController 

    @RequestMapping("/")
    public UserDto user(@AuthenticationPrincipal(errorOnInvalidType = true) User user) 
        return UserDto.fromUser(user);
    

这是我的自定义用户类:

@Entity()
@Table(name = "app_user")
public class User extends AbstractEntity<UserId> implements Serializable 
// ------------------------------ FIELDS ------------------------------

    @NotNull
    @Column(unique = true)
    @Pattern(regexp = "[a-zA-Z_\\-\\.0-9]+")
    @Size(min = 1, max = 20)
    private String username;
    private String password;
    @Column(unique = true)
    @Email
    private String emailAddress;
    @Enumerated(EnumType.STRING)
    @NotNull
    private UserRole role;

我还创建了一个类来确认Spring Security的UserDetails接口:

public class CustomUserDetails extends User implements UserDetails 

    public CustomUserDetails(User user) 
        super(user);
    

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() 
        return Sets.newHashSet(new SimpleGrantedAuthority("ROLE_" + getRole().name()));
    

    @Override
    public boolean isAccountNonExpired() 
        return true;
    

    @Override
    public boolean isAccountNonLocked() 
        return true;
    

    @Override
    public boolean isCredentialsNonExpired() 
        return true;
    

    @Override
    public boolean isEnabled() 
        return true;
    

然后在我的UserDetailsService:

@Override
public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
    com.company.app.domain.account.User user = userRepository.findByUsername(username);

    if (user != null) 
        return new CustomUserDetails(user);
     else 
        throw new UsernameNotFoundException(format("User %s does not exist!", username));
    

我有一个完美运行的集成测试。但是,运行应用程序本身(来自 IntelliJ IDEA)不起作用。我得到一个例外:

"CustomUserDetailsid=UserIdid=401868de-99ff-4bae-bcb6-225e3062ed33 is not assignable to class com.company.app.domain.account.User"

但这不是真的,因为CustomUserDetails 是我的自定义User 类的子类。

用调试器检查,我看到AuthenticationPrincipalArgumentResolver中的这段代码失败了:

if (principal != null
            && !parameter.getParameterType().isAssignableFrom(principal.getClass())) 

parameter.getParameterType() 的类加载器是RestartClassloader 的实例,而principal.getClass() 的类加载器是Launcher$AppClassLoader 的实例。

这是 Spring Boot 或 Spring Security 中的错误还是我做错了什么?

更新:

我可以确认禁用 Spring Boot 的 devtools 使其工作:

public static void main(String[] args) 
    System.setProperty("spring.devtools.restart.enabled", "false");
    SpringApplication.run(MyApplication.class, args);

【问题讨论】:

【参考方案1】:

为了帮助遇到同样问题的其他人,这是 Spring Boot DevTools 和 Spring Security OAuth 中的一个限制。本期正在跟踪:https://github.com/spring-projects/spring-boot/issues/5071

【讨论】:

作为一种解决方法,使用InMemoryTokenStore 而不是JDBCTokenStore

以上是关于@AuthenticationPrincipal 与 Spring Boot 不工作的主要内容,如果未能解决你的问题,请参考以下文章

@AuthenticationPrincipal 是如何工作的?

@AuthenticationPrincipal 与 Spring Boot 不工作

@AuthenticationPrincipal 返回空用户

使用 @AuthenticationPrincipal 注入自定义 OidcUser 包装器

使用 EnableWebSecurity 时 AuthenticationPrincipal 为空

AuthenticationPrincipal 返回空的 UserDetails 对象