2015-10-10 18 views
15

私は、RSA秘密鍵で署名され、RSA公開鍵でサーバ側で検証されたOAuth1要求を認証するためのユースケースを持っています。RSA-SHA1でTwitter joauthを使用してOAuth1a署名付きリクエストを確認しますか?

私はOauthが署名したリクエストを認証/検証するのに役立つこのライブラリをTwitterから見つけました。 https://github.com/twitter/joauth

JerseyまたはSpring MVCアクションメソッドからの要求を検証するために、このライブラリを活用したいと考えています。クライアントからの要求は、秘密鍵を使用して署名されています。私の最後では、クライアントの公開鍵を使用してリクエストを確認します。これはRSA-SHA1アルゴリズムを意味します。

Twitterはjoauth有用であると思われるが、私は、ライブラリ読み取り私のファイルが施設として、このことを示唆しているが、私はjavax.servlet.http.HttpServletRequest行うコードを見つけることができませんでしたOAuthRequest

へのHttpServletRequestを変換するコード行方不明です - >com.twitter.joauth.OAuthRequestを変換。

次の署名が付いている検証方法で要求確認が行われます。

public VerifierResult verify(UnpackedRequest.OAuth1Request request, String tokenSecret, String consumerSecret); 

は、第二に、私もこの方法を検証することはStringパラメータを取るときのTwitter joauthとRSA公開鍵を読む/使用するための最も適切な方法であるかを知りたいですか?

+0

あなたはどのバージョンのJOAuthを使用していますか? – Val

答えて

1

Twitterを使用してユーザーを認証するライブラリは一度も使用していません。しかし、私はUnpackedRequest.OAuth1Requestを見てきました。すべてのパラメータを入力することで、このクラスのインスタンスを作成できます。私はTwitter OAuth Headerの作成者を書いているので、それらのパラメータを埋めるために使うことも、ライブラリなしでPOSTリクエストを直接送ることもできます。

必要なすべてのクラス:

署名 - OAuth署名を生成する。

public class Signature { 
    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1"; 
    public static String calculateRFC2104HMAC(String data, String key) 
      throws java.security.SignatureException 
    { 
     String result; 
     try { 
      SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM); 
      Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM); 
      mac.init(signingKey); 
      byte[] rawHmac = mac.doFinal(data.getBytes()); 
      result = new String(Base64.encodeBase64(rawHmac)); 
     } catch (Exception e) { 
      throw new SignatureException("Failed to generate HMAC : " + e.getMessage()); 
     } 
     return result; 
    } 
} 

NvpComparator - あなたがヘッダに必要なパラメータをソートします。

public class NvpComparator implements Comparator<NameValuePair> { 
    @Override 
    public int compare(NameValuePair arg0, NameValuePair arg1) { 
     String name0 = arg0.getName(); 
     String name1 = arg1.getName(); 
     return name0.compareTo(name1); 
    } 
} 

のOAuth - URLエンコードのために。

class OAuth{ 
... 
    public static String percentEncode(String s) { 
      return URLEncoder.encode(s, "UTF-8") 
        .replace("+", "%20").replace("*", "%2A") 
        .replace("%7E", "~"); 
    } 
... 
} 

HeaderCreator - すべての必要なパラメータを作成し、OAuthのヘッダPARAMを生成します。

public class HeaderCreator { 
    private String authorization = "OAuth "; 
    private String oAuthSignature; 
    private String oAuthNonce; 
    private String oAuthTimestamp; 
    private String oAuthConsumerSecret; 
    private String oAuthTokenSecret; 

    public String getAuthorization() { 
     return authorization; 
    } 

    public String getoAuthSignature() { 
     return oAuthSignature; 
    } 

    public String getoAuthNonce() { 
     return oAuthNonce; 
    } 

    public String getoAuthTimestamp() { 
     return oAuthTimestamp; 
    } 

    public HeaderCreator(){} 

    public HeaderCreator(String oAuthConsumerSecret){ 
     this.oAuthConsumerSecret = oAuthConsumerSecret; 
    } 

    public HeaderCreator(String oAuthConsumerSecret, String oAuthTokenSecret){ 
     this(oAuthConsumerSecret); 
     this.oAuthTokenSecret = oAuthTokenSecret; 
    } 

