2016-09-16 80 views
1

我想使用JIRA REST api獲取數據,並提供JIRA OAuth authentication服務。Groovy - 使用HttpBuilder的Jira OAuth集成

基本上我可以使用ScribeJavaGroovy來實現這個任務。但我想,如下脫鉤全部過程: -

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

所以,我能夠使用ScribeJava實現上述前三個步驟,並將accessToken存儲爲Database以供進一步的r eQUEST的數據如下: -

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

所以要實現4步使用HTTPBuilder獲得實際數據,我下面做一些事情: -

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

我只想要一個指針如何實現它得到實際的數據。

回答

0

經過大量的搜索,我得到了解決方案from here。其實HTTPBuilder內部使用Signpost其簽約使用HmacSha SignerJira rest api支持RSA-SHA1 Signer驗證HttpRequest這就是爲什麼它給響應的要求: -

{oauth_problem=signature_method_rejected} 

所以,基本上我所要做的定製RSA-SHA1 Signer拿到簽名http請求。爲了實現這一目標,我使用Google Data (GData) APIs簽署使用數據RSA-SHA1 Signer如下之前HttprRequest: -

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 } 
    } 
}