私は単純な 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 を使用しているようです。
ありがとうステファン!!