    public String getTwitterServerTime() throws IOException, ParseException { 
     HttpsURLConnection con = (HttpsURLConnection) 
       new URL("https://api.twitter.com/oauth/request_token").openConnection(); 
     con.setRequestMethod("HEAD"); 
     con.getResponseCode(); 
     String twitterDate= con.getHeaderField("Date"); 
     DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH); 
     Date date = formatter.parse(twitterDate); 
     return String.valueOf(date.getTime()/1000L); 
    } 

    public String generatedSignature(String url, String method, List<NameValuePair> allParams, 
            boolean withToken) throws SignatureException { 
     oAuthNonce = String.valueOf(System.currentTimeMillis()); 
     allParams.add(new BasicNameValuePair("oauth_nonce", oAuthNonce)); 
     try { 
      oAuthTimestamp = getTwitterServerTime(); 
      allParams.add(new BasicNameValuePair("oauth_timestamp", oAuthTimestamp)); 
     }catch (Exception ex){ 
      //TODO: Log!! 
     } 

     Collections.sort(allParams, new NvpComparator()); 
     StringBuffer params = new StringBuffer(); 
     for(int i=0;i<allParams.size();i++) 
     { 
      NameValuePair nvp = allParams.get(i); 
      if (i>0) { 
       params.append("&"); 
      } 
      params.append(nvp.getName() + "=" + OAuth.percentEncode(nvp.getValue())); 
     } 
     String signatureBaseStringTemplate = "%s&%s&%s"; 
     String signatureBaseString = String.format(signatureBaseStringTemplate, 
       OAuth.percentEncode(method), 
       OAuth.percentEncode(url), 
       OAuth.percentEncode(params.toString())); 
     String compositeKey = OAuth.percentEncode(oAuthConsumerSecret)+"&"; 
     if(withToken) compositeKey+=OAuth.percentEncode(oAuthTokenSecret); 
     oAuthSignature = Signature.calculateRFC2104HMAC(signatureBaseString, compositeKey); 

     return oAuthSignature; 
    } 

    public String generatedAuthorization(List<NameValuePair> allParams){ 
     authorization = "OAuth "; 
     Collections.sort(allParams, new NvpComparator()); 
     for(NameValuePair nvm : allParams){ 
      authorization+=nvm.getName()+"="+OAuth.percentEncode(nvm.getValue())+", "; 
     } 
     authorization=authorization.substring(0,authorization.length()-2); 
     return authorization; 
    } 

} 

説明:
1. getTwitterServerTime
oAuthTimestampで をご使用のサーバーの時間が、Twitterのサーバーの時間を必要はありません。特定のTwitterサーバーでリクエストを送信する場合、このパラメータを保存して最適化することができます。

2. HeaderCreator.generatedSignature(...)
URL - GETやPOST - 論理的にTwitterのAPIに
方法をURL。 allParams - 署名( "param_name"、 "param_value")を生成するために知っているパラメータ。
withToken - oAuthTokenSecretが真であることがわかっている場合。それ以外の場合はfalse。

3. HeaderCreator.generatedAuthorization(...)
OAuthヘッダー文字列を生成するためにgeneratedSignature(...)の後にこのメソッドを使用します。
allParams - generatedSignature(...)で使用したパラメータです。nonce、signature、timestamp。常に使用:

allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce())); 
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature())); 
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp())); 


今、あなたはあなたのライブラリーにUnpackedRequest.OAuth1Requestを埋めるためにそれを使用することができます。
また、ライブラリを持たないSpringMVCのユーザを認証する例もあります。
リクエスト - 投稿要求を送信します。

