web-dev-qa-db-ja.com

.net-coreミドルウェアが空白の結果を返す

APIを使用してWebサイトを作成している場合、ユーザーが自分のデータのみを取得できるように、APIを検証する必要があります。ログインを検証するために、次のミドルウェアを作成しました。

public class ApiAuthenticationMiddleware
{
    private readonly RequestDelegate _next;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;

    public ApiAuthenticationMiddleware(RequestDelegate next,
        SignInManager<ApplicationUser> signInManager,
        UserManager<ApplicationUser> usermanager)
    {
        _next = next;
        _signInManager = signInManager;
        _userManager = usermanager;
    }

    public async  Task Invoke(HttpContext context)
    {
        if (!context.Request.Query.ContainsKey("password") || !context.Request.Query.ContainsKey("email"))
        {
            context.Response.StatusCode = 401; //UnAuthorized
            await context.Response.WriteAsync("Invalid User Key");
            return;
        }
        var email = context.Request.Query["email"];
        var password = context.Request.Query["password"];

        var result = await _signInManager.PasswordSignInAsync(email, password, false, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            await _next.Invoke(context);
        }
        else if (//some more checks)
            context.Response.StatusCode = 401; //UnAuthorized
            await context.Response.WriteAsync("Invalid User Key");
            return;
        }
    }
}

私が欲しいのは、ユーザーが有効なログインを持っていない場合、空白のページまたは「無効なユーザーキー」のようなエラーメッセージが表示されることです。ただし、現時点で発生するのはホームページが返されることです(usemvcの前にミドルウェアが呼び出され、returnステートメントがusemvcによって実行されたコントローラー要求をスキップするため)。

Startup.csのconfigureメソッドの関連コード

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {

        app.UseIdentity();
        app.UseWhen(x => (x.Request.Path.StartsWithSegments("/api", StringComparison.OrdinalIgnoreCase)),
            builder =>
            {
                builder.UseMiddleware<ApiAuthenticationMiddleware>();
            });
        app.UseStaticFiles();
        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }

ミドルウェアにステータスコードのある空白のページを返すようにするにはどうすればよいですか?

更新

多くのことを試した後、削除すると次のことがわかりました。

 context.Response.StatusCode = 401; //UnAuthorized

期待どおりに機能し、ユーザーは次のメッセージを受け取ります。

await context.Response.WriteAsync("Invalid User Key"); 

ただし、ログインに失敗したときにユーザーが200のステータスコードを取得するのではなく、401のステータスコードを取得する必要があります。ただし、ステータスコード行を使用すると、ユーザーはリダイレクトされます。では、リダイレクトせずにステータスコードを送信するにはどうすればよいですか?

17

app.UseIdentity()には、403/401が発生すると応答をインターセプトし、リダイレクトを開始するというデフォルトの動作があるという予感があります。コメントアウトして、機能するかどうかを確認してください。

別の解決策を参照してください: https://stackoverflow.com/a/43456151/3948882

最後のコメント:リクエストごとに資格情報を渡さないことを強くお勧めします。ビルド済みの認証プロバイダーを使用し、ミドルウェアとして実装することをお勧めします。 Authorize属性は、行われた要求に十分であり、探していることを実行できます。何か特別なものを返したい場合は、app.UseIdentity()ミドルウェアがリダイレクトを使用している可能性があるようにミドルウェアで応答をオーバーライドできます。

4
Brandon

StatusCodeを設定する前に、.Clear()を使用してみてください。

            context.Response.Clear();
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            await context.Response.WriteAsync("Unauthorized");
3
Darxtar

ContentTypeも設定する必要があります。このようなもの:

        context.Response.ContentType = "text/plain";
        context.Response.StatusCode = 401; //UnAuthorized
        await context.Response.WriteAsync("Invalid User Key");
0
Torben Nielsen