授权得客户端信息、授权码信息全都存在数据库
1.建表
官方给了个sql文件:https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
create table oauth_client_details ( client_id VARCHAR(128) PRIMARY KEY, resource_ids VARCHAR(128), client_secret VARCHAR(128), scope VARCHAR(128), authorized_grant_types VARCHAR(128), web_server_redirect_uri VARCHAR(128), authorities VARCHAR(128), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(128) ); create table oauth_client_token ( token_id VARCHAR(128), token BLOB, authentication_id VARCHAR(128) PRIMARY KEY, user_name VARCHAR(128), client_id VARCHAR(128) ); create table oauth_access_token ( token_id VARCHAR(128), token BLOB, authentication_id VARCHAR(128) PRIMARY KEY, user_name VARCHAR(128), client_id VARCHAR(128), authentication BLOB, refresh_token VARCHAR(128) ); create table oauth_refresh_token ( token_id VARCHAR(128), token BLOB, authentication BLOB ); create table oauth_code ( code VARCHAR(128), authentication BLOB ); create table oauth_approvals ( userId VARCHAR(128), clientId VARCHAR(128), scope VARCHAR(128), status VARCHAR(10), expiresAt TIMESTAMP, lastModifiedAt TIMESTAMP );
//造点测试数据
/*
INSERT INTO `oauth_client_details` VALUES ('client1', 'resource1', '$2a$10$YEpRG0cFXz5yfC/lKoCHJ.83r/K3vaXLas5zCeLc.EJsQ/gL5Jvum', 'scope1,scope2', 'authorization_code,password,client_credentials,implicit,refresh_token', 'http://www.baidu.com', null, '300', '1500', null, 'false');*/
2.配置数据源 yml里配置后注入到clientDetailService
server: port: 8001 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: root url: mysql://192.168.3.158:3306/test?&useUnicode=true&characterEncoding=utf-8
3.配置clientDetailService
@Autowired private DataSource dataSource; //配置客户端 @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //配置客户端存储到db 代替原来得内存模式 JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); clientDetailsService.setPasswordEncoder(passwordEncoder); clients.withClientDetails(clientDetailsService); }
4.授权码存到数据库
@Configuration public class TokenConfig { @Autowired private DataSource dataSource; //配置token的存储方法 @Bean public TokenStore tokenStore() { //配置token存储在数据库 return new JdbcTokenStore(dataSource); } }
//配置token管理服务 @Bean public AuthorizationServerTokenServices tokenServices() { DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); defaultTokenServices.setClientDetailsService(clientDetailsService); defaultTokenServices.setSupportRefreshToken(true); //配置token的存储方法 defaultTokenServices.setTokenStore(tokenStore); defaultTokenServices.setAccessTokenValiditySeconds(300); defaultTokenServices.setRefreshTokenValiditySeconds(1500); return defaultTokenServices; }
以上完整代码:
AuthorizationServerConfig
@Configuration //开启oauth2,auth server模式 @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Autowired private DataSource dataSource; //配置客户端 @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { //配置客户端存储到db JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); clientDetailsService.setPasswordEncoder(passwordEncoder); clients.withClientDetails(clientDetailsService); } @Autowired private ClientDetailsService clientDetailsService; @Autowired private TokenStore tokenStore; //配置token管理服务 @Bean public AuthorizationServerTokenServices tokenServices() { DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); defaultTokenServices.setClientDetailsService(clientDetailsService); defaultTokenServices.setSupportRefreshToken(true); //配置token的存储方法 defaultTokenServices.setTokenStore(tokenStore); defaultTokenServices.setAccessTokenValiditySeconds(300); defaultTokenServices.setRefreshTokenValiditySeconds(1500); return defaultTokenServices; } //密码模式才需要配置,认证管理器 @Autowired private AuthenticationManager authenticationManager; //把上面的各个组件组合在一起 @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager)//认证管理器 //配置授权码存储到db .authorizationCodeServices(new JdbcAuthorizationCodeServices(dataSource))//授权码管理 .tokenServices(tokenServices())//token管理 .allowedTokenEndpointRequestMethods(HttpMethod.POST); } //配置哪些接口可以被访问 @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()")///oauth/token_key公开 .checkTokenAccess("permitAll()")///oauth/check_token公开 .allowFormAuthenticationForClients();//允许表单认证 } }
TokenConfig
@Configuration public class TokenConfig { @Autowired private DataSource dataSource; //配置token的存储方法 @Bean public TokenStore tokenStore() { //配置token存储在内存中,这种是普通token,每次都需要远程校验,性能较差 return new JdbcTokenStore(dataSource); } }
WebSecurityConfig
@Configuration @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } //密码模式才需要配置,认证管理器 @Bean @Override protected AuthenticationManager authenticationManager() throws Exception { return super.authenticationManager(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .anyRequest().permitAll() .and() .formLogin() .and() .logout(); } @Bean public UserDetailsService userDetailsService() { return s -> { if ("admin".equals(s) || "user".equals(s)) { return new MyUserDetails(s, passwordEncoder().encode(s), s); } return null; }; } }
验证:
//授权码模式
//浏览器访问
http://127.0.0.1:8001/oauth/authorize?client_id=client1&response_type=code&scope=scope1&redirect_uri=http://www.baidu.com
授权码也存入了数据库:
postman申请令牌
已经存入了数据库
验证令牌