簡體   English   中英

Groovy - 使用 HttpBuilder 的 Jira OAuth 集成

[英]Groovy - Jira OAuth integration using HttpBuilder

我想使用JIRA REST api和提供的JIRA OAuth authentication服務獲取數據。

基本上我可以使用帶有Groovy ScribeJava來完成這個任務。 但我想將所有過程解耦如下:-

  • 請求獲取請求令牌
  • 請求獲取授權 URL
  • 請求訪問令牌
  • 請求使用HTTPBuilder獲取實際數據

所以,我能夠達到上述提到使用前三個步驟ScribeJava和存儲accessTokenDatabase的數據,如下面進一步的要求: -

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}

所以,任何人都可以建議我怎么能得到使用實際數據HTTPBuilderOAuth使用認證accessToken和secretToken?

注意:- 我也可以使用帶有OAuthRequest ScribeJava Api 獲取實際數據,但要求是使用HTTPBuilder獲取實際數據

我只想要一個如何實現它的指針。

經過大量搜索,我從這里得到了解決方案。 實際上, HTTPBuilder內部使用Signpost ,它使用HmacSha Signer對請求進行HmacSha SignerJira rest api支持RSA-SHA1 Signer來驗證HttpRequest ,這就是它給出響應的原因:-

{oauth_problem=signature_method_rejected}

所以,基本上我必須做自定義RSA-SHA1 Signer來獲取 http 請求的簽名。 為了實現這一點,我在HttprRequest之前使用Google Data (GData) APIs使用RSA-SHA1 Signer對數據進行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 }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM