asp.net-core - HttpContext.User null 与经过身份验证的用户?

标签 asp.net-core asp.net-identity

所以我正在开发一个 .net core 2 项目,我们希望在该项目中创建一个可用于 future 项目的基本平台。对于登录,我们使用 Identity。我们已经完成所有设置,用户可以成功登录并设置 cookie。出于某种原因,一旦我们调用 HttpContext.User,这将导致 null。我很确定它确实找到了一个身份,但这个身份是空的。我们已经检查了 cookie,它非常好,它有它的 token 。我们确实添加了 token 身份验证,但这不应该在设置 cookie 时干扰 cookie 系统。

下面是Startup.cs

public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<MyIdentityDbContext>(options => options
        .UseSqlServer("Data Source=PATH;Initial Catalog=DB;Persist Security Info=True;User ID=ID;Password=*******"));

        services.AddSingleton<IJwtFactory, JwtFactory>();

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        }).AddCookie();

        services.AddIdentity<User, IdentityRole>(options =>
        {
            options.SignIn.RequireConfirmedEmail = true;
            options.User.RequireUniqueEmail = false;
            options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
        })
    .AddEntityFrameworkStores<MyIdentityDbContext>()
    .AddDefaultTokenProviders();

        services.Configure<IISOptions>(options =>
        {
            options.ForwardClientCertificate = false;
        });

        var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));

        services.Configure<JwtIssuerOptions>(options =>
        {
            options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
            options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
            options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
        });

        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],

            ValidateAudience = true,
            ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

            ValidateIssuerSigningKey = true,
            IssuerSigningKey = _signingKey,

            RequireExpirationTime = false,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero
        };

        services
           .AddAuthentication(options =>
           {
               options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
               options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

           })
       .AddJwtBearer(cfg =>
       {
           cfg.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
           cfg.TokenValidationParameters = tokenValidationParameters;
           cfg.SaveToken = true;
       });

        services.Configure<IdentityOptions>(options =>
        {
            // Password settings
            options.Password.RequireDigit = true;
            options.Password.RequiredLength = 8;
            options.Password.RequireNonAlphanumeric = true;
            options.Password.RequireUppercase = true;
            options.Password.RequireLowercase = true;
            options.Password.RequiredUniqueChars = 6;

            // Lockout settings
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
            options.Lockout.MaxFailedAccessAttempts = 5;
            options.Lockout.AllowedForNewUsers = true;

            // User settings
            options.User.RequireUniqueEmail = true;
        });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.LoginPath = "/Account/Login"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login
            options.LogoutPath = "/Account/Logout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout
            options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
            options.SlidingExpiration = true;
            options.Cookie = new CookieBuilder
            {
                HttpOnly = true,
                Name = "MyAuthToken",
                Path = "/",
                SameSite = SameSiteMode.Lax,
                SecurePolicy = CookieSecurePolicy.SameAsRequest
            };
        });


        services.AddAuthorization(options =>
        {
            options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("Employee"));
            options.AddPolicy("OwnerOnly", policy => policy.RequireClaim("Owner"));
            options.AddPolicy("AdminOnly", policy => policy.RequireClaim("Admin"));
            options.AddPolicy("ModeratorOnly", policy => policy.RequireClaim("Moderator"));
        });

        services.AddTransient<IEmailSender, EmailSender>();
        services.Configure<AuthMessageSenderOptions>(Configuration);

        services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
    }

这是 Controller 中用于获取用户的代码:

 User _user = await _userManager.GetUserAsync(HttpContext.User);

以及我们用来登录用户的代码:

var result = await _signInManager.PasswordSignInAsync(model.Email,
                    model.Password, true, false);

最佳答案

您编写了两次 AddAuthentication,一次用于 Cookie,一次用于 JWT 并覆盖默认值。

只使用一次AddAuthentication,并添加CookieJWT

services.AddAuthentication(options =>
{
    // set schema here
})
.AddCookie(config =>
{
    //config cookie
})
.AddJwtBearer(config =>
{
    //config jwt
});

现在您有两种身份验证方案,您必须选择要使用哪一种来验证您的请求

[授权(CookieAuthenticationDefaults.AuthenticationScheme)]

[授权(JwtBearerDefaults.AuthenticationScheme)]

或者两者兼而有之

[Authorize($"{CookieAuthenticationDefaults.AuthenticationScheme},{JwtBearerDefaults.AuthenticationScheme}")]

关于asp.net-core - HttpContext.User null 与经过身份验证的用户?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50025679/

相关文章:

c# - 热衷于从同一解决方案中的另一个项目访问 appsettings.json?

asp.net-core - 在默认包装器中返回响应

c# - Mediatr 无法解析 ASP.Net Core 中的 UserManager

asp.net - 在 ASP.NET 身份验证系统中合并 OAuth 帐户

asp.net-mvc - 使用 Controller 的单页应用程序 - 如何使用 ASP.NET Identity 保证安全?

asp.net-core - 获取 ASP.NET Core 3.0 中所有注册的路由

c# - 在 .NET Core 类构造函数中注入(inject)接口(interface)的所有实现者

asp.net-mvc - ASP.Net MVC 5 Google 身份验证与范围

c# - 验证访问 token - Asp.Net 身份

asp.net-mvc - ASP MVC 5 (Microsoft.AspNet.Identity) 用户管理包