2015-05-30 19 views
5

Tôi đang thực hiện oauth bằng Java với folowing trình tự:Twitter oauth oauth_verifier không hợp lệ tham số

1) Gửi https POST: //api.twitter.com/oauth/request_token (với callback) Twitter phản ứng chứa oauth_token, oauth_token_secret và oauth_callback_confirmed = true

2) Chuyển hướng đến https: //api.twitter.com/oauth/authenticate oauth_token = {oauth_token từ phản ứng trước từ twitter}

3) mẫu đăng nhập Twitter xuất hiện, tôi bấm vào nút "đăng nhập".

4) Twitter chuyển hướng đến {} callback_url oauth_token = {dấu hiệu này bằng thẻ từ oauth phản ứng/request_token} & oauth_verifier = {} xác minh

5) https POST: //api.twitter.com/oauth/access_token với Oauth tiêu đề bao gồm oauth_token, nội dung thư chứa oauth_verifier = {trở verifier}

6) Twitter phản ứng = Lỗi khi xử lý yêu cầu OAuth của bạn: tham số không hợp lệ oauth_verifier

Điều gì là sai với oauth_verifier?

phương pháp Tính chữ ký:

private static String computeSignature(String baseString, String keyString) throws GeneralSecurityException, UnsupportedEncodingException { 
     SecretKey secretKey = null; 

     byte[] keyBytes = keyString.getBytes(); 
     secretKey = new SecretKeySpec(keyBytes, "HmacSHA1"); 

     Mac mac = Mac.getInstance("HmacSHA1"); 
     mac.init(secretKey); 

     byte[] text = baseString.getBytes(); 

     return new String(Base64.encodeBase64(mac.doFinal(text))).trim(); 
    } 

Mã cho yêu cầu đầu tiên:

String oauth_signature_method = "HMAC-SHA1"; 

    // generate any fairly random alphanumeric string as the "nonce". 
    String uuid_string = UUID.randomUUID().toString(); 
    uuid_string = uuid_string.replaceAll("-", ""); 
    String oauth_nonce = uuid_string; 

    // get the timestamp 
    Calendar tempcal = Calendar.getInstance(); 
    long ts = tempcal.getTimeInMillis(); 
    String oauth_timestamp = (new Long(ts/1000)).toString(); 
    String parameter_string = "oauth_callback=" + OauthConstants.TWITTER_OAUTH_CALLBACK 
      + "&oauth_consumer_key=" + OauthConstants.TWITTER_OAUTH_CONSUMER_KEY 
      + "&oauth_nonce=" + oauth_nonce + "&oauth_signature_method=" 
      + oauth_signature_method + "&oauth_timestamp=" + oauth_timestamp + "&oauth_version=1.0"; 
    String signature_base_string = get_or_post + "&" + encode(twitter_endpoint) + "&" + encode(parameter_string); 
    String oauth_signature = ""; 

    try { 
     oauth_signature = computeSignature(signature_base_string, OauthConstants.TWITTER_OAUTH_CONSUMER_SECRET + "&"); 
    } catch (GeneralSecurityException | UnsupportedEncodingException e) { 
     ...} 

String twitter_endpoint = "https://api.twitter.com/oauth/request_token"; 
String authorization_header_string = "OAuth oauth_callback=\"" + OauthConstants.TWITTER_OAUTH_CALLBACK 
       + "\",oauth_consumer_key=\"" + OauthConstants.TWITTER_OAUTH_CONSUMER_KEY 
       + "\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"" + oauth_timestamp 
       + "\",oauth_nonce=\"" + oauth_nonce + "\",oauth_version=\"1.0\",oauth_signature=\"" 
       + encode(oauth_signature) + "\""; 

// Apache httpcore 4.4.1 
HttpProcessor httpproc = HttpProcessorBuilder.create() 
       .add(new RequestContent()) 
       .add(new RequestTargetHost()) 
       .add(new RequestConnControl()) 
       .add(new RequestUserAgent("ApacheHttp/1.1")) 
       .add(new RequestExpectContinue(true)).build(); 

     HttpRequestExecutor httpexecutor = new HttpRequestExecutor(); 
     HttpCoreContext context = HttpCoreContext.create(); 
     HttpHost host = new HttpHost(twitter_endpoint_host, 443); 
     DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1024); 

     context.setAttribute(HttpCoreContext.HTTP_CONNECTION, conn); 
     context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, host); 

try { 
       // initialize the HTTPS connection 
       SSLContext sslcontext = SSLContext.getInstance("TLS"); 
       sslcontext.init(null, null, null); 
       SSLSocketFactory ssf = sslcontext.getSocketFactory(); 
       Socket socket = ssf.createSocket(); 
       socket.connect(new InetSocketAddress(host.getHostName(), host.getPort()), 0); 
       conn.bind(socket); 

       BasicHttpEntityEnclosingRequest request2 = new BasicHttpEntityEnclosingRequest("POST", twitter_endpoint_path, HttpVersion.HTTP_1_1); 
       request2.setEntity(new StringEntity("", "UTF-8")); 
       request2.addHeader("Authorization", authorization_header_string); 
       httpexecutor.preProcess(request2, httpproc, context); 
       HttpResponse response2 = httpexecutor.execute(request2, conn, context); 
       httpexecutor.postProcess(response2, httpproc, context); 
} catch(Exception e) {} ... 

Mã cho yêu cầu thứ hai (Chuyển tới https oauth/authenticate)

