1

認証サービスに Stormpath を使用しています。HttpWebRequest を使用して、Stormpath の RestAPI を呼び出します。

また、HttpWebRequest を使用して RestAPI を呼び出していますが、機能しません。

private void BtnGetResetApiClick(object sender, EventArgs e)
{

var username = "aaaa";
var password = "bbbb";
ServicePointManager.ServerCertificateValidationCallback = Callback;
var request = WebRequest.Create("https://api.stormpath.com/v1/tenants/current") as HttpWebRequest;

request.UserAgent = ".NET SDK";
request.Method = "GET";
request.Accept = "*/*";

var data = string.Format("{0}:{1}", username, HttpUtility.HtmlEncode(password));

var token = Convert.ToBase64String(Encoding.UTF8.GetBytes(data));
string authHeader = string.Format("Basic {0}", token);

request.Headers.Add("Authorization", authHeader);
request.ServerCertificateValidationCallback = Callback;

using (var response = request.GetResponse())
{
    var stream = response.GetResponseStream();
    if (stream != null)
    {
        var streamReader = new StreamReader(stream);
        var str = streamReader.ReadToEnd();
        streamReader.Close();
        stream.Close();
    }
  }
}

private bool Callback(object obj, X509Certificate certificate, X509Chain  chain, SslPolicyErrors errors)
{
 return true;
}

通話時:

var response = request.GetResponse()

私は例外を得ました:

System.dll で 'System.Net.WebException' 型の未処理の例外が発生しました リモート サーバーがエラーを返しました: (401) 権限がありません。

私のコードに何か問題があるかどうかを確認するのを手伝ってもらえますか?

4

1 に答える 1

1

更新 - SDK を使用すると、はるかに簡単になります。

C# から Stormpath API を頻繁に呼び出す場合は、リクエストを手動で記述する必要はありません。代わりに、Stormpath .NET SDKを使用してください。私は著者です。:)

install-package Stormpath.SDKパッケージ マネージャー コンソールからインストールします。次に、IClientオブジェクトを作成します。

// In a production environment, you'll want to load these from
// environment variables or a secure file, instead of hardcoding!
var apiKey = ClientApiKeys.Builder()
                 .SetId("Your_Stormpath_API_key_ID")
                 .SetSecret("Your_Stormpath_API_key_secret")
                 .Build();
var client = Clients.Builder()
                 .SetApiKey(apiKey)
                 .Build();

テナント情報を取得するのは、次の単純な呼び出しだけです。

var tenant = await client.GetCurrentTenantAsync();
Console.WriteLine($"Current tenant is: {tenant.Name}");

本当に生のリクエストをしたい場合は、まだそれを行うことができます! 以下に説明します。


Authorization ヘッダーの作成

401 Unauthorized応答は、API が要求で有効な Authorization ヘッダーを見つけられなかったことを意味します。正しく認証するには、次の 2 つのものが必要です。

  • 形式の認証ペイロードapiKeyID:apiKeySecret
  • Authorization値を持つヘッダー:Basic base64(payload)

完全なヘッダーを作成する方法は次のとおりです。

// API_KEY_ID and API_KEY_SECRET populated elsewhere
var authPayload = string.Format("{0}:{1}", API_KEY_ID, API_KEY_SECRET);
var authPayloadEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(authPayload));
request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + authPayloadEncoded);

あなたはものを必要としませんServerCertificateValidationCallback = Callback。上記のヘッダーを使用すると、リクエストは API によって有効なリクエストとして認識されます (もちろん、API キー ID とシークレットが正しいと仮定します)。


リダイレクト処理

注意すべきことの 1 つは (最初はつまずきました!)、WebRequest は HTTP 302 リダイレクトに自動的に従いますが、既存のヘッダーを新しい要求に適用しないことです。

解決策は、次のリダイレクトを無効にすることです。

request.AllowAutoRedirect = false;

これは、302 応答を自分で処理する必要があることを意味しますが、それが Authorization ヘッダーを各要求に正しく適用する唯一の方法です。


実施例

この gistで簡単な作業例を作成しました。リクエストを複数回作成するため、ヘルパー関数を作成しました。

private static HttpWebRequest BuildRequest(string method, string uri)
{
    var request = WebRequest.Create(uri) as HttpWebRequest;
    request.UserAgent = "dotnet/csharp web-request";
    request.Method = method;
    request.ContentType = "application/json";

    // Important, otherwise the WebRequest will try to auto-follow
    // 302 redirects without applying the authorization header to the
    // subsequent requests.
    request.AllowAutoRedirect = false;

    // Construct HTTP Basic authorization header
    var authPayload = string.Format("{0}:{1}", API_KEY_ID, API_KEY_SECRET);
    var authPayloadEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(authPayload));
    request.Headers.Add(HttpRequestHeader.Authorization, "Basic " + authPayloadEncoded);

    return request;
}

そして、現在のテナントの URL と名前を取得する方法を示す簡単なコンソール アプリ:

// Get these from the Stormpath admin console
private static string API_KEY_ID = "Your_Stormpath_API_key_ID";
private static string API_KEY_SECRET = "Your_Stormpath_API_key_secret";

static void Main(string[] args)
{
    // First, we need to get the current tenant's actual URL
    string tenantUrl = null;
    var getCurrentTenantRequest = BuildRequest("GET", "https://api.stormpath.com/v1/tenants/current");

    try
    {
        using (var response = getCurrentTenantRequest.GetResponse())
        {
            tenantUrl = response.Headers["Location"];
        }
    }
    catch (WebException wex)
    {
        Console.WriteLine("Request failed. {0}", wex.Message);
        throw;
    }

    // Now that we have the real tenant URL, get the tenant info
    string tenantData = null;
    var getTenantInfoRequest = BuildRequest("GET", tenantUrl);

    try
    {
        using (var response = getTenantInfoRequest.GetResponse())
        using (var responseStream = response.GetResponseStream())
        using (var reader = new StreamReader(responseStream))
        {
            tenantData = reader.ReadToEnd();
        }
    }
    catch (WebException wex)
    {
        Console.WriteLine("Request failed. {0}", wex.Message);
        throw;
    }

    // Use JSON.NET to parse the data and get the tenant name
    var parsedData = JsonConvert.DeserializeObject<Dictionary<string, object>>(tenantData);
    Console.WriteLine("Current tenant is: {0}", parsedData["name"]);

    // Wait for user input
    Console.ReadKey(false);
}

API に対して生のリクエストを行っているため、コードは非常に冗長です。繰り返しになりますが、リクエストを頻繁に行う場合は、代わりに SDK を使用してください。

于 2015-11-05T18:01:00.390 に答える