2

我打算使用使用承載認證的服務。我試圖從Android取得它徒然。這是我的代碼。如何從Android訪問承載認證服務

String mytoken = "some token I am sure is right"; 
HttpClient witClient = new DefaultHttpClient(); 
Uri.Builder b = Uri.parse("www.somewebsite.com").buildUpon(); 
b.appendQueryParameter("q", "some query string"); 
String finalurl = b.build().toString(); 
HttpGet request = new HttpGet(new URI(finalurl)); 
request.setHeader("Authorization", "Bearer "+mytoken); 
HttpResponse response = witClient.execute(request); 

服務器將返回一個錯誤,說明需要驗證。很顯然,標題被丟棄了。

11-22 21:50:42.180: W/DefaultRequestDirector(3408): Authentication error: Unable to respond to any of these challenges: {bearer=Www-Authenticate: Bearer realm="OAuth required"} 

哪裏錯

回答

4

這可能是複雜一點點,但我已經受夠了它的成功,所以我會盡量給你我的經驗中獲益。

你必須提供幾個項目

  • org.apache.http.auth.Credentials
  • 的org.apache.http.auth.AuthSchemeFactory
的實施方案的實施

您的證書實施應該類似於以下內容:

​​

然後,你需要實現AuthSchemeFactory:

import org.apache.http.Header; 
import org.apache.http.HttpRequest; 
import org.apache.http.auth.AUTH; 
import org.apache.http.auth.AuthScheme; 
import org.apache.http.auth.AuthSchemeFactory; 
import org.apache.http.auth.AuthenticationException; 
import org.apache.http.auth.ContextAwareAuthScheme; 
import org.apache.http.auth.Credentials; 
import org.apache.http.auth.MalformedChallengeException; 
import org.apache.http.message.BufferedHeader; 
import org.apache.http.params.HttpParams; 
import org.apache.http.protocol.HttpContext; 
import org.apache.http.util.CharArrayBuffer; 

public class BearerAuthSchemeFactory implements AuthSchemeFactory { 

    @Override 
    public AuthScheme newInstance(HttpParams params) { 
     return new BearerAuthScheme(); 
    } 

    private static class BearerAuthScheme implements ContextAwareAuthScheme { 
     private boolean complete = false; 

     @Override 
     public void processChallenge(Header header) throws MalformedChallengeException { 
      this.complete = true; 
     } 

     @Override 
     public Header authenticate(Credentials credentials, HttpRequest request) throws AuthenticationException { 
      return authenticate(credentials, request, null); 
     } 

     @Override 
     public Header authenticate(Credentials credentials, HttpRequest request, HttpContext httpContext) 
       throws AuthenticationException { 
      CharArrayBuffer buffer = new CharArrayBuffer(32); 
      buffer.append(AUTH.WWW_AUTH_RESP); 
      buffer.append(": Bearer "); 
      buffer.append(credentials.getUserPrincipal().getName()); 
      return new BufferedHeader(buffer); 
     } 

     @Override 
     public String getSchemeName() { 
      return "Bearer"; 
     } 

     @Override 
     public String getParameter(String name) { 
      return null; 
     } 

     @Override 
     public String getRealm() { 
      return null; 
     } 

     @Override 
     public boolean isConnectionBased() { 
      return false; 
     } 

     @Override 
     public boolean isComplete() { 
      return this.complete; 
     } 
    } 
} 

下一個步驟是讓HttpClient的接受它作爲一個有效的方案:

HttpContext httpContext = new BasicHttpContext(); 

    AuthSchemeRegistry authSchemeRegistry = new AuthSchemeRegistry(); 
    authSchemeRegistry.register("Bearer", new BearerAuthSchemeFactory()); 
    httpContext.setAttribute(ClientContext.AUTHSCHEME_REGISTRY, authSchemeRegistry); 
    AuthScope sessionScope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM, "Bearer"); 

    Credentials credentials = new TokenCredentials (token); 
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); 
    credentialsProvider.setCredentials(sessionScope, credentials); 
    httpContext.setAttribute(ClientContext.CREDS_PROVIDER, credentialsProvider); 

我通常會在每個上下文的基礎上創建這些掛在在一段時間內的背景下。

其他文檔可以發現here。我建議遠離「先發制人」的身份驗證,並讓這個架構在處理401挑戰方面做好工作。

如果您想查看我在說什麼,請打開HTTP客戶端中的日誌記錄,以便跟蹤連線對話 - 您會看到最初的請求會返回挑戰,然後客戶端將使用憑證提供程序來查找適當的憑證並將請求發送給我們定義的方案的適當的質詢響應。

祝你好運!