Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.3k views
in Technique[技术] by (71.8m points)

basic authentication - IAsyncAuthorizationFilter is executed after redirect to login page

I've migrated an ASP.NET Core MVC 2.2 web application to ASP.NET Core 5 MVC. I'm using an IAsyncAuthorizationFilter (global filter) to do BasicAuthentication for my API controllers.

In 2.2 this was working fine. With 5.0 (and I think also 3.1), I get the default login page when calling the ApiController because the AuthorizationFilter gets executed after the Identity framework is doing the redirect to the login page because of the Authorize attribute placed on the controller. The filter is registered as global filter in the ConfigureServices method.

I was able to reproduce the behavior by creating a new ASP.NET Core 5 web application with Identity (individual user account). Then I created an ApiController and a dummy IAsyncAuthorizationFilter that checks for the request path.

When I call the ApiController URL at https://localhost:xxx/api/data/get with Postman, the content of the login page is returned. As far as I know auth filter are executed first in the request pipeline in order to handle authorization.

But in that scenario I have no change to do that because the Authorize attribute on the controller causes the auth framework to request the login credentials via the login page. Was there a change from version 2.2 to 3.x/5.0 ?

Here are the code snippets.

Dummy filter:

public class ApiBasicAuthorizationFilter : IAsyncAuthorizationFilter
{
     public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
     {
         // execute only when the api route is called
         // error: the route here is /Account/Login because OnAuthorizeAsync is executed after the Redirect
         if (context.HttpContext.Request.Path.Value.Contains("/api"))
         {
             var identity = new ClaimsIdentity("identity");
             identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "user1"));
             identity.AddClaim(new Claim(ClaimTypes.Name, "user1"));
             var principal = new ClaimsPrincipal(identity);
             context.HttpContext.User = principal;
         }
     }
}

Filter registration

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();

    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddControllersWithViews(options => 
    {
        options.Filters.Add<ApiBasicAuthorizationFilter>();
    });
}

ApiController:

[ApiController]
[Route("api/data")]
[Authorize]
public class DataController : Controller
{
    [HttpGet("get")]
    public async Task<string> GetData()
    {
        return "TEST";
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...