我正在使用Spring Security OAuth2 2.0.7.RELEASE。当我使用ORM连接到数据库并且默认JdbcUserDetailsManager使用jdbc时,我想实现自己的UserDetailsService,即
@Service public class UserService implements UserDetailsService { @Override public UserDetailsService loadUserByUsername(String username) throws UsernameNotFoundException { // I tested this logic and works fine so i avoid this lines return userDetailsService; } }
此外,我修改了权限架构,如下所示:
mysql> describe authorities; +--------------+---------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+---------------------+------+-----+---------+----------------+ | authority_id | bigint(20) unsigned | NO | PRI | NULL | auto_increment | | user_id | bigint(20) unsigned | NO | MUL | NULL | | | authority | varchar(256) | NO | | NULL | | +--------------+---------------------+------+-----+---------+----------------+
然后,我像这样注入我的自定义userDetailsService:
@Configuration @Import(OAuth2SupportConfig.class) @EnableAuthorizationServer public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { ... @Autowired private UserDetailsService userDetailsService @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager) .tokenStore(tokenStore).tokenServices(tokenService); endpoints.userDetailsService(userDetailsService); // Inject custom endpoints.authorizationCodeServices(authorizationCodeServices); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource); } } @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) public class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private UserDetailsService userService; @Override public void init(AuthenticationManagerBuilder auth) throws Exception { auth.jdbcAuthentication().dataSource(this.dataSource).and().userDetailsService(this.userService);// Inject custom } }
如果我使用Grant_type = password发送/ oauth / token请求,则会出现此错误
POST /oauth/token HTTP/1.1 Host: localhost:8080 Authorization: Basic aW5kaXJhOnNlY3JldA== Cache-Control: no-cache Postman-Token: c89baf37-8ad2-4270-5251-9715bfab470a Content-Type: application/x-www-form-urlencoded grant_type=password&username=user&password=pass
(其中对clientId和clientSecret进行编码)
{ "error": "unauthorized", "error_description": "PreparedStatementCallback; bad SQL grammar [select username,authority from authorities where username = ?]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'username' in 'field list'" }
显然仍在使用默认的JdbcDaoImpl。实际上,当我开始调试时,我发现遵循以下步骤:
我不知道为什么会这样。对我来说,这听起来像个虫子。你有没有发现什么问题?
您正在使用auth.jdbcAuthentication().dataSource(this.dataSource).and().userDetailsService(this.userService);// Inject custom,我在这里正在创建两个auth管理器- 一个具有默认值JdbcDaoImpl并dataSource指向auth管理器this.dataSource,另一个具有您的custom userService。尝试仅放置auth.userDetailsService(this.userService)(我希望userService已经在内部自动连接了jdbc)。
auth.jdbcAuthentication().dataSource(this.dataSource).and().userDetailsService(this.userService);// Inject custom
JdbcDaoImpl
dataSource
this.dataSource
userService
auth.userDetailsService(this.userService)
这里的要点.and()是用于向身份验证管理器添加不同的身份验证配置,而不是配置jdbcAuthentication()一个。
.and()
jdbcAuthentication()