当使用Spring OAuth2 Jdbc令牌存储时,无法填充User对象



我用一个基于jdbc的令牌存储更新了Roy Clarkson的Spring REST服务(https://github.com/royclarkson/spring-rest-service-oauth)。最初的实现使用内存中的令牌存储。我可以在user对象中看到用户的详细信息。另一方面,在切换到基于jdbc的令牌存储之后,User对象中的所有字段都为空。当我使用基于jdbc的令牌存储时,Spring安全性似乎无法将访问令牌与获得令牌的用户关联起来。

内存令牌存储实现:

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
        AuthorizationServerConfigurerAdapter {
    @Autowired
    private DataSource dataSource;
    private TokenStore tokenStore = new InMemoryTokenStore();
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Bean
    public ClientDetailsService clientDetailsService() {
        return new JdbcClientDetailsService(dataSource);
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        // @formatter:off
        endpoints
            .tokenStore(this.tokenStore)
            .authenticationManager(this.authenticationManager)
            .userDetailsService(userDetailsService);
        // @formatter:on
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .withClientDetails(clientDetailsService);
    }
    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(this.tokenStore);
        return tokenServices;
    }
}

REST端点:

@RequestMapping("/greeting")
public Greeting greeting(@AuthenticationPrincipal User user) {
    return new Greeting(counter.incrementAndGet(), String.format(template, user.getName()));
}

user. getname()返回获得访问令牌的用户名。

jdbc令牌存储实现:
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
        AuthorizationServerConfigurerAdapter {
    @Autowired
    private DataSource dataSource;
    @Autowired
    private TokenStore tokenStore;
    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Bean
    public ClientDetailsService clientDetailsService() {
        return new JdbcClientDetailsService(dataSource);
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        // @formatter:off
        endpoints
            .tokenStore(this.tokenStore)
            .authenticationManager(this.authenticationManager)
            .userDetailsService(userDetailsService);
        // @formatter:on
    }
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .withClientDetails(clientDetailsService);
    }
    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(this.tokenStore);
        return tokenServices;
    }
}

REST端点:

@RequestMapping("/greeting")
public Greeting greeting(@AuthenticationPrincipal User user) {
    return new Greeting(counter.incrementAndGet(), String.format(template, user.getName()));
}

user.getName()返回null。

CustomUserDetailsService

@Service
public class CustomUserDetailsService implements UserDetailsService {
    private final UserRepository userRepository;
    @Autowired
    public CustomUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByLogin(username);
        if (user == null) {
            throw new UsernameNotFoundException(String.format("User %s does not exist!", username));
        }
        return new UserRepositoryUserDetails(user);
    }
    private final static class UserRepositoryUserDetails extends User implements UserDetails {
        private static final long serialVersionUID = 1L;
        private UserRepositoryUserDetails(User user) {
            super(user);
        }
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return getRoles();
        }
        @Override
        public String getUsername() {
            return getLogin();
        }
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
}
用户

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    @NotEmpty
    private String name;
    @NotEmpty
    @Column(unique = true, nullable = false)
    private String login;
    @NotEmpty
    private String password;
    @NotEmpty
    private String privilege;
    @JsonIgnore
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = { @JoinColumn(name = "role_id") })
    private Set<Role> roles = new HashSet<Role>();
    public User() {
    }
    public User(User user) {
        super();
        this.id = user.getId();
        this.name = user.getName();
        this.login = user.getLogin();
        this.password = user.getPassword();
        this.roles = user.getRoles();
        this.privilege = user.getPrivilege();
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getLogin() {
        return login;
    }
    public void setLogin(String login) {
        this.login = login;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getPrivilege() {return privilege; }
    public void setPrivilege(String privilege) {this.privilege = privilege; }
    public Set<Role> getRoles() {
        return roles;
    }
    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
}

问题是你正在创建的"UserRepositoryUserDetails"是不可序列化的。

UserRepositoryUserDetails正在实现"UserDetails",这是可序列化的,但类它正在扩展"用户"是不可序列化的。

你必须得到一个警告,也从编译器添加一个serialId。

<<p> 解决方案/strong>

将UserRepositoryUserDetails设置为可序列化的。

设置用户类可序列化后一切正常

最新更新