c# - 用户 : (null) 授权失败

标签 c# asp.net-core

我正在为不使用 Identity 的 ASP.NET MVC Core 使用自定义身份验证。这是 Startup.cs:

public class Startup
{
    public IConfiguration Configuration { get; set; }

    // Configure IoC container
    // https://docs.asp.net/en/latest/fundamentals/dependency-injection.html
    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<AppSettings>(options => Configuration.GetSection(nameof(AppSettings)).Bind(options));

        // https://docs.asp.net/en/latest/security/anti-request-forgery.html
        services.AddAntiforgery(options => options.CookieName = options.HeaderName = "X-XSRF-TOKEN");

        services.AddDbContext<DbSesamContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("SesamConnection"));
        });

        services.AddDbContext<TerminalDbContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("TerminalConnection"));
        });

        services.AddMvcCore()
            .AddAuthorization()
            .AddViews()
            .AddRazorViewEngine()
            .AddJsonFormatters();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory factory)
    {
        // Configure logging
        // https://docs.asp.net/en/latest/fundamentals/logging.html
        factory.AddConsole(Configuration.GetSection("Logging"));
        factory.AddDebug();

        // Serve static files
        // https://docs.asp.net/en/latest/fundamentals/static-files.html
        app.UseStaticFiles();

        // Enable external authentication provider(s)
        // https://docs.asp.net/en/latest/security/authentication/sociallogins.html
        //app.UseIdentity();

        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            AuthenticationScheme = "ResWebAuth",
            LoginPath = new PathString("/login"),
            AccessDeniedPath = new PathString("/unauthorized/"),
            AutomaticAuthenticate = true,
            AutomaticChallenge = true,
        });

        // Configure ASP.NET MVC
        // https://docs.asp.net/en/latest/mvc/index.html
        app.UseMvc(routes =>
        {
            routes.MapRoute("default", "{*url}", new { controller = "Home", action = "Index" });
        });
    }

    public static void Main()
    {
        var cwd = Directory.GetCurrentDirectory();
        var web = Path.GetFileName(cwd) == "server" ? "../public" : "public";

        var host = new WebHostBuilder()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseWebRoot(web)
            .UseKestrel()
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        host.Run();
    }
}

在我的 Controller 中:

[Authorize]
public class HomeController : Controller
{
    public async Task<IActionResult> Index()
    {
        ...

        return View();
    }

    [HttpGet("login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login(string ReturnUrl)
    {
        ...

        return View();
    }

    [HttpPost("login")]
    [AllowAnonymous]
    public async Task<IActionResult> Login(LoginInfo loginInfo)
    {
        if (LoginUser(loginInfo.Username, loginInfo.Password))
        {
            var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, loginInfo.Username),
                    new Claim("DbVersion", loginInfo.Terminal.SesamDbVersion),
                    new Claim("DbUrl", loginInfo.Terminal.SesamDbUrl),
                    new Claim("DbName", loginInfo.Terminal.SesamDbName),
                    new Claim("DbUsername", loginInfo.Terminal.SesamDbUserName),
                    new Claim("DbPasswordHash", loginInfo.Terminal.SesamDbPasswordHash),
                };

            var userIdentity = new ClaimsIdentity(claims, "login");

            ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
            await HttpContext.Authentication.SignInAsync("ResWebAuth", principal);

            //Just redirect to our index after logging in. 
            return Redirect("/");
        }
        return View();
    }

    [HttpGet("getchartdata")]
    //[AllowAnonymous]
    public JsonResult GetChartData()
    {
        ...
    }

日志:

info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[3]
      HttpContext.User merged via AutomaticAuthentication from authenticationScheme: ResWebAuth.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]
      Authorization was successful for user: admin.

...

info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/getchartdata/
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[12]
      AuthenticationScheme: ResWebAuth was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action Server.Controllers.HomeController.GetChartData (server) in 5.2905ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 10.1037ms 302 

所以基本上它在 Controller 的 Index() 方法中成功授权了用户,但在同一 Controller 的 GetChartData() 方法中失败了。

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[1]Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 之间似乎有区别,我不明白它是什么以及如何修复它。

最佳答案

对于 ASP.Net Core 2.0,我在 Startup.Configure() 中添加了:app.UseAuthentication();这为我解决了这个错误。

引用:Auth 2.0 Migration announcement

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();

    app.UseAuthentication();

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });
}

注意:在Startup.Configure()中调用UseMvc()之前一定要调用UseAuthentication()如评论中所述。

The order that middleware components are added in the Configure method defines the order in which they're invoked on requests, and the reverse order for the response. This ordering is critical for security, performance, and functionality.

来源ASP.NET Core Docs -> Middleware -> Ordering

关于c# - 用户 : (null) 授权失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45198275/

相关文章:

c# - C# 中的内联函数 block

c# - 使用 ExceptionHandler PipeLine 时,ASP.NET Core 返回 404 而不是 500

c# - 在 Asp.Net 5 中,wwwroot/web.config 中的 %DNX_PATH% 来自哪里?

asp.net-mvc - 我可以在运行时更新我的​​ asp 核心站点吗?

asp.net-mvc - 添加基于策略的授权会跳过 JWT 持有者 token 身份验证检查吗?

c# - 将参数传递给委托(delegate)c#

C# .NET (WPF,DIGITALOCEAN) 创建 mysql 连接时现有数据库未知

c# - 中止一个线程还是让它被计算机清理?

c# - 将 IConfigurationSection 转换为 IOptions

c# - 如何将图像绘制到图片框?