我结合了Jdbc身份验证提供程序和在授权服务器中配置的自定义身份验证提供程序。代码段如下所示。
SecurityConfig.java
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired(required = false)
private List<AuthenticationProvider> providers;
@Autowired
private DataSource dataSource;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/webjars/**").antMatchers(HttpMethod.OPTIONS, "/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/login","/oauth/authorize")
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.logout().permitAll()
.and()
.csrf().disable().cors().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder())
.usersByUsernameQuery("select username,password,enabled from tbl_users where username = ?")
.authoritiesByUsernameQuery("select username, role as authority from tbl_user_roles where username = ?");
if(providers !=null && !providers.isEmpty()) {
providers.stream().forEach(auth::authenticationProvider);
}
}
@Bean
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
AuthServerConfig.java
@Configuration
@EnableAuthorizationServer
@EnableConfigurationProperties(AuthorizationServerProperties.class)
@Import({AuthorizationServerTokenServicesConfiguration.class})
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired(required = false)
private AccessTokenConverter tokenConverter;
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource).passwordEncoder(passwordEncoder);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).userDetailsService(userDetailsService).reuseRefreshTokens(false);
if(tokenConverter != null) {
endpoints.accessTokenConverter(tokenConverter);
}
endpoints.tokenStore(tokenStore());
}
}
CustomAuthProvider.java
@Configuration
@Order(103)
public class CustomAuthProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = (String) authentication.getCredentials();
if("kp_user".equals(username) && "password".equals(password)) {
return new UsernamePasswordAuthenticationToken(username, password, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
}
return null;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
对于使用数据库注册的用户,使用刷新令牌进行身份验证和获取新的访问令牌的效果很好。
当我对自定义身份验证提供程序中存在的用户进行身份验证时,我可以进行身份验证并获取新的访问令牌和刷新令牌
curl -X POST \
http://localhost:8080/oauth/token \
-H 'Authorization: Basic Y2xpZW50XzE6c2VjcmV0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'username=kp_user&password=password&grant_type=password'
但是,当我尝试使用refresh_token为自定义身份验证提供程序中存在的用户获取新的访问令牌时,出现错误User kp_user not found
。
curl -X POST \
http://localhost:8080/oauth/token \
-H 'Authorization: Basic Y2xpZW50XzE6c2VjcmV0' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJrcF91c2VyIiwic2NvcGUiOlsicmVhZCIsIndyaXRlIiwidHJ1c3QiXSwiYXRpIjoiOTNmNDJkNWUtZDBkMy00YjgzLThkYjYtZDA1NTdhNmJkOWNhIiwiZXhwIjoxNTY1MDE0OTA3LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiMzM4MmEzYzctNzYwMi00YmY5LTk5YWItYjM2MTg5YmNiNzNkIiwiY2xpZW50X2lkIjoiY2xpZW50XzEifQ.KmB1vz4lIQYySkeQKR0HOyJEVepl-Z5R6LHJu3Zc7CA'
我不确定是否需要自定义DefaultTokenServices
,可以在here中找到源代码。