我需要调用Oauth2 ResT API服务从JSON文件中获取访问令牌和expire_in值。
以下是我需要用JAVA调用的CURL示例,我是JAVA初学者,所以不知道怎么做,但是我可以用shell脚本来做。
curl -u 'ClientId:Clientaccesskey' https://oauth2.url/oauth/token -X POST -d 'response_type=token&client_id=ClientId&username=user&password=userpassword&scope=process&grant_type=password'
上面的curl命令得到的JSON样本 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
{"access_token":"accessTokentobefetched","token_type":"bearer","refresh_token":"refreshToken","expires_in":7199,"scope":"process","jti":"somehexadecimalvaliu"}
在shell脚本中,我们可以使用AWK命令和其他命令来获取访问令牌和其他字段的值,所以我需要在JAVA中调用这个CURL命令,从JSON文件中获取访问令牌和其他键的值。
所以我需要在JAVA中调用这个CURL命令,从JSON文件中获取访问令牌和其他键值。
由于我是一个新的JAVA学习者,欢迎任何能帮助我开始这项工作的帮助。
你没有明确说明这个标记将在什么情况下使用,但我假设你正在创建一个需要访问资源服务器的客户端应用程序。
似乎你需要访问授权服务器返回的值。
你可能会发现像这样的库很有意义。oauth2-essentials. 以下是他们的例子。
初始化客户机
// Create HttpRequestExecutor to execute HTTP requests
// Any other HttpRequestExecutor implementaion will do
HttpRequestExecutor executor = new HttpUrlConnectionExecutor();
// Create OAuth2 provider
OAuth2AuthorizationProvider provider = new BasicOAuth2AuthorizationProvider(
URI.create("http://example.com/auth"),
URI.create("http://example.com/token"),
new Duration(1,0,3600) /* default expiration time in case the server doesn't return any */);
// Create OAuth2 client credentials
OAuth2ClientCredentials credentials = new BasicOAuth2ClientCredentials(
"client-id", "client-password");
// Create OAuth2 client
OAuth2Client client = new BasicOAuth2Client(
provider,
credentials,
new LazyUri(new Precoded("http://localhost")) /* Redirect URL */);
授权代码 拨款
// Start an interactive Authorization Code Grant
OAuth2InteractiveGrant grant = new AuthorizationCodeGrant(
client, new BasicScope("scope"));
// Get the authorization URL and open it in a WebView
URI authorizationUrl = grant.authorizationUrl();
// Open the URL in a WebView and wait for the redirect to the redirect URL
// After the redirect, feed the URL to the grant to retrieve the access token
OAuth2AccessToken token = grant.withRedirect(redirectUrl).accessToken(executor);
来自 [OAuth2AccessToken](https://github.com/dmfs/oauth2-essentials/blob/master/src/main/java/org/dmfs/oauth2/client/OAuth2AccessToken.java)
然后你可以使用以下方法来访问token的内容。
public CharSequence token.accessToken()
public CharSequence tokenType()
public boolean hasRefreshToken()
public CharSequence refreshToken()
public DateTime expirationDate()
public OAuth2Scope scope()
访问此链接查看如何将此依赖关系添加到你的mavengradle项目中。
OAuth2 Essentials " 0.18 - 最新的版本是从2019年9月开始的,在写这篇文章的时候是0.18版本。
然而,如果你发现自己在Spring应用中,有很好的支持。而且,你将永远不会真正需要处理令牌本身。考虑一下Spring是否适合你的应用--看看这个。Spring安全OAuth. 注意 SPring安全OAuth 包最近已经被去掉了 -- 网上有很多文档现在已经和它一起被去掉了,请查看迁移指南了解更多信息。
你可能还想看看其他可用的库来帮助你使用oauth2,包括服务器端和客户端,这里有一个很好的列表。
有相当多的库可以用来帮助你从Java中发出一个常规的HTTP POST请求,但由于你似乎需要发送普通的 text/plain
体含量--我建议你用 okhttp3. 这是一个相当轻量级且易于使用的HTTP客户端。
您将需要在您的pom.xml中添加以下依赖关系,这些依赖关系是从 https:/mvnrepository.comartifactcom.squareup.okhttp3okhttp4.7.2。:
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.7.2</version>
</dependency>
如果你使用的是gradle,只要访问前面提到的URL,就可以得到gradle对应的依赖声明。
这里是一个完整的类,说明如何使用okhttp3客户端来执行POST请求,并提取返回值。这个例子希望你使用的是 spring-boot-starter-web
依赖关系 (这将包括本例中使用的 jackson 和 tomcat 库)。
package com.example.demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Component
public class TokenRequester {
public String getAccessToken() throws IOException {
// Create a new HTTP client
OkHttpClient client = new OkHttpClient().newBuilder().build();
// Create the request body
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create("response_type=token&client_id=ClientId&username=user&password=userpassword&scope=process&grant_type=password", mediaType);
// Build the request object, with method, headers
Request request = new Request.Builder()
.url("https://oauth2.url/oauth/token")
.method("POST", body)
.addHeader("Authorization", createAuthHeaderString("ClientId", "Clientaccesskey"))
.addHeader("Content-Type", "text/plain")
.build();
// Perform the request, this potentially throws an IOException
Response response = client.newCall(request).execute();
// Read the body of the response into a hashmap
Map<String,Object> responseMap = new ObjectMapper().
readValue(response.body().byteStream(), HashMap.class);
// Read the value of the "access_token" key from the hashmap
String accessToken = (String)responseMap.get("access_token");
// Return the access_token value
return accessToken;
}
// Just a helper metod to create the basic auth header
private String createAuthHeaderString(String username, String password) {
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.US_ASCII));
String authHeader = "Basic " + new String(encodedAuth);
return authHeader;
}
}
你可能需要调整一些东西。我可以要求你提供curl命令的详细输出,以便确定编码--但试试这个,看看你能得到什么?
下面是一个只涉及Spring的解决方案,在POST请求中使用RestTemplate。
我发现,当你使用 curl -X POST -d 'key=data'
,curl将添加头 content-type: application/x-www-form-urlencoded
所以这里的解决方案也会做同样的事情。
这个解决方案用你指定的头部和主体设置了RestTemplate,并在一个相当于你描述的对象中捕获响应。
下面的解决方案由两个文件组成,您可以尝试将其引入到您的解决方案中。
package com.example.demo;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
@Component
public class RestTemplateTokenRequester {
public TokenResponse requestAccessToken() {
// Create a RestTemplate to describe the request
RestTemplate restTemplate = new RestTemplate();
// Specify the http headers that we want to attach to the request
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.add("Authorization", createAuthHeaderString("ClientId", "Clientaccesskey"));
// Create a map of the key/value pairs that we want to supply in the body of the request
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("response_type","token");
map.add("client_id","ClientId");
map.add("username","user");
map.add("password","userpassword");
map.add("scope","process");
map.add("grant_type","password");
// Create an HttpEntity object, wrapping the body and headers of the request
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);
// Execute the request, as a POSt, and expecting a TokenResponse object in return
ResponseEntity<TokenResponse> response =
restTemplate.exchange("https://oauth2.url/oauth/token",
HttpMethod.POST,
entity,
TokenResponse.class);
return response.getBody();
}
// Just a helper metod to create the basic auth header
private String createAuthHeaderString(String username, String password) {
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.US_ASCII));
String authHeader = "Basic " + new String(encodedAuth);
return authHeader;
}
}
这是一个简单的POJO,被jackson mapper使用,用来捕捉响应的对象,你可以很容易的读取结果。
package com.example.demo;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class TokenResponse {
@JsonProperty("access_token")
private String accessToken;
@JsonProperty("token_type")
private String tokenType;
@JsonProperty("refresh_token")
private String refreshToken;
@JsonProperty("expires_in")
private Integer expiresIn;
@JsonProperty("scope")
private String scope;
@JsonProperty("jti")
private String jti;
}
我希望这个解决方案能帮到你--比起我用okhttp3建议的其他解决方案,我更喜欢它。
curl是一个HTTP客户端.更好的解决方案是使用HTTP客户端API的java来调用端点.RestTemplate是常见的HTTP客户端与spring一起,它是你最好的选择。