简体   繁体   中英

ASP.NET Core 2.2 authorize attribute with roles not working

I am migrating an ASP.NET 4.6 MVC app to Asp.Net Core 2.2. I have managed to migrate all the data. I have checked the AspNetUsers, AspNetRoles, and AspNetUserRoles tables and they have the migrated data. I scaffolded the Login and AccessDenied pages using the Razor Class Library as per the offical docs

[ https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-2.2&tabs=visual-studio]

My scenario is as follows: I have a controller named Leads which has an action named Create. I want only those users who belong to the CreateLead role to access the Create action. For testing purposes I have configured it to be the default page so when the application starts it will redirect the user to the Login page because the action is protected by the Authorize attribute. If the user is authenticated they will be redirected to the Leads contoller.

I can successfully login using my username and password stored in the AspNetUsers table. If I add the Authorize attribute without specifying the Role property and without adding the AddRoles extension in the Startup class I am being redirected to the Create view successfully.

 [Authorize]
 public IActionResult Create()
 {
     return View();
 }

Startup class

services.AddDefaultIdentity<User>()
      .AddEntityFrameworkStores<SalesIdentityContext>();

However, if I specify the Roles property and add the AddRoles extension to the Startup class as shown below the browser will not load the view. Its giving me the following error: The webpage at https://localhost:44388/ might be temporarily down or it may have moved permanently to a new web address: ERR_SPDY_PROTOCOL_ERROR.

[Authorize( Roles = "CreateLead")]
public IActionResult Create()
{
    return View();
}

Startup class:

public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<CookiePolicyOptions>(options =>
        {
            options.CheckConsentNeeded = context => true;
            options.MinimumSameSitePolicy = SameSiteMode.None;
        });

        services.AddDbContext<SalesIdentityContext>(options =>
         options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));

        services.AddDefaultIdentity<User>()
            .AddRoles<IdentityRole>()
            .AddEntityFrameworkStores<SalesIdentityContext>();

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
            options.LoginPath = "/Identity/Account/Login";
            options.AccessDeniedPath = "/Identity/Account/AccessDenied";
            options.SlidingExpiration = true;
        });

        // Add application services.
        services.AddScoped(typeof(IAppLogger<>), typeof(LoggerAdapter<>));
        services.AddScoped<ILeadService, LeadService>();

        services.AddHttpClient("my_api_client_name", c => 
        {
            c.BaseAddress = "my_api_uri");
        });

        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            ListAllRegisteredServices(app);
            app.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            //app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseAuthentication();
        app.UseMvc(routes =>
        {
            routes.MapRoute(name: "default", template: "{controller=Leads}/{action=Create}/{id?}");
        });
    }

I have a custom identity class named User which is extending the IdentityUser class. On the User class I have added FirstName and LastName properties.

I have checked the AspNetUserRoles table and can confirm that both the UserId and RoleId are available.

Visual Studio Output Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler:Information: AuthenticationScheme: Identity.Application signed in. WebApp.Areas.Identity.Pages.Account.LoginModel:Information: User logged in. Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed handler method OnPostAsync, returned result Microsoft.AspNetCore.Mvc.LocalRedirectResult. Microsoft.AspNetCore.Mvc.Infrastructure.LocalRedirectResultExecutor:Information: Executing LocalRedirectResult, redirecting to /. Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker:Information: Executed page /Account/Login in 10100.4486ms Microsoft.AspNetCore.Routing.EndpointMiddleware:Information: Executed endpoint 'Page: /Account/Login' Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 10232.1354ms 302

You Can Add

app.UseAuthorization();

under

  app.UseAuthentication();

You are missing addauthorization after addmvc. In Configure service method, change it as follow: services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2).AddAuthorization();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM