【发布时间】:2022-12-12 16:18:45
【问题描述】:
很长一段时间以来,我一直在努力使它正常工作,但不知道如何正确地进行。我能够使用 LocalStorage 实现 Rememeber Me。但是,我想使用 cookie 通过 JWT 实现记住我的功能,我可以在其中设置过期时间。我想我弄乱了登录逻辑?有人可以指出这里有什么问题吗?
如有必要,我还可以从我的应用程序中添加其他部分。
授权控制器.cs:
[HttpPost]
public async Task<IActionResult> Login([FromBody] LoginModel login)
{
ApplicationUser user = await this.SignInManager.UserManager.FindByEmailAsync(login.Email);
if (user == null)
{
List<string> errors = new List<string>();
errors.Add("No such user has been found.");
return BadRequest(new LoginResult
{
Successful = false,
Errors = errors,
});
}
bool emailConfirmed = await this.UserManager.IsEmailConfirmedAsync(user);
if (!emailConfirmed)
{
List<string> errors = new List<string>();
errors.Add("Email not confirmed.");
return BadRequest(new LoginResult
{
Successful = false,
Errors = errors,
});
}
Microsoft.AspNetCore.Identity.SignInResult result =
await this.SignInManager.PasswordSignInAsync(login.Email, login.Password, login.RememberMe, false);
if (!result.Succeeded)
{
List<string> errors = new List<string>();
errors.Add("Email and password are invalid.");
return BadRequest(new LoginResult
{
Successful = false,
Errors = errors,
});
}
IList<string> roles = await this.SignInManager.UserManager.GetRolesAsync(user);
List<Claim> claims = new List<Claim>
{
new Claim(ClaimTypes.Name, login.Email)
};
ClaimsIdentity identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
AuthenticationProperties props = new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddMonths(1)
};
// to register the cookie to the browser
this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, props).Wait();
foreach (string role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.Configuration["JwtSecurityKey"]));
SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
DateTime expiry = DateTime.Now.AddDays(Convert.ToInt32(this.Configuration["JwtExpiryInDays"]));
JwtSecurityToken token = new JwtSecurityToken(
this.Configuration["JwtIssuer"],
this.Configuration["JwtAudience"],
claims,
expires: expiry,
signingCredentials: creds
);
return Ok(new LoginResult
{
Successful = true,
Token = new JwtSecurityTokenHandler().WriteToken(token),
});
}
启动.cs:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["JwtIssuer"],
ValidAudience = Configuration["JwtAudience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtSecurityKey"]))
};
})
.AddCookie(options =>
{
options.Cookie.Name = "MySpecialCookie";
options.LoginPath = "/login";
//options.LogoutPath = "/Home/Index";
//options.AccessDeniedPath = "AccessDenied";
options.ExpireTimeSpan = TimeSpan.FromDays(30);
options.SlidingExpiration = true; // the cookie would be re-issued on any request half way through the ExpireTimeSpan
//options.Cookie.Expiration = TimeSpan.FromDays(5);
options.EventsType = typeof(CookieAuthEvent);
});
services.AddScoped<CookieAuthEvent>();
services.AddAuthorization(config =>
{
config.AddPolicy(Policies.IsAdmin, Policies.IsAdminPolicy());
config.AddPolicy(Policies.IsUser, Policies.IsUserPolicy());
});
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = true;
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
在客户端,我目前正在使用 AuthorizeApi 和 LocalStorage。这行得通,但我想将其移至 Cookie。
授权API.cs:
public async Task<LoginResult> Login(LoginModel loginModel)
{
//var stringContent = new StringContent(JsonSerializer.Serialize(LoginModel), Encoding.UTF8, "application/json");
HttpResponseMessage responseMessage = await this.HttpClient.PostAsJsonAsync("Authorize/Login", loginModel);
LoginResult result = await responseMessage.Content.ReadFromJsonAsync<LoginResult>();
if (result.Successful)
{
if (loginModel.RememberMe)
{
await this.LocalStorage.SetItemAsync("MySpecialToken", result.Token);
}
((ApiAuthenticationStateProvider)this.AuthenticationStateProvider).MarkUserAsAuthenticated(result.Token);
this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.Token);
return result;
}
return result;
}
ApiAuthenticationStateProvider.cs:
public void MarkUserAsAuthenticated(string token)
{
ClaimsPrincipal authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"));
Task<AuthenticationState> authState = Task.FromResult(new AuthenticationState(authenticatedUser));
NotifyAuthenticationStateChanged(authState);
}
【问题讨论】: