【发布时间】:2017-06-11 12:29:04
【问题描述】:
在我当前的项目中,我有一个应用程序,它有一个小图形片段,用户使用 SSO 进行身份验证,还有一部分是纯 API,用户使用 Authorization 标头进行身份验证。
例如:
-
使用 SSO 访问
/ping-other-service。 -
/api/ping-other-service使用不记名令牌访问
作为所有云原生应用,我们的应用程序使用 JWT 令牌 (UAA) 与使用相同 SSO 提供程序的其他服务通信,所以我想我们会使用 OAuth2RestTemplate,因为 according to the documentation 它可以神奇地插入身份验证凭据。它对所有使用 SSO 进行身份验证的端点执行此操作。但是,当我们使用通过承载令牌进行身份验证的端点时,它不会填充其余模板。
我的理解 from the documentation 是 @EnableOAuth2Client 只会从 SSO 登录中提取令牌,而不是 auth 标头?
我看到了什么
失败的请求及其作用:
-
curl -H "Authorization: Bearer <token>" http://localhost/api/ping-other-service - 内部使用 restTemplate 调用 http://some-other-service/ping 响应 401
成功的请求及其作用:
- 铬http://localhost/ping-other-service
- 内部使用 restTemplate 调用 http://some-other-service/ping 响应 200
我们是如何解决这个问题的
为了解决这个问题,我最终创建了以下怪物,如果无法从授权标头中获得令牌,它将从 OAuth2ClientContext 中提取令牌。
@PostMapping(path = "/ping-other-service")
public ResponseEntity ping(@PathVariable String caseId, HttpServletRequest request, RestTemplate restTemplate) {
try {
restTemplate.postForEntity(adapterUrl + "/webhook/ping", getRequest(request), Map.class);
} catch (HttpClientErrorException e) {
e.printStackTrace();
return new ResponseEntity(HttpStatus.SERVICE_UNAVAILABLE);
}
return new ResponseEntity(HttpStatus.OK);
}
private HttpEntity<?> getRequest(HttpServletRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + getRequestToken(request));
return new HttpEntity<>(null, headers);
}
private String getRequestToken(HttpServletRequest request) {
Authentication token = new BearerTokenExtractor().extract(request);
if (token != null) {
return (String) token.getPrincipal();
} else {
OAuth2AccessToken accessToken = oAuth2ClientContext.getAccessToken();
if (accessToken != null) {
return accessToken.getValue();
}
}
throw new ResourceNotFound("No valid access token found");
}
【问题讨论】:
标签: spring spring-boot spring-security