例子基于Spring Boot 2.1.7.RELEASE ,使用mysql数据库
本例中资源服务为独立的应用
参考资源: Resource Server Configuration
ResourceServerConfigurer
接口的实现类且使用@EnableResourceServer
注解进行标注ResourceServerConfigurer
接口有一个实现类ResourceServerConfigurerAdapter
,这里我们继承这个类
/**
* Created by liuquan on 2019/8/13.
*/
@Configuration
@EnableResourceServer
public class CustomResourceServerConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
}
@Override
public void configure(HttpSecurity http) throws Exception {
}
}
@EnableResourceServer
注解会导入一个配置类ResourceServerConfiguration
protected void configure(HttpSecurity http) throws Exception {
ResourceServerSecurityConfigurer resources = new ResourceServerSecurityConfigurer();
ResourceServerTokenServices services = resolveTokenServices();
if (services != null) {
resources.tokenServices(services);
}
else {
if (tokenStore != null) {
resources.tokenStore(tokenStore);
}
else if (endpoints != null) {
resources.tokenStore(endpoints.getEndpointsConfigurer().getTokenStore());
}
}
if (eventPublisher != null) {
resources.eventPublisher(eventPublisher);
}
for (ResourceServerConfigurer configurer : configurers) {
configurer.configure(resources);
}
// @formatter:off
http.authenticationProvider(new AnonymousAuthenticationProvider("default"))
// N.B. exceptionHandling is duplicated in resources.configure() so that
// it works
.exceptionHandling()
.accessDeniedHandler(resources.getAccessDeniedHandler()).and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.csrf().disable();
// @formatter:on
http.apply(resources);
if (endpoints != null) {
// Assume we are in an Authorization Server
http.requestMatcher(new NotOAuthRequestMatcher(endpoints.oauth2EndpointHandlerMapping()));
}
for (ResourceServerConfigurer configurer : configurers) {
// Delegates can add authorizeRequests() here
configurer.configure(http);
}
if (configurers.isEmpty()) {
// Add anyRequest() last as a fall back. Spring Security would
// replace an existing anyRequest() matcher with this one, so to
// avoid that we only add it if the user hasn't configured anything.
http.authorizeRequests().anyRequest().authenticated();
}
第二行,在创建ResourceServerSecurityConfigurer
对象时会默认设置resourceId属性值为oauth2-resource
第三行,从系统中获取ResourceServerTokenServices
对象,系统提供了两个实现类(DefaultTokenServices
、RemoteTokenServices
),本例中采用RemoteTokenServices
第十八行,循环调用ResourceServerConfigurer
对象中的configure(ResourceServerSecurityConfigurer resources)
方法
第三十六行,循环调用ResourceServerConfigurer
对象中的configure(HttpSecurity http)
方法
创建两个服务接口
@Controller
public class ApiController {
@RequestMapping(value = "/serverA")
@ResponseBody
public Map<String,String> serverA(){
Map<String,String> resourceInfo = new HashMap<>();
resourceInfo.put("serverName","serverA");
return resourceInfo;
}
@RequestMapping(value = "/serverB")
@ResponseBody
public Map<String,String> serverB(){
Map<String,String> resourceInfo = new HashMap<>();
resourceInfo.put("serverName","serverB");
return resourceInfo;
}
}
@Configuration
@EnableResourceServer
public class CustomResourceServerConfigurer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("resource");//每个资源服务都有一个唯一的ID
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/serverA").permitAll()//不需要验证
.antMatchers("/serverB").authenticated();//需要通过验证
}
}
/**
* Created by liuquan on 2019/8/14.
*/
@Configuration
public class RemoteTokenService {
@Autowired
private Environment environment;
@Bean
public ResourceServerTokenServices tokenServices(){
RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setCheckTokenEndpointUrl(environment.getProperty("security.oauth2.checkTokenAccess"));
remoteTokenServices.setClientId(environment.getProperty("security.oauth2.client.clientid"));
remoteTokenServices.setClientSecret(environment.getProperty("security.oauth2.client.clientSecret"));
return remoteTokenServices;
}
}
server.port=8082
spring.datasource.url=jdbc:mysql://localhost:3306/part01?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
security.oauth2.client.clientid=app
security.oauth2.client.clientSecret=app
security.oauth2.checkTokenAccess=http://localhost:8081/oauth/check_token