文档说明
最近在搭建oauth2.0服务器,发现自己能找到的文章要么是1.5版本,要么就是内存存储,所以自己用mysql搭建了一个授权服务器(client和user都用数据库)
核心代码
授权服务器
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DataSource dataSource;
@Autowired
private TokenStore tokenStore;
@Autowired(required = false)
private JwtAccessTokenConverter jwtAccessTokenConverter;
@Autowired(required = false)
private TokenEnhancer jwtTokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore)
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
if (jwtAccessTokenConverter != null && jwtTokenEnhancer != null) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
List<TokenEnhancer> enhancerList = new ArrayList();
enhancerList.add(jwtTokenEnhancer);
enhancerList.add(jwtAccessTokenConverter);
tokenEnhancerChain.setTokenEnhancers(enhancerList);
endpoints.tokenEnhancer(tokenEnhancerChain)
.accessTokenConverter(jwtAccessTokenConverter);
}
}
@Bean
public ClientDetailsService clientDetails() {
JdbcClientDetailsService jdbcClientDetailsService=new JdbcClientDetailsService(dataSource);
jdbcClientDetailsService.setPasswordEncoder(new BCryptPasswordEncoder());
return jdbcClientDetailsService;
}
/**
* <p>注意,自定义TokenServices的时候,需要设置@Primary,否则报错,</p>
*
* @return
*/
@Primary
@Bean
public DefaultTokenServices defaultTokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore);
tokenServices.setSupportRefreshToken(true);
tokenServices.setClientDetailsService(clientDetails());
// token有效期自定义设置,默认12小时
tokenServices.setAccessTokenValiditySeconds(60 * 60 * 12);
//默认30天,这里修改
tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);
return tokenServices;
}
/**
* 配置客户端一些信息
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetails());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.allowFormAuthenticationForClients()
.checkTokenAccess("permitAll()")
.passwordEncoder(NoOpPasswordEncoder.getInstance());
}
security配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().and()
.csrf().disable();
}
}
常见问题
- Encoded password does not look like BCrypt
- id is null
解决方式
因为springsecurity在最新版本升级后,默认把之前的明文密码方式给去掉了官方文档说明;
解决方式:
- 一般我们客户端账号密码不需要加密,所以在这里实现 .passwordEncoder(NoOpPasswordEncoder.getInstance()) 告诉security客户端密码不需要加密
- 使用BCryptPasswordEncoder将数据库中client密码加密