User.Identity.Name 在 PasswordSignInAsync MVC .Net Core 3.0 之后始终为 null 并且声明计数为 0
User.Identity.Name always null and claims count 0 after PasswordSignInAsync MVC .Net Core 3.0
我有一个无法用 ASP.NET MVC Core 3.0 解决的问题。登录后结果是成功returns登录成功到我想要的页面,查看cookies或session可以看到API添加成功。但是当我尝试获取 User.Identity.Name 时,它始终为 null,并且 isAuthenticated 始终等于 false。这就像 app.UseAuthentication() 不读取 cookie 或会话。
我的startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
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.AddDbContextPool<AnisubsDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("AnisubsDBConnection")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AnisubsDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
services.AddControllersWithViews();
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = "353222242210621";
facebookOptions.AppSecret = "XXXX";
facebookOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddGoogle(googleOptions =>
{
googleOptions.ClientId = "1093176997632-ug4j2h7m9f1nl9rg8nucecpf9np0isro.apps.googleusercontent.com";
googleOptions.ClientSecret = "XXXX";
googleOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddTwitter(twitterOptions =>
{
twitterOptions.ConsumerKey = "lZ2ugpLuKpDOlmdSuyw1hVJLU";
twitterOptions.ConsumerSecret = "XXXX";
twitterOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = "22f501ab-70c9-4054-8f33-2b35af3a64ba";
microsoftOptions.ClientSecret = "XXXX";
microsoftOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddCookie();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
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.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
LoginController.cs
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel loginViewModel)
{
if (ModelState.IsValid)
{
var user = await userManager.FindByEmailAsync(loginViewModel.Email);
if (user != null)
{
var result = await signInManager.PasswordSignInAsync(user.UserName, loginViewModel.Password, loginViewModel.RememberMe, false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError(string.Empty, "Invalid Login Attempt");
}
return View(loginViewModel);
}
重定向到主页后的会话数
Razor 页面共享 _navbarlayout.cshtml(_layout.cshtml 内的部分视图)
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> signInManager;
<nav class="navbar fixed-top">
<a class="navbar-logo" href="Dashboard.Default.html">
<span class="logo d-none d-xs-block"></span>
<span class="logo-mobile d-block d-xs-none"></span>
</a>
<div class="navbar-right">
<div class="header-icons d-inline-block align-middle">
<div class="user d-inline-block">
<button class="btn btn-empty p-0" type="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
@if (signInManager.IsSignedIn(User))
{
<span class="name">@User.Identity.Name</span>
}
else
{
<span class="name">Not Registered</span>
}
<span>
<img alt="Profile Picture" src="img/profile-pic-l.jpg" />
</span>
</button>
<div class="dropdown-menu dropdown-menu-right mt-3">
@if (signInManager.IsSignedIn(User))
{
<a class="dropdown-item" href="#">Account</a>
<a class="dropdown-item" href="#">Features</a>
<a class="dropdown-item" href="#">History</a>
<a class="dropdown-item" href="#">Support</a>
<a class="dropdown-item" asp-action="logout" asp-controller="account">Sign out</a>
}
else
{
<a class="dropdown-item" asp-action="login" asp-controller="account">Login</a>
<a class="dropdown-item" asp-action="register" asp-controller="account">Register</a>
}
</div>
</div>
</div>
</nav>
从上面的剃须刀代码中,signInManager.IsSignedIn(用户)始终为假,User.identity 声明始终计数为零。
像下面这样更改了启动中间件的顺序,问题还是一样
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
下面是快速观看用户时的样子的GIF图片
尝试更改 "startup.cs" 中中间件的顺序。所以你应该像这样在 app.UseAuthentication()
之前使用 app.UseHttpsRedirection()
:
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
ASP.NET Core Identity 创建一个 cookie(在屏幕截图中显示为 .AspNetCore.Identity.Application
),它在成功调用 PasswordSignInAsync
后设置。 Startup.ConfigureServices
中对 AddIdentity
的调用设置了这一点:它注册了一个名为 Identity.Application
的身份验证方案,并将其设置为应用程序的默认身份验证方案。
现在,考虑到这一点,从问题中提取以下代码:
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
如上所示,对 AddAuthentication
的调用覆盖了 默认身份验证方案 CookieAuthenticationDefaults.AuthenticationScheme
。最终 PasswordSignInAsync
使用 Identity.Application
方案正确登录用户,但应用程序在尝试加载当前用户时使用 Cookies
方案。当然,这意味着永远不会加载用户。
在解决方案方面,只需从 AddAuthentication
中删除回调:
services.AddAuthentication()
.AddFacebook(facebookOptions =>
{
// ...
})
.AddGoogle(googleOptions =>
{
// ...
})
.AddTwitter(twitterOptions =>
{
// ...
})
.AddMicrosoftAccount(microsoftOptions =>
{
// ...
});
我还删除了对 AddCookie
的调用,这是多余的。这会添加 Cookies
身份验证方案,但您的应用程序正在使用 Identity.Application
,如前所述。
我有一个无法用 ASP.NET MVC Core 3.0 解决的问题。登录后结果是成功returns登录成功到我想要的页面,查看cookies或session可以看到API添加成功。但是当我尝试获取 User.Identity.Name 时,它始终为 null,并且 isAuthenticated 始终等于 false。这就像 app.UseAuthentication() 不读取 cookie 或会话。
我的startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
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.AddDbContextPool<AnisubsDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("AnisubsDBConnection")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AnisubsDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
services.AddControllersWithViews();
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddFacebook(facebookOptions =>
{
facebookOptions.AppId = "353222242210621";
facebookOptions.AppSecret = "XXXX";
facebookOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddGoogle(googleOptions =>
{
googleOptions.ClientId = "1093176997632-ug4j2h7m9f1nl9rg8nucecpf9np0isro.apps.googleusercontent.com";
googleOptions.ClientSecret = "XXXX";
googleOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddTwitter(twitterOptions =>
{
twitterOptions.ConsumerKey = "lZ2ugpLuKpDOlmdSuyw1hVJLU";
twitterOptions.ConsumerSecret = "XXXX";
twitterOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddMicrosoftAccount(microsoftOptions =>
{
microsoftOptions.ClientId = "22f501ab-70c9-4054-8f33-2b35af3a64ba";
microsoftOptions.ClientSecret = "XXXX";
microsoftOptions.CallbackPath = new Microsoft.AspNetCore.Http.PathString("/Login/Callback");
})
.AddCookie();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
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.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
LoginController.cs
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel loginViewModel)
{
if (ModelState.IsValid)
{
var user = await userManager.FindByEmailAsync(loginViewModel.Email);
if (user != null)
{
var result = await signInManager.PasswordSignInAsync(user.UserName, loginViewModel.Password, loginViewModel.RememberMe, false);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
}
ModelState.AddModelError(string.Empty, "Invalid Login Attempt");
}
return View(loginViewModel);
}
重定向到主页后的会话数
Razor 页面共享 _navbarlayout.cshtml(_layout.cshtml 内的部分视图)
@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> signInManager;
<nav class="navbar fixed-top">
<a class="navbar-logo" href="Dashboard.Default.html">
<span class="logo d-none d-xs-block"></span>
<span class="logo-mobile d-block d-xs-none"></span>
</a>
<div class="navbar-right">
<div class="header-icons d-inline-block align-middle">
<div class="user d-inline-block">
<button class="btn btn-empty p-0" type="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
@if (signInManager.IsSignedIn(User))
{
<span class="name">@User.Identity.Name</span>
}
else
{
<span class="name">Not Registered</span>
}
<span>
<img alt="Profile Picture" src="img/profile-pic-l.jpg" />
</span>
</button>
<div class="dropdown-menu dropdown-menu-right mt-3">
@if (signInManager.IsSignedIn(User))
{
<a class="dropdown-item" href="#">Account</a>
<a class="dropdown-item" href="#">Features</a>
<a class="dropdown-item" href="#">History</a>
<a class="dropdown-item" href="#">Support</a>
<a class="dropdown-item" asp-action="logout" asp-controller="account">Sign out</a>
}
else
{
<a class="dropdown-item" asp-action="login" asp-controller="account">Login</a>
<a class="dropdown-item" asp-action="register" asp-controller="account">Register</a>
}
</div>
</div>
</div>
</nav>
从上面的剃须刀代码中,signInManager.IsSignedIn(用户)始终为假,User.identity 声明始终计数为零。
像下面这样更改了启动中间件的顺序,问题还是一样
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
下面是快速观看用户时的样子的GIF图片
尝试更改 "startup.cs" 中中间件的顺序。所以你应该像这样在 app.UseAuthentication()
之前使用 app.UseHttpsRedirection()
:
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
ASP.NET Core Identity 创建一个 cookie(在屏幕截图中显示为 .AspNetCore.Identity.Application
),它在成功调用 PasswordSignInAsync
后设置。 Startup.ConfigureServices
中对 AddIdentity
的调用设置了这一点:它注册了一个名为 Identity.Application
的身份验证方案,并将其设置为应用程序的默认身份验证方案。
现在,考虑到这一点,从问题中提取以下代码:
services.AddAuthentication(options => { options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; })
如上所示,对 AddAuthentication
的调用覆盖了 默认身份验证方案 CookieAuthenticationDefaults.AuthenticationScheme
。最终 PasswordSignInAsync
使用 Identity.Application
方案正确登录用户,但应用程序在尝试加载当前用户时使用 Cookies
方案。当然,这意味着永远不会加载用户。
在解决方案方面,只需从 AddAuthentication
中删除回调:
services.AddAuthentication()
.AddFacebook(facebookOptions =>
{
// ...
})
.AddGoogle(googleOptions =>
{
// ...
})
.AddTwitter(twitterOptions =>
{
// ...
})
.AddMicrosoftAccount(microsoftOptions =>
{
// ...
});
我还删除了对 AddCookie
的调用,这是多余的。这会添加 Cookies
身份验证方案,但您的应用程序正在使用 Identity.Application
,如前所述。