public class Requests { 
    public static String sendPost(String url, String urlParameters, Map<String, String> prop) throws Exception { 
     URL obj = new URL(url); 
     HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(); 

     con.setRequestMethod("POST"); 
     if(prop!=null) { 
      for (Map.Entry<String, String> entry : prop.entrySet()) { 
       con.setRequestProperty(entry.getKey(), entry.getValue()); 
      } 
     } 
     con.setDoOutput(true); 
     DataOutputStream wr = new DataOutputStream(con.getOutputStream()); 
     wr.writeBytes(urlParameters); 
     wr.flush(); 
     wr.close(); 
     int responseCode = con.getResponseCode(); 
     BufferedReader in; 
     if(responseCode==200) { 
      in = new BufferedReader(
        new InputStreamReader(con.getInputStream())); 
     }else{ 
      in = new BufferedReader(
        new InputStreamReader(con.getErrorStream())); 
     } 
     String inputLine; 
     StringBuffer response = new StringBuffer(); 
     while ((inputLine = in.readLine()) != null) { 
      response.append(inputLine); 
     } 
     in.close(); 

     return response.toString(); 
    } 
} 

twAuth(...) - あなたのコントローラにそれを置きます。ユーザーがTwitter経由であなたのサイトで認証したいときに実行します。

@RequestMapping(value = "/twauth", method = RequestMethod.GET) 
    @ResponseBody 
    public String twAuth(HttpServletResponse response) throws Exception{ 
     try { 
      String url = "https://api.twitter.com/oauth/request_token"; 

      List<NameValuePair> allParams = new ArrayList<NameValuePair>(); 
      allParams.add(new BasicNameValuePair("oauth_callback", "http://127.0.0.1:8080/twlogin")); 
      allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT")); 
      allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1")); 
      allParams.add(new BasicNameValuePair("oauth_version", "1.0")); 

      HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL"); 
      headerCreator.generatedSignature(url,"POST",allParams,false); 
      allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce())); 
      allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature())); 
      allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp())); 

      Map<String, String> props = new HashMap<String, String>(); 
      props.put("Authorization", headerCreator.generatedAuthorization(allParams)); 
      String twitterResponse = Requests.sendPost(url,"",props); 
      Integer indOAuthToken = twitterResponse.indexOf("oauth_token"); 
      String oAuthToken = twitterResponse.substring(indOAuthToken, twitterResponse.indexOf("&",indOAuthToken)); 

      response.sendRedirect("https://api.twitter.com/oauth/authenticate?" + oAuthToken); 
     }catch (Exception ex){ 
      //TODO: Log 
      throw new Exception(); 
     } 
     return "main"; 
    } 

twLogin(...) - あなたのコントローラにそれを置きます。 Twitterからのコールバックです。

@RequestMapping(value = "/twlogin", method = RequestMethod.GET) 
    public String twLogin(@RequestParam("oauth_token") String oauthToken, 
          @RequestParam("oauth_verifier") String oauthVerifier, 
          Model model, HttpServletRequest request){ 
     try { 
      if(oauthToken==null || oauthToken.equals("") || 
        oauthVerifier==null || oauthVerifier.equals("")) 
       return "main"; 

      String url = "https://api.twitter.com/oauth/access_token"; 

      List<NameValuePair> allParams = new ArrayList<NameValuePair>(); 
      allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT")); 
      allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1")); 
      allParams.add(new BasicNameValuePair("oauth_token", oauthToken)); 
      allParams.add(new BasicNameValuePair("oauth_version", "1.0")); 
      NameValuePair oAuthVerifier = new BasicNameValuePair("oauth_verifier", oauthVerifier); 
      allParams.add(oAuthVerifier); 

      HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL"); 
      headerCreator.generatedSignature(url,"POST",allParams,false); 
      allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce())); 
      allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature())); 
      allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp())); 
      allParams.remove(oAuthVerifier); 

      Map<String, String> props = new HashMap<String, String>(); 
      props.put("Authorization", headerCreator.generatedAuthorization(allParams)); 

      String twitterResponse = Requests.sendPost(url,"oauth_verifier="+oauthVerifier,props); 

      //Get user id 

      Integer startIndexTmp = twitterResponse.indexOf("user_id")+8; 
      Integer endIndexTmp = twitterResponse.indexOf("&",startIndexTmp); 
      if(endIndexTmp<=0) endIndexTmp = twitterResponse.length()-1; 
      Long userId = Long.parseLong(twitterResponse.substring(startIndexTmp, endIndexTmp)); 

      //Do what do you want... 

     }catch (Exception ex){ 
      //TODO: Log 
      throw new Exception(); 
     } 
    } 
+0

このような精巧な答えをお寄せいただきありがとうございます。 –

関連する問題