【发布时间】:2020-12-23 20:20:42
【问题描述】:
实际上是 asp.net core 3.1 中的新手,我正在尝试创建用户登录并使用 cookie 注册
当我试图让ClaimTypes.NameIdentifier 总是返回 null 时,你能帮帮我吗?
控制器代码
public class AccountController : ControllerBase
{
private readonly ApiSiteDbContext _db;
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
private readonly RoleManager<AppRole> _roleManager;
public AccountController(ApiSiteDbContext db,
UserManager<AppUser> userManager,
SignInManager<AppUser> signInManager,
RoleManager<AppRole> roleManager)
{
_db = db;
_userManager = userManager;
_signInManager = signInManager;
_roleManager = roleManager;
}
[AllowAnonymous]
[HttpPost("Login")]
public async Task<IActionResult> Login(LoginModel loginModel)
{
var user = await _userManager.FindByEmailAsync(loginModel.Email);
// **** this is always return null *****
var id = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (id != null)
{
return BadRequest("User already logged !!");
}
var result = await _signInManager.PasswordSignInAsync(user, loginModel.Password, loginModel.RememberMe, true);
if (result.Succeeded)
{
if (await _roleManager.RoleExistsAsync("User"))
{
if (!await _userManager.IsInRoleAsync(user, "User"))
{
await _userManager.AddToRoleAsync(user, "User");
}
}
var roleName = await GetRoleNameByUserId(user.Id);
if (roleName != null)
{
AddCookies(user.UserName, user.Id, roleName, loginModel.RememberMe, user.Email);
}
return Ok();
}
else if (result.IsLockedOut)
{
return Unauthorized("Your account were locked");
}
return BadRequest("Wrong password!");
//return StatusCode(StatusCodes.Status204NoContent);
}
public async void AddCookies(string userName, string userId, string roleName, bool remember, string email)
{
var claim = new List<Claim>
{
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.Email, email),
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Role, roleName),
};
var claimIdentity = new ClaimsIdentity(claim, CookieAuthenticationDefaults.AuthenticationScheme);
if (remember)
{
var authProperties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddDays(10)
};
await HttpContext.SignInAsync
(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimIdentity),
authProperties
);
}
else
{
var authProperties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = false,
ExpiresUtc = DateTime.UtcNow.AddMinutes(30)
};
await HttpContext.SignInAsync
(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimIdentity),
authProperties
);
}
}
}
在 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.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = Context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddControllers();
//services.AddControllersWithViews();
services.AddDbContext<ApiSiteDbContext>();
services.AddIdentity<AppUser, AppRole>(option =>
{
option.Password.RequireDigit = true;
option.Password.RequiredLength = 6;
option.Password.RequiredUniqueChars = 0;
option.Password.RequireLowercase = true;
option.Password.RequireNonAlphanumeric = true;
option.Password.RequireUppercase = true;
option.SignIn.RequireConfirmedEmail = true;
option.Lockout.MaxFailedAccessAttempts = 5;
option.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
}).AddEntityFrameworkStores<ApiSiteDbContext>()
.AddDefaultTokenProviders();
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
options.LogoutPath = "/api/Account/Logout";
//options.LoginPath = "/api/Account/Login";
//options.AccessDeniedPath = "/api/Account/accessDenied";
options.SlidingExpiration = true;
});
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_3_0);
services.AddCors();
}
// 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();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(x => x.WithOrigins("http://localhost:4200").AllowAnyHeader().AllowAnyMethod().AllowCredentials());
app.UseMvc();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
当我在另一个控制器中使用这个变量之前检查 NameIdentifier 是否返回 id 时。
【问题讨论】:
-
在您的
Login方法中,如果id!=null,您将返回BadRequest。这意味着当您最终调用AddCookies方法(在其中添加NameIdentifier声明)时,id被保证为null。这就是为什么它总是null,对吧? -
@crgolden 它不是每次都必须返回 null ,我创建这个变量以确保返回值但它没有返回,它必须在第一次登录时为 null 并且如果用户登录返回错误请求有一条消息我把它测试了
-
@MohamedElSoufi 首次登录时确保调用了
AddCookies方法,否则不会有NameIdentifier声明。
标签: c# asp.net-core asp.net-web-api