我正在使用springboot创建一个应用程序,该应用程序将使用具有OAuth2身份验证的API。成功获取Bearer代码后,我将调用另一个API,该API实际上将为我提供数据以进行进一步处理。我有自定义的OAuth网址,授权代码,用户名,密码,密钥,api密钥。当我在互联网上搜索时,所有这些示例都没有使用[仅使用了秘密密钥,授权码和api密钥。]。我还需要使用用户名和密码吗?
我尝试了下面的代码[和其他一些东西]。但是无法解决这个问题。
<code>
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.DatatypeConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.support.BasicAuthorizationInterceptor;
import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class ApiConsumer {
@Autowired
private RestTemplate template;
@Value("${oauth.api}")
String url;
@Value("${oauth.oAuth.url}")
String oAuthUrl;
@Value("${oauth.user}")
String username;
@Value("${oauth.password}")
String password;
@Value("${oauth.apikey}")
String apiKey;
@Value("${oauth.secretkey}")
String apiSecret;
public String postData() {
log.info("Call API");
try {
String response = consumeApi();
if (response.equals("200")) {
log.info("posting data to another api");
// CALL another API HERE for actual data with bearer code
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
private String consumeApi() throws Exception {
String authorizationHeader = "Basic "
+ DatatypeConverter.printBase64Binary((apiKey + ":" + apiSecret).getBytes());
// setting up the HTTP Basic Authentication header value
HttpHeaders requestHeaders = new HttpHeaders();
// set up HTTP Basic Authentication Header
requestHeaders.add("Authorization", authorizationHeader);
requestHeaders.add("Accept", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
requestHeaders.add("response_type", "code");
// request entity is created with request headers
HttpEntity<String> request = new HttpEntity<String>(requestHeaders);
template.getInterceptors().add(new BasicAuthorizationInterceptor(username, password));
ResponseEntity<String> result = null;
try {
result = template.exchange(oAuthUrl, HttpMethod.POST, request, String.class);
log.info( result.getBody());
if (result.getStatusCode() == HttpStatus.OK) {
transformData(result.getBody());
}
if (result.getStatusCode() != HttpStatus.REQUEST_TIMEOUT) {
throw new Exception("Api taking too long to respond! ");
}
}
catch (Exception e) {
log.error("Api taking too long to respond!");
}
return "";
}
private void transformData(String body) throws JsonMappingException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
List<HeapEntity> heapEntityList = Arrays.asList(mapper.readValue(body, HeapEntity[].class));
if (heapEntityList != null && heapEntityList.size() > 0) {
heapEntityList.forEach(i -> i.getPhoneNumber().replaceAll("-", ""));
}
log.debug("Size of list is :: " + heapEntityList.size());
heapEntityList.add(null);
}
}
</code>
不幸的是,我无法直接回答您的问题,因为不清楚您要使用哪种grant type,这将确定问题的答案,是否需要使用用户名和密码。
我建议您熟悉Section 4 of RFC 6749,在其中您将找到有关该标准支持的所有授予类型的信息,以及它们所需的请求参数。
密码授予类型的示例:
如果需要使用RestTemplate
,则可以执行以下操作:
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/x-www-form-urlencoded");
headers.set("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString((clientId + ":" + clientSecret).getBytes()));
String body = String.format("grant_type=password&username=%s&password=%s", username, password);
String json = restTemplate.postForObject(tokenUrl, new HttpEntity<>(body, headers), String.class);
请注意,响应是一个包含令牌的json对象,而不是令牌本身。
或者您可以简单地使用更适合您的目的OAuth2RestTemplate
:
@Bean
public OAuth2RestTemplate oAuth2RestTemplate() {
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setClientAuthenticationScheme(AuthenticationScheme.form);
resource.setAccessTokenUri("tokenUrl");
resource.setClientId("clientId");
resource.setClientSecret("clientSecret");
resource.setUsername("username");
resource.setPassword("password");
return new OAuth2RestTemplate(resource);
}
[不要忘记将@EnableOAuth2Client
添加到您的配置类之一。