下面的例子是spring boot项目中,访问Oauth2资源服务器的资源接口(非集群环境下)。
maven pom文件需要引入对spring cloud相关依赖:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
为了使用feign组件,我们增加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<exclusions>
<!--配置中心去掉,会自动连接 -->
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>8.18.0</version>
</dependency>
为了使用spring boot 的自动配置,我们需要引入 @EnableFeignClients 注解,自动扫描Feign相关代码。
@SpringBootApplication(
exclude = {DataSourceAutoConfiguration.class,
MybatisAutoConfiguration.class,
JpaRepositoriesAutoConfiguration.class,
HibernateJpaAutoConfiguration.class},
scanBasePackages = {"com.sdcuike.practice",
"com.sdcuike.spring.controller.advice"})
@EnableFeignClients
@Slf4j
public class Application {
public static void main(String[] args) throws UnknownHostException {
SpringBootApplicationUtil.runSpringBootApplication(log, args, Application.class);
}
}
为了访问资源服务器上的资源,我们定义demo接口:
/**
* Created by beaver on 2017/5/27.<br>
* <p>
* {@link https://jmnarloch.wordpress.com/2015/10/14/spring-cloud-feign-oauth2-authentication }
*/
@FeignClient(name = "exampleService",
url = "${exampleService.ribbon.listOfServers}",
configuration = {OAuth2FeignAutoConfiguration.class})
@RequestMapping(value = "/springBoot/example"
, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE
, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public interface ExampleServiceFeignClient {
@GetMapping("/")
ModelResult<String> home();
}
由于spring-cloud-feign对feign做了扩展,所以,我们可以使用spring的web相关注解,来使用feign,大大方便了我们的spring 应用。其关键的配置在于:
@FeignClient(name = "exampleService",
url = "${exampleService.ribbon.listOfServers}",
configuration = {OAuth2FeignAutoConfiguration.class})
注解中name属性最新版本必须要求有,而url的出现,主要显示的配置feign访问的服务地址。 OAuth2FeignAutoConfiguration类主要是feign组件利用Oauth2的认证token来访问资源服务器上的资源。
/**
* Created by beaver on 2017/6/3.
*/
@Configuration
public class OAuth2FeignAutoConfiguration {
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor(@Qualifier("practiceOAuth2RestTemplate") OAuth2RestTemplate oAuth2RestTemplate) {
return new OAuth2FeignRequestInterceptor(oAuth2RestTemplate);
}
}
/**
* Created by beaver on 2017/6/3.
*/
public class OAuth2FeignRequestInterceptor implements RequestInterceptor {
private final Logger LOGGER = LoggerFactory.getLogger(getClass());
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String BEARER_TOKEN_TYPE = "Bearer";
private final OAuth2RestTemplate oAuth2RestTemplate;
public OAuth2FeignRequestInterceptor(OAuth2RestTemplate oAuth2RestTemplate) {
Assert.notNull(oAuth2RestTemplate, "Context can not be null");
this.oAuth2RestTemplate = oAuth2RestTemplate;
}
@Override
public void apply(RequestTemplate template) {
LOGGER.debug("Constructing Header {} for Token {}", AUTHORIZATION_HEADER, BEARER_TOKEN_TYPE);
template.header(AUTHORIZATION_HEADER,
String.format("%s %s",
BEARER_TOKEN_TYPE,
oAuth2RestTemplate.getAccessToken().toString()));
}
}
其主要思路是利用feign的的扩展RequestInterceptor,对于每次请求我们自动设置Oauth2的AccessToken 头信息。
对于Oauth2ClientConfig 的配置在此不再复述,具体请看代码: https://github.com/sdcuike/spring-boot-oauth2-demo/tree/blog-2017-07-16/spring-boot-oauth-resource-server/src/main/java/com/sdcuike/practice