2

私は単純な API の例、つまり ServiceStack の Hello World の例を認証付きで修正したバージョンを使って作業してきました。概念実証の目標は、いくつかの異なる Web プロジェクトから完全に Ajax を介してアクセスできる、認証を必要とするサービスを含む RESTful API を作成することです。

認証と承認、およびCORSの実装についてwikiを読み、実装しました(多くの結果[申し訳ありませんが、関連するリンクを指すのに十分な信用がありません])。この時点で、私の Hello サービスは、CredentialsAuthProvider とカスタム ユーザー セッション オブジェクトをオーバーライドするカスタム認証メカニズムを使用して認証できます。簡単なテスト アプリケーション (私たちのニーズをシミュレートするための完全に別のプロジェクト) を作成または借用し、認証してから Hello サービスを呼び出し、名前を渡し、'Hello Fred' 応答を単一のブラウザセッション。つまり、URL で /auth/credentials パスを呼び出し、ユーザー名と ID を渡して、適切な応答を受け取ることができます。その後、URL を /hello/fred に更新すると、有効な応答を受け取ることができます。

私の理解の内訳は、すべての ajax 呼び出しの認証を実装する方法です。以下の最初のログインは正常に機能します。何をしても、認証されたサービスを ajax 経由で呼び出そうとすると、OPTIONS 404 エラーまたは Not Found エラーが発生するか、Origin http // localhost:12345 (pseudo-link) is not allowed by Access-Control-Allow が表示されます。・出身地など

このルートに行く必要がありますか?

これが紛らわしい場合は申し訳ありません。必要に応じてより詳細な情報を提供できますが、知識のある方が私の理解不足を解消するには、これで十分だと思います。

    function InvokeLogin() {
    var Basic = new Object();
    Basic.UserName = "MyUser";
   Basic.password = "MyPass";

    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: JSON.stringify(Basic),
        url: "http://localhost:58795/auth/credentials",
        success: function (data, textStatus, jqXHR) {
                alert('Authenticated! Now you can run Hello Service.');
            },
        error: function(xhr, textStatus, errorThrown) {
            var data = $.parseJSON(xhr.responseText);
            if (data === null)
                alert(textStatus + " HttpCode:" + xhr.status);
            else
                alert("ERROR: " + data.ResponseStatus.Message + (data.ResponseStatus.StackTrace ? " \r\n Stack:" + data.ResponseStatus.StackTrace : ""));
        }
    });
}

編集:

Stefan から提供された回答とリンクに基づいて、いくつかの変更を加えました。

My Config (注: カスタム認証とセッション オブジェクトを使用していますが、すべて正しく機能しています。)

public override void Configure(Funq.Container container)
{
    Plugins.Add(new AuthFeature(() => new CustomUserSession(), 
                new IAuthProvider[] {
                new CustomCredentialsAuthProvider(),
                    }));

    base.SetConfig(new EndpointHostConfig
    {
        GlobalResponseHeaders = {
            { "Access-Control-Allow-Origin", "*" },
            { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
            { "Access-Control-Allow-Headers", "Content-Type, Authorization" },
        },
        DefaultContentType = "application/json"
    });

    Plugins.Add(new CorsFeature());
    this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
    {
        //Handles Request and closes Responses after emitting global HTTP Headers
        if (httpReq.HttpMethod == "OPTIONS")
            httpRes.EndRequest();   //   extension method
    });

    Routes
        .Add<Hello>("/Hello", "GET, OPTIONS");


    container.Register<ICacheClient>(new MemoryCacheClient());
    var userRep = new InMemoryAuthRepository();
    container.Register<IUserAuthRepository>(userRep);
}

私のシンプルなハローサービス

[EnableCors]
public class HelloService : IService
{
    [Authenticate]
    public object GET(Hello request)
    {
        Looks strange when the name is null so we replace with a generic name.
        var name = request.Name ?? "John Doe";
        return new HelloResponse { Result = "Hello, " + name };
    }
}

上記のログイン呼び出しを行った後、その後の Hello サービスの呼び出しで 401 エラーが発生しました。これは進行状況ですが、必要な場所ではありません。(私のスクリプトファイルには Jquery.support.cors= true が設定されています。)

function helloService() {
    $.ajax({
        type: "GET",
        contentType: "application/json",
        dataType: "json",
        url: "http://localhost:58795/hello",
        success: function (data, textStatus, jqXHR) {
            alert(data.Result);
        },
        error: function (xhr, textStatus, errorThrown) {
            var data = $.parseJSON(xhr.responseText);
            if (data === null)
                alert(textStatus + " HttpCode:" + xhr.status);
            else
                alert("ERROR: " + data.ResponseStatus.Message +
                    (data.ResponseStatus.StackTrace ? " \r\n Stack:" + data.ResponseStatus.StackTrace : ""));
        }
    });
}

繰り返しますが、これは、最初に /auth/credentials を適切に呼び出し、その後に /hello を呼び出すと、RESTConsole で機能します。

最終編集 以下のステファンのアドバイスに従い、他の多くのリンクを含めて、ようやくこれを機能させることができました。Stefan のコードに加えて、さらに 1 つの変更を加える必要がありました。

Plugins.Add(new CorsFeature(allowedHeaders: "Content-Type, Authorization"));

次の課題: Jonas Eriksson の CustomAuthenticateAttibute コードの更新 (いくつかの機能が使用できなくなったため、古いバージョンの ServiceStack を使用しているようです。

ありがとうステファン!!

4

1 に答える 1