SpringSecurityOAuth2客户端模式集成Springboot项目
一、导入maven依赖
<!--oauth-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.3.4</version>
</dependency>
二、配置类继承AuthorizationServerConfigurerAdapter
/**
* 认证授权配置
* @author ry
* @date 2021/11/17 14:15
*/
@Configuration
@EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private AuthenticationManager authenticationManager;
/**
* 从数据库中查询出客户端信息
* @return
*/
@Bean
public JdbcClientDetailsService clientDetailsService() {
JdbcClientDetailsService detailsService = new JdbcClientDetailsService(dataSource);
detailsService.setPasswordEncoder(new BCryptPasswordEncoder());
return detailsService;
}
/**
* token保存至数据库
* @return
*/
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
// 如要保存至内存可以切换
//return new InMemoryTokenStore();
}
/**
* 授权信息保存至数据库
* @return
*/
@Bean
public ApprovalStore approvalStore() {
return new JdbcApprovalStore(dataSource);
}
/**
* 授权码模式专用对象
* @return
*/
//@Bean
//public AuthorizationCodeServices authorizationCodeServices() {
// return new JdbcAuthorizationCodeServices(dataSource);
//}
/**
* 指定客户端登录信息来源
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//从数据库取数据
clients.withClientDetails(clientDetailsService());
}
/**
* 检测token的策略
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
//允许form表单客户端认证,允许客户端使用client_id和client_secret获取token
security.allowFormAuthenticationForClients()
//通过验证返回token信息
.checkTokenAccess("isAuthenticated()")
// 获取token请求不进行拦截
.tokenKeyAccess("permitAll()")
// 允许表单认证
.allowFormAuthenticationForClients()
.passwordEncoder(new BCryptPasswordEncoder());
}
/**
* OAuth2的主配置信息
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
//指定授权信息保存至数据库
.approvalStore(approvalStore())
//指定授权管理器
.authenticationManager(authenticationManager)
//授权码模式使用
//.authorizationCodeServices(authorizationCodeServices())
//指定客户端token保存位置等信息
.tokenServices(tokenServices())
//指定请求方式
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
//.reuseRefreshTokens(true);
}
@Bean
public AuthorizationServerTokenServices tokenServices(){
DefaultTokenServices tokenServices = new DefaultTokenServices();
//设置客户端详情
tokenServices.setClientDetailsService(clientDetailsService());
设置token自动刷新
//tokenServices.setSupportRefreshToken(true);
储存token
tokenServices.setTokenStore(tokenStore());
设置token过期时间为12小时(适用于token储存到内存模式)
//tokenServices.setAccessTokenValiditySeconds(43200);
//tokenServices.setRefreshTokenValiditySeconds(72000);
return tokenServices;
}
}
注意:测试前要新建两张表
1.储存客户端详情表:配置客户端的信息
CREATE TABLE oauth_client_details
(
client_id
varchar(48) NOT NULL,
resource_ids
varchar(256) DEFAULT NULL,
client_secret
varchar(256) DEFAULT NULL,
scope
varchar(256) DEFAULT NULL,
authorized_grant_types
varchar(256) DEFAULT NULL,
web_server_redirect_uri
varchar(256) DEFAULT NULL,
authorities
varchar(256) DEFAULT NULL,
access_token_validity
int(11) DEFAULT NULL,
refresh_token_validity
int(11) DEFAULT NULL,
additional_information
varchar(4096) DEFAULT NULL,
autoapprove
varchar(256) DEFAULT NULL,
PRIMARY KEY (client_id
)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.储存token信息表:
CREATE TABLE oauth_access_token
(
token_id
varchar(255) DEFAULT NULL,
token
blob,
authentication_id
varchar(255) DEFAULT NULL,
user_name
varchar(255) DEFAULT NULL,
client_id
varchar(255) DEFAULT NULL,
authentication
blob,
refresh_token
varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
三、配置类继承WebSecurityConfigurerAdapter
/**
* 资源安全配置
* @author ry
* @date 2021/11/17 14:31
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
三、配置类继承ResourceServerConfigurerAdapter
/**
* 认证授权配置
*
* @author ry
* @date 2021/11/18 9:32
*/
@Configuration
@EnableResourceServer
public class Oauth2ResourceServer extends ResourceServerConfigurerAdapter {
private static final String TEST= "test";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// 指定资源可以访问,有多个资源可以继续添加,对应表里的字段值,表里多个字段值用逗号隔开
resources.resourceId(TEST).stateless(true);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
http.authorizeRequests()
//指定不同请求方式访问资源所需要的权限。
.antMatchers(HttpMethod.POST, "/test1").access("#oauth2.hasScope('test1')")
.antMatchers(HttpMethod.POST, "/test2").access("#oauth2.hasScope('test2')")
.and()
.headers().addHeaderWriter((request, response) -> {
response.addHeader("Access-Control-Allow-Origin", "*");//允许跨域
if (request.getMethod().equals("OPTIONS")) {//如果是跨域的预检请求,则原封不动向下传达请求头信息
response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
}
});
}
}