public JSONObject getTwitterAuthorizationCodeFromRequestToken(String oauth_token) { 
... 
     String twitter_endpoint = "https://api.twitter.com/oauth/authenticate"; 

     ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext(); 
     try { 
      FacesContext.getCurrentInstance().getExternalContext().redirect(twitter_endpoint + "?oauth_token=" + encode(oauth_token)); 
     } catch (IOException ex) {...} 
... 
    } 

Mã cho yêu cầu thứ 3 (POST oauth/access_token)

public JSONObject getTwitterAccessTokenFromAuthorizationCode(String verifier_or_pin, String oauth_token) { 
    ... 
String oauth_signature_method = "HMAC-SHA1"; 

    // generate any fairly random alphanumeric string as the "nonce". Nonce = Number used ONCE. 
    String uuid_string = UUID.randomUUID().toString(); 
    uuid_string = uuid_string.replaceAll("-", ""); 
    String oauth_nonce = uuid_string; 

    Calendar tempcal = Calendar.getInstance(); 
    long ts = tempcal.getTimeInMillis(); 
    String oauth_timestamp = (new Long(ts/1000)).toString(); 

    // the parameter string must be in alphabetical order 
    String parameter_string = "oauth_consumer_key=" + OauthConstants.TWITTER_OAUTH_CONSUMER_KEY 
          + "&oauth_nonce=" + oauth_nonce + "&oauth_signature_method=" + oauth_signature_method 
          + "&oauth_timestamp=" + oauth_timestamp + "&oauth_token=" + encode(oauth_token) + "&oauth_version=1.0"; 

    String signature_base_string = get_or_post + "&" + encode(twitter_endpoint) + "&" + encode(parameter_string); 

    String oauth_signature = ""; 
    try { 
     oauth_signature = computeSignature(signature_base_string, OauthConstants.TWITTER_OAUTH_CONSUMER_SECRET + "&"); 
    } catch (GeneralSecurityException | UnsupportedEncodingException e) { 
     ... 
    } 

    String authorization_header_string = "OAuth oauth_consumer_key=\"" + OauthConstants.TWITTER_OAUTH_CONSUMER_KEY 
               + "\",oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"" + oauth_timestamp 
               + "\",oauth_nonce=\"" + oauth_nonce + "\",oauth_version=\"1.0\",oauth_signature=\"" 
               + encode(oauth_signature) + "\",oauth_token=\"" + encode(oauth_token) + "\""; 

    HttpProcessor httpproc = HttpProcessorBuilder.create() 
        .add(new RequestContent()) 
        .add(new RequestTargetHost()) 
        .add(new RequestConnControl()) 
        .add(new RequestUserAgent("ApacheHttp/1.1")) 
        .add(new RequestExpectContinue(true)).build(); 

      HttpRequestExecutor httpexecutor = new HttpRequestExecutor(); 
      HttpCoreContext context = HttpCoreContext.create(); 
      HttpHost host = new HttpHost(twitter_endpoint_host, 443); 
      DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1024); 

      context.setAttribute(HttpCoreContext.HTTP_CONNECTION, conn); 
      context.setAttribute(HttpCoreContext.HTTP_TARGET_HOST, host); 

    try { 
        SSLContext sslcontext = SSLContext.getInstance("TLS"); 
        sslcontext.init(null, null, null); 
        SSLSocketFactory ssf = sslcontext.getSocketFactory(); 
        Socket socket = ssf.createSocket(); 
        socket.connect(new InetSocketAddress(host.getHostName(), host.getPort()), 0); 
        conn.bind(socket); 

        BasicHttpEntityEnclosingRequest request2 = new BasicHttpEntityEnclosingRequest("POST", twitter_endpoint_path); 
        // Including oauth_verifier value to request body 
        request2.setEntity(new StringEntity("oauth_verifier=" + encode(verifier_or_pin), "UTF-8")); 
        request2.addHeader("Authorization", authorization_header_string); 
        httpexecutor.preProcess(request2, httpproc, context); 
        HttpResponse response2 = httpexecutor.execute(request2, conn, context); 
... 
    } 
+0

Bạn có thể hiển thị mã của mình để thực hiện việc này không? –

+0

@Matthew C câu hỏi được cập nhật –

+0

Có chính xác cùng một vấn đề, bạn đã tìm thấy giải pháp chưa? –

Trả lời

2

Tôi đã gặp phải tình huống tương tự chính xác với cơ sở mã JavaScript của chúng tôi. Sau khi đấu tranh một ngày, tôi tìm thấy một giải pháp giải quyết lỗi. Đó chỉ là thêm tiêu đề "Loại nội dung" với giá trị "ứng dụng/x-www-form-urlencoded".

Mã của tôi đã được sử dụng để hoạt động chính xác nhưng đã ngừng hoạt động trong vài tháng qua. Tôi đoán là Twitter đã thay đổi việc thực hiện xử lý OAuth gần đây, buộc chúng tôi phải thêm loại nội dung một cách rõ ràng.

+1

Tôi nghĩ rằng họ sẽ thêm nó vào tài liệu, nếu đó là trường hợp –

+1

Chúng tôi không thể đổ lỗi cho Twitter vì nó được xác định trong đặc tả HTTP. http://www.w3.org/Protocols/rfc2616/rfc2616-sec7.html#sec7.2.1 – Basuke

+1

Tất nhiên, các kỹ sư Twitter có thể tốt hơn vì họ đã sử dụng để chấp nhận yêu cầu mà không có kiểu nội dung. Nếu thông báo lỗi rõ ràng hơn, hãy nói "Lỗi: Tiêu đề loại nội dung là bắt buộc để xử lý yêu cầu bài đăng với dữ liệu"., Chúng tôi có thể tìm thấy sự cố sớm hơn. – Basuke

Các vấn đề liên quan