我的登录代码有以下内容,还有另一种在另一个呼叫中检索用户ID的方法。
// POST: /api/Account/Login
[HttpPost]
[AllowAnonymous]
public async Task<IActionResult> Login([FromBody]LoginViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user != null)
{
if (!await _userManager.IsEmailConfirmedAsync(user))
{
ModelState.AddModelError(string.Empty,
"You must have a confirmed email to log in.");
return BadRequest(Errors.AddErrorToModelState("Email", "You must have a confirmed email to log in.", ModelState));
}
}
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
// IS THIS NEEDED? --> // HttpContext.User = await _userClaimsPrincipalFactory.CreateAsync(user);
var tokens = _antiforgery.GetAndStoreTokens(HttpContext);
var identity = _jwtFactory.GenerateClaimsIdentity(model.Email, user.Id);
_logger.LogInformation(1, "User logged in.");
var jwt = await Tokens.GenerateJwt(identity, _jwtFactory, model.Email, _jwtOptions, new JsonSerializerSettings { Formatting = Formatting.Indented });
return new OkObjectResult(jwt);
}
if (result.RequiresTwoFactor)
{
//return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (result.IsLockedOut)
{
string message = "User account locked out.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));
}
if (result.IsNotAllowed)
{
string message = "User account is not allowed to sign in.";
_logger.LogWarning(2, message);
return BadRequest(Errors.AddErrorToModelState("Email", message, ModelState));
}
return BadRequest(Errors.AddErrorToModelState("", "Sign in failed.", ModelState));
}
return BadRequest(Errors.AddErrorToModelState("", "", ModelState));
}
public string GetUserId()
{
string username = string.Empty;
ClaimsPrincipal principal = HttpContext.User as ClaimsPrincipal;
if (HttpContext.User != null)
{
var id = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier);
if (id != null)
{
username = id.Value;
}
}
return username;
}
这是GenerateJwt的代码。 (这些字段是标准字段吗?我看到其他字段已在其他代码中设置,例如在https://code-maze.com/authentication-aspnetcore-jwt-1/中。)
public static async Task<string> GenerateJwt(ClaimsIdentity identity, IJwtFactory jwtFactory,string userName, JwtIssuerOptions jwtOptions, JsonSerializerSettings serializerSettings)
{
var response = new
{
id = identity.Claims.Single(c => c.Type == "id").Value,
auth_token = await jwtFactory.GenerateEncodedToken(userName, identity),
expires_in = (int)jwtOptions.ValidFor.TotalSeconds
}; // see GenerateEncodedToken pasted below.
return JsonConvert.SerializeObject(response, serializerSettings);
}
public async Task<string> GenerateEncodedToken(string userName, ClaimsIdentity identity)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id)
};
// Create the JWT security token and encode it.
var jwt = new JwtSecurityToken(
issuer: _jwtOptions.Issuer,
audience: _jwtOptions.Audience,
claims: claims,
notBefore: _jwtOptions.NotBefore,
expires: _jwtOptions.Expiration,
signingCredentials: _jwtOptions.SigningCredentials);
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}
这些是ConfigureServices中的相关行。
// jwt wire up
// Get options from app settings
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
// Configure 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(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
configureOptions.RequireHttpsMetadata = false;
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
});
// add identity
var builder = services.AddIdentity<AppUser, AppRole>(o =>
{
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
})
.AddSignInManager<SignInManager<AppUser>>()
.AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();
我正在使用以下代码从Angular传递令牌。
private authHeader(): HttpHeaders {
let headers = new HttpHeaders();
if (isPlatformBrowser(this.platformId)) {
headers = headers.set('Content-Type', 'application/json');
let authToken = this.windowRefService.nativeWindow.localStorage.getItem('auth_token');
headers = headers.set('Authorization', authToken);
headers = headers.set('X-XSRF-TOKEN', this.getCookie('XSRF-TOKEN'));
}
return headers;
}
protected jsonAuthRequestOptions = { headers: this.authHeader() };
public loggedInAs(): Observable<string> {
return this.http.post<any>(this.baseUrl + "api/Account/GetUserId", { } , this.jsonAuthRequestOptions)
.map(data => {
if (data) {
return data;
}
return '';
})
.catch(this.handleError);
}
JWT身份验证是否自动设置HttpContext.User?还是我必须明确地做到这一点?
我的后续呼叫失败。 (用户没有声明,尽管HttpContext.User不为null。)我不知道问题是否在于依赖HttpContext.User,或者令牌生成/使用是否有问题。
答案 0 :(得分:-1)
有类似的问题。来自令牌的声明未传递给HttpContext.User.Identity.Claims。 就我而言,更改添加服务的顺序很有帮助。在添加身份验证之前添加身份。
在startup.cs中,我现在有:
services.AddIdentity(); services.AddAuthentication();