首页 > 解决方案 > 从 mvc 中的中间件手动调用授权流程

问题描述

我在 MVC aspnet core 2 应用程序中设置了 oauth 授权。当我使用该[Authorize]属性时它按预期工作,但我无法让它与我的中间件一起使用RequestHandler

我尝试创建一个调用该context.ChallengeAsync()方法的服务,但是从中间件调用时它失败了(调用从不重定向)。如果用户尚未登录,则永远不会显示同意页面,并且返回的令牌是null.

如果用户已经登录,则调用返回令牌。从控制器内部调用该服务时(而不是使用[Authorize]) ,该服务确实有效

那么我该如何让它工作呢?在继续之前,我想确保用户已获得授权(以便我可以访问令牌)...

以下是相关的代码部分:

启动.cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OAuthOptionsDefaults.SchemeName;
        })
       .AddCookie() 
       .AddOAuth(OAuthOptionsDefaults.SchemeName, 
                options => { options.SaveTokens = true;  /*other options*/ });

        services.AddMvc();

        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddScoped<IOAuthService, OAuthService>();
        services.AddTransient<IRequestHandler, RequestHandler>();
    }

    public void Configure(IApplicationBuilder app, IRequestHandler requestHandler, ..)
    {

        app.UseExceptionHandler("/Home/Error");
        app.UseStaticFiles();
        app.UseAuthentication();

        app.Map(new PathString("/myapi"), appbuilder =>
        {
            appbuilder.Run(async (context) =>
            {
                await requestHandler.Handle(context, "url to an api", "an api key");
            });

        });

        app.UseMvcWithDefaultRoute();
    }
}

请求处理程序.cs

public class RequestHandler : IRequestHandler
{
    //[Authorize] doesn't work
    public async Task Handle(HttpContext context, string apiUrl, string apiKey)
    {   
        //injected IOAuthService _service;
        //tried with and without context as parameter
        var accessToken = await _service.GetAccesTokenAsync();

        //do stuff ... 
    }
}

OAuthService.cs

public class OAuthService : IOAuthService
{
    private async Task<string> GetAccesTokenAsyncHelper(HttpContext context)
    {
        var isAuthenticated = ((ClaimsIdentity)context.User.Identity)?.IsAuthenticated ?? false;
        if (!isAuthenticated)
        {
            //tried with and without setting schemename
            await context.ChallengeAsync(OAuthOptionsDefaults.SchemeName);
        }

        return await context.GetTokenAsync(OAuthOptionsDefaults.SchemeName, "access_token");
    }

    public async Task<string> GetAccesTokenAsync()
    {
        //injected IHttpContextAccessor _accessor;
        var context = _accessor.HttpContext;
        return await GetAccesTokenAsyncHelper(context);
    }

    public async Task<string> GetAccesTokenAsync(HttpContext context)
    {
        return await GetAccesTokenAsyncHelper(context);
    }
}

编辑:使问题更短,更指向希望有人回答。

标签: c#asp.net-mvcasp.net-coreoauthauthorization

解决方案


您需要将 Identity 添加到 HttpContext 的用户属性

context.User.AddIdentity((ClaimsIdentity) principal.Identity);

我在这里添加了一个教程,解释了如何使用来自 URL 的 JWT 在中间件中授权 HttpContext 希望这会有所帮助:)


推荐阅读