Groovy - 使用 HttpBuilder 的 Jira OAuth 集成
Groovy - Jira OAuth integration using HttpBuilder
我想使用 JIRA REST api 和提供的 JIRA OAuth authentication
服务获取数据。
基本上我可以使用 ScribeJava
和 Groovy
来完成这个任务。但我想将所有过程解耦如下:-
- 请求获取请求令牌
- 申请授权URL
- 请求访问令牌
- 请求使用
HTTPBuilder
获取实际数据
所以我能够使用 ScribeJava
实现上述前三个步骤并将 accessToken
存储到 Database
以进一步请求数据,如下所示:-
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.spec.PKCS8EncodedKeySpec
import com.github.scribejava.core.builder.api.DefaultApi10a
import com.github.scribejava.core.model.OAuth1RequestToken
import com.github.scribejava.core.services.RSASha1SignatureService
import com.github.scribejava.core.services.SignatureService
class JiraOauthProvider extends DefaultApi10a {
private String authURL
private String requestTokenURL
private String accessTokenURL
private String consumerPrivateKey
private JiraOauthProvider(authURL, requestTokenURL, accessTokenURL, consumerPrivateKey) {
this.authURL = authURL
this.requestTokenURL = requestTokenURL
this.accessTokenURL = accessTokenURL
this.consumerPrivateKey = consumerPrivateKey
}
private static JiraOauthProvider instance = null
public static JiraOauthProvider instance(Map map) {
if(instance == null) {
instance = new JiraOauthProvider(map.authURL,
map.requestTokenURL,
map.accessTokenURL,
map.consumerPrivateKey)
}
return instance
}
@Override
public String getAccessTokenEndpoint() {
return accessTokenURL
}
@Override
public String getRequestTokenEndpoint() {
return requestTokenURL
}
@Override
public String getAuthorizationUrl(OAuth1RequestToken requestToken) {
return String.format(authURL, requestToken.getToken())
}
@Override
public SignatureService getSignatureService() {
return new RSASha1SignatureService(getPrivateKey())
}
private PrivateKey getPrivateKey() {
byte[] key = Base64.getDecoder().decode(consumerPrivateKey)
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key)
KeyFactory kf = KeyFactory.getInstance("RSA")
return kf.generatePrivate(keySpec)
}
现在我正在构建 OAuthService
作为 :-
private static final String CALLBACK_URI = "callback-url"
protected static final String CONSUMER_KEY = "consumer-key"
protected static final String CONSUMER_PRIVATE_KEY = "private-key"
Map oAuthMap = [
"authURL" :"auth-url=%s",
"requestTokenURL":"request-token-url",
"accessTokenURL":"access-token-url",
"consumerPrivateKey":CONSUMER_PRIVATE_KEY
]
//Buid oauth service to get request token, auth url and access token
OAuth10aService service = ServiceBuilder()
.apiKey(CONSUMER_KEY)
.apiSecret(CONSUMER_PRIVATE_KEY).callback(CALLBACK_URI)
.build(JiraOauthProvider.instance(oAuthMap))
OAuth1RequestToken requestToken = service.getRequestToken()
def authURL = service.getAuthorizationUrl(requestToken)
//Now after redirect to this authURL and providing credential I'm getting oauthVerifier code to get accessToken and secretToken
def oauthVerifier = "oauth verifier code"
//Now calling to get accessToken
OAuth1AccessToken oAuth1AccessToken = service.getAccessToken(requestToken, oauthVerifier);
def accessToken = oAuth1AccessToken.getToken()
def secretToken = oAuth1AccessToken.getTokenSecret()
//now I'm storing this `accessToken`and `secretToken` into DB for further future data request.
所以在完成上述所有事情之后,我能够实现上述三个步骤并将访问令牌存储到 db
中,仅供 data
.
的未来请求使用
因此,为了实现使用 HTTPBuilder
获取实际数据的第 4 步,我正在做如下事情:-
def http = new HTTPBuilder('base-url')
http.auth.oauth CONSUMER_KEY, CONSUMER_PRIVATE_KEY, accessToken, secretToken
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = 'path'
response.success = { resp, json ->
println json
}
response.failure = { resp, json -> print json }
}
}
但我得到的回复是:-
{oauth_problem=signature_method_rejected}
所以,有人能建议我如何使用 HTTPBuilder
和 OAuth
身份验证使用 accessToken
和 secretToken 获取实际数据吗?
注意:- 我也可以使用 ScribeJava
Api 和 OAuthRequest
[=72 来获取实际数据=] 但要求是使用 HTTPBuilder
获取实际数据
我只是想要一个如何实现它的指针。
经过大量搜索,我得到了解决方案 from here. Actually HTTPBuilder
internally using Signpost
which signing the request using HmacSha Signer
而 Jira rest api
支持 RSA-SHA1 Signer
来验证 HttpRequest
这就是为什么它给出响应的原因:-
{oauth_problem=signature_method_rejected}
所以,基本上我必须自定义 RSA-SHA1 Signer
才能获得 http 请求的签名。为了实现这一点,我使用 Google Data (GData) APIs
在 HttprRequest
之前使用 RSA-SHA1 Signer
对数据进行签名,如下所示:-
private static PrivateKey getPrivateKey(String consumerKey) {
try {
byte[] key = Base64.getDecoder().decode(consumerKey)
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key)
KeyFactory kf = KeyFactory.getInstance("RSA")
return kf.generatePrivate(keySpec)
} catch (Exception e) {
throw new RuntimeException(e)
}
}
import com.google.gdata.client.authn.oauth.OAuthParameters
import com.google.gdata.client.authn.oauth.OAuthRsaSha1Signer
import com.google.gdata.client.authn.oauth.OAuthUtil
import com.google.gdata.client.authn.oauth.RsaSha1PrivateKeyHelper
OAuthRsaSha1Signer rsaSigner = new OAuthRsaSha1Signer()
rsaSigner.setPrivateKey(getPrivateKey(CONSUMER_PRIVATE_KEY))
OAuthParameters params = new OAuthParameters()
params.setOAuthConsumerKey(CONSUMER_KEY)
params.setOAuthNonce(OAuthUtil.getNonce())
params.setOAuthTimestamp(OAuthUtil.getTimestamp())
params.setOAuthSignatureMethod("RSA-SHA1")
params.setOAuthType(OAuthParameters.OAuthType.TWO_LEGGED_OAUTH)
params.setOAuthToken(accessToken)
String paramString = params.getBaseParameters().sort().collect{it}.join('&')
String baseString = [
OAuthUtil.encode("GET"),
OAuthUtil.encode('base-url' + 'path'),
OAuthUtil.encode(paramString)
].join('&')
String signature = rsaSigner.getSignature(baseString, params);
params.addCustomBaseParameter("oauth_signature", signature);
//Now calling using HTTPBuilder with signed data
def http = new HTTPBuilder('base-url')
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = 'path'
uri.query = params.getBaseParameters()
response.success = { resp, json ->
println json
}
response.failure = { resp, json -> print json }
}
}
我想使用 JIRA REST api 和提供的 JIRA OAuth authentication
服务获取数据。
基本上我可以使用 ScribeJava
和 Groovy
来完成这个任务。但我想将所有过程解耦如下:-
- 请求获取请求令牌
- 申请授权URL
- 请求访问令牌
- 请求使用
HTTPBuilder
获取实际数据
所以我能够使用 ScribeJava
实现上述前三个步骤并将 accessToken
存储到 Database
以进一步请求数据,如下所示:-
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.spec.PKCS8EncodedKeySpec
import com.github.scribejava.core.builder.api.DefaultApi10a
import com.github.scribejava.core.model.OAuth1RequestToken
import com.github.scribejava.core.services.RSASha1SignatureService
import com.github.scribejava.core.services.SignatureService
class JiraOauthProvider extends DefaultApi10a {
private String authURL
private String requestTokenURL
private String accessTokenURL
private String consumerPrivateKey
private JiraOauthProvider(authURL, requestTokenURL, accessTokenURL, consumerPrivateKey) {
this.authURL = authURL
this.requestTokenURL = requestTokenURL
this.accessTokenURL = accessTokenURL
this.consumerPrivateKey = consumerPrivateKey
}
private static JiraOauthProvider instance = null
public static JiraOauthProvider instance(Map map) {
if(instance == null) {
instance = new JiraOauthProvider(map.authURL,
map.requestTokenURL,
map.accessTokenURL,
map.consumerPrivateKey)
}
return instance
}
@Override
public String getAccessTokenEndpoint() {
return accessTokenURL
}
@Override
public String getRequestTokenEndpoint() {
return requestTokenURL
}
@Override
public String getAuthorizationUrl(OAuth1RequestToken requestToken) {
return String.format(authURL, requestToken.getToken())
}
@Override
public SignatureService getSignatureService() {
return new RSASha1SignatureService(getPrivateKey())
}
private PrivateKey getPrivateKey() {
byte[] key = Base64.getDecoder().decode(consumerPrivateKey)
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key)
KeyFactory kf = KeyFactory.getInstance("RSA")
return kf.generatePrivate(keySpec)
}
现在我正在构建 OAuthService
作为 :-
private static final String CALLBACK_URI = "callback-url"
protected static final String CONSUMER_KEY = "consumer-key"
protected static final String CONSUMER_PRIVATE_KEY = "private-key"
Map oAuthMap = [
"authURL" :"auth-url=%s",
"requestTokenURL":"request-token-url",
"accessTokenURL":"access-token-url",
"consumerPrivateKey":CONSUMER_PRIVATE_KEY
]
//Buid oauth service to get request token, auth url and access token
OAuth10aService service = ServiceBuilder()
.apiKey(CONSUMER_KEY)
.apiSecret(CONSUMER_PRIVATE_KEY).callback(CALLBACK_URI)
.build(JiraOauthProvider.instance(oAuthMap))
OAuth1RequestToken requestToken = service.getRequestToken()
def authURL = service.getAuthorizationUrl(requestToken)
//Now after redirect to this authURL and providing credential I'm getting oauthVerifier code to get accessToken and secretToken
def oauthVerifier = "oauth verifier code"
//Now calling to get accessToken
OAuth1AccessToken oAuth1AccessToken = service.getAccessToken(requestToken, oauthVerifier);
def accessToken = oAuth1AccessToken.getToken()
def secretToken = oAuth1AccessToken.getTokenSecret()
//now I'm storing this `accessToken`and `secretToken` into DB for further future data request.
所以在完成上述所有事情之后,我能够实现上述三个步骤并将访问令牌存储到 db
中,仅供 data
.
因此,为了实现使用 HTTPBuilder
获取实际数据的第 4 步,我正在做如下事情:-
def http = new HTTPBuilder('base-url')
http.auth.oauth CONSUMER_KEY, CONSUMER_PRIVATE_KEY, accessToken, secretToken
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = 'path'
response.success = { resp, json ->
println json
}
response.failure = { resp, json -> print json }
}
}
但我得到的回复是:-
{oauth_problem=signature_method_rejected}
所以,有人能建议我如何使用 HTTPBuilder
和 OAuth
身份验证使用 accessToken
和 secretToken 获取实际数据吗?
注意:- 我也可以使用 ScribeJava
Api 和 OAuthRequest
[=72 来获取实际数据=] 但要求是使用 HTTPBuilder
我只是想要一个如何实现它的指针。
经过大量搜索,我得到了解决方案 from here. Actually HTTPBuilder
internally using Signpost
which signing the request using HmacSha Signer
而 Jira rest api
支持 RSA-SHA1 Signer
来验证 HttpRequest
这就是为什么它给出响应的原因:-
{oauth_problem=signature_method_rejected}
所以,基本上我必须自定义 RSA-SHA1 Signer
才能获得 http 请求的签名。为了实现这一点,我使用 Google Data (GData) APIs
在 HttprRequest
之前使用 RSA-SHA1 Signer
对数据进行签名,如下所示:-
private static PrivateKey getPrivateKey(String consumerKey) {
try {
byte[] key = Base64.getDecoder().decode(consumerKey)
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key)
KeyFactory kf = KeyFactory.getInstance("RSA")
return kf.generatePrivate(keySpec)
} catch (Exception e) {
throw new RuntimeException(e)
}
}
import com.google.gdata.client.authn.oauth.OAuthParameters
import com.google.gdata.client.authn.oauth.OAuthRsaSha1Signer
import com.google.gdata.client.authn.oauth.OAuthUtil
import com.google.gdata.client.authn.oauth.RsaSha1PrivateKeyHelper
OAuthRsaSha1Signer rsaSigner = new OAuthRsaSha1Signer()
rsaSigner.setPrivateKey(getPrivateKey(CONSUMER_PRIVATE_KEY))
OAuthParameters params = new OAuthParameters()
params.setOAuthConsumerKey(CONSUMER_KEY)
params.setOAuthNonce(OAuthUtil.getNonce())
params.setOAuthTimestamp(OAuthUtil.getTimestamp())
params.setOAuthSignatureMethod("RSA-SHA1")
params.setOAuthType(OAuthParameters.OAuthType.TWO_LEGGED_OAUTH)
params.setOAuthToken(accessToken)
String paramString = params.getBaseParameters().sort().collect{it}.join('&')
String baseString = [
OAuthUtil.encode("GET"),
OAuthUtil.encode('base-url' + 'path'),
OAuthUtil.encode(paramString)
].join('&')
String signature = rsaSigner.getSignature(baseString, params);
params.addCustomBaseParameter("oauth_signature", signature);
//Now calling using HTTPBuilder with signed data
def http = new HTTPBuilder('base-url')
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = 'path'
uri.query = params.getBaseParameters()
response.success = { resp, json ->
println json
}
response.failure = { resp, json -> print json }
}
}