【OpenFeign Oauth2.0 认证非web请求验证实现】
-
功能实现定义
试想我们在使用OpenFeign 时,请求的资源服务为Oauth2.0认证资源服务器的时候,如果客户端为非web加粗样式情况, 例如:安卓,JAVAFX,C#,QT等客户端的时候,我们使用spring 提供的服务器Oauth2.0验证获取令牌的时候就不能实现,因为获取OAuth2AuthorizedClient的时候必须要OAuth2AuthorizeRequest对象为请求资源处理对象,但客户端非web的时候是不是就没有Request对象,或你根本就无法创建Request对象,那么下面的实例就让你能在客户端方式来获取令牌调用OpenFeign 请求资源服务器数据.该实例用于JAVAFX项目中,如果非要自己去实现非web令牌加载处理,官网提供的 Oauth2.0客户令牌管理可以参考:OAuth2AuthorizedClientManager接口实现:
- DefaultOAuth2AuthorizedClientManager
- AuthorizedClientServiceOAuth2AuthorizedClientManager
- TestOAuth2AuthorizedClientManager
自己可以慢慢参考去吧 -
说明:
OAuth 2.0定义了五种授权方式:
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
- 扩展模式(Extension)
此处只实现了一种方式(客户端模式(client credentials)), 其他授权认证方式根据情况自行调整实现即可. -
代码实现
/**
* LCH
* 功能:增加请求头 - 请求拦截器
*/
@Component
public class FeignConfig implements RequestInterceptor {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Autowired
private OkHttpClient okHttpClient;
@Autowired
private DiscoveryClient discoveryClient; // 服务列表
@Autowired
private ObjectMapper objectMapper;
@Override
public void apply(RequestTemplate requestTemplate) {
TokenEntity tokenEntity = tokenEntity();
if (tokenEntity != null && !tokenEntity.equals(null)) {
requestTemplate.header("Authorization",
// "Bearer 80c81bde-58ad-41f1-b404-4ef63e7782aa"
tokenEntity.getTokenType() + " " + tokenEntity.getAccessToken()
);
} else {
throw new RuntimeException("加载Authorization数据失败.");
}
}
@Bean
public Logger.Level feignLoggerLevel() {
ProcessDefinition d;
return Logger.Level.FULL;
}
/**
* 获取Token
*/
public TokenEntity tokenEntity() {
StringBuffer url = new StringBuffer();
ClientRegistration registration = clientRegistrationRepository.findByRegistrationId("client-id");
url.append(registration.getProviderDetails().getTokenUri() + "?")
.append("client_id=" + registration.getClientId() + "&")
.append("client_secret=" + registration.getClientSecret() + "&")
.append("grant_type=" + registration.getAuthorizationGrantType().getValue() + "&")
.append("scope=" + String.join(", ", registration.getScopes()));
TokenEntity entity = null;
// 加载数据
Request request = new Request.Builder()
.url(url.toString())
.build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.code() == 200) {
Map<String, Object> body = objectMapper.readValue(response.body().string(), objectMapper.getTypeFactory().constructMapType(HashMap.class, String.class, Object.class));
entity = new TokenEntity();
entity.setClientId(registration.getClientId());
entity.setClientSecret(registration.getClientSecret());
entity.setAccessToken(body.get("access_token").toString());
entity.setScope(body.get("scope").toString());
entity.setTokenType(body.get("token_type").toString());
entity.setExpiresIn(Long.valueOf(body.get("expires_in").toString()));
body = null;
} else {
System.out.println("Feign调用异常" + response.code() + ",异常:" + response.body().string());
}
response.close();
response = null;
} catch (IOException e) {
e.printStackTrace();
}
url = null;
registration = null;
request = null;
return entity;
}
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class TokenEntity {
private String clientId;
private String clientSecret;
private String accessToken;
private String scope;
private String tokenType;
private Long expiresIn;
}
}