C# .NET核心MVC和Web API两种身份验证方案
我有一个MVC应用程序和一个公开的API端点。我使用Identity Core的默认值验证了我的MVC应用程序,我使用C# .NET核心MVC和Web API两种身份验证方案,c#,asp.net-mvc,authentication,.net-core,jwt,C#,Asp.net Mvc,Authentication,.net Core,Jwt,我有一个MVC应用程序和一个公开的API端点。我使用Identity Core的默认值验证了我的MVC应用程序,我使用User.FindFirstValue(ClaimTypes.NameIdentifier)查找某个用户是否登录,等等 对于我的API端点,我使用JWT身份验证,以下是JWT的配置代码: services.AddAuthentication(options => { options.DefaultAuthenticateScheme
User.FindFirstValue(ClaimTypes.NameIdentifier)
查找某个用户是否登录,等等
对于我的API端点,我使用JWT身份验证,以下是JWT的配置代码:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwt =>
{
var key = Encoding.ASCII.GetBytes(Configuration["Jwt:Secret"]);
jwt.SaveToken = true;
jwt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
RequireExpirationTime = false,
ValidateLifetime = true
};
});
以下是令牌请求的控制器:
[HttpPost]
[Route("token")]
public async Task<IActionResult> Token([FromBody] UserLoginRequest user)
{
if (ModelState.IsValid)
{
var existingUser = await _userManager.FindByEmailAsync(user.Email);
if (existingUser == null)
{
return BadRequest();
}
var isCorrect = await _userManager.CheckPasswordAsync(existingUser, user.Password);
if (isCorrect)
{
var jwtToken = _identityService.GenerateJwtToken(existingUser);
return Ok(new RegistrationResponse()
{
Result = true,
Token = jwtToken
});
}
else
{
return BadRequest();
}
}
return BadRequest();
}
但很明显,这个解决方案无法正常工作,因为一旦我启动我的MVC应用程序并尝试登录,我就会被重定向回索引,而我仍然是未经授权的。反之亦然,在API中,当我进行邮递员调用时,我得到令牌,当我尝试调用我的书签控制器来查询用户的书签时,我得到零,尽管该用户有书签
任何关于如何实现这一点的想法都将受到欢迎。在我的JWT令牌生成器中,我获得了我希望存储为声明的用户的详细信息,如用户名,可用于识别用户
public static class JwtTokenExtensions
{
/// <summary>
/// Generates a JWT Bearer token containing the users email
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public static string GenerateJwtToken(this Identity user)
{
// Set our token claims
Claim[] claims = {
// Unique ID for this token
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
new(JwtRegisteredClaimNames.Email, user.Email),
// The username using the Identity name so it fills out the HttpContext.User.Identity.Name value
new(ClaimsIdentity.DefaultNameClaimType, user.UserName),
// Add user Id so that UserManager.GetUserAsync can find the user based on Id
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
// Create the credentials used to generate the token
SigningCredentials credentials =
new SigningCredentials(SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"])),
SecurityAlgorithms.HmacSha256);
// Generate the Jwt Token that lasts for an hour before expiring
JwtSecurityToken token =
new JwtSecurityToken
(Configuration["Jwt:Issuer"],
Configuration["Jwt:Audience"],
claims:claims,
signingCredentials:credentials,
expires: DateTime.Now.AddHours(1));
// Return the generated token.
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
公共静态类JwtTokenExtensions
{
///
///生成包含用户电子邮件的JWT承载令牌
///
///
///
公共静态字符串GenerateJwtToken(此标识用户)
{
//设定我们的代币索赔
索赔[]索赔={
//此令牌的唯一ID
新建(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString(“N”)),
新的(JwtRegisteredClaimNames.Email,user.Email),
//使用标识名的用户名,以填充HttpContext.User.Identity.name值
新建(ClaimsIdentity.DefaultNameClaimType,user.UserName),
//添加用户Id,以便UserManager.GetUserAsync可以基于Id找到用户
新声明(ClaimTypes.NameIdentifier,user.Id)
};
//创建用于生成令牌的凭据
签名凭据凭据=
新的签名凭据(SymmetricSecurityKey(Encoding.UTF8.GetBytes(配置[“Jwt:SecretKey]”)),
安全算法(HmacSha256);
//生成在到期前持续一小时的Jwt令牌
JwtSecurityToken令牌=
新JwtSecurityToken
(配置[“Jwt:Issuer”],
配置[“Jwt:观众”],
索赔:索赔,
签署证书:证书,
expires:DateTime.Now.AddHours(1));
//返回生成的令牌。
返回新的JwtSecurityTokenHandler().WriteToken(令牌);
}
}
在具有JWT授权的api控制器中,我可以通过HttpContext获得用户
var user=await\u userManager.GetUserAsync(HttpContext.user)代码>在我的JWT令牌生成器中,我得到了我想存储为声明的用户的详细信息,例如用户名,它可以用来识别用户
public static class JwtTokenExtensions
{
/// <summary>
/// Generates a JWT Bearer token containing the users email
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
public static string GenerateJwtToken(this Identity user)
{
// Set our token claims
Claim[] claims = {
// Unique ID for this token
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
new(JwtRegisteredClaimNames.Email, user.Email),
// The username using the Identity name so it fills out the HttpContext.User.Identity.Name value
new(ClaimsIdentity.DefaultNameClaimType, user.UserName),
// Add user Id so that UserManager.GetUserAsync can find the user based on Id
new Claim(ClaimTypes.NameIdentifier, user.Id)
};
// Create the credentials used to generate the token
SigningCredentials credentials =
new SigningCredentials(SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:SecretKey"])),
SecurityAlgorithms.HmacSha256);
// Generate the Jwt Token that lasts for an hour before expiring
JwtSecurityToken token =
new JwtSecurityToken
(Configuration["Jwt:Issuer"],
Configuration["Jwt:Audience"],
claims:claims,
signingCredentials:credentials,
expires: DateTime.Now.AddHours(1));
// Return the generated token.
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
公共静态类JwtTokenExtensions
{
///
///生成包含用户电子邮件的JWT承载令牌
///
///
///
公共静态字符串GenerateJwtToken(此标识用户)
{
//设定我们的代币索赔
索赔[]索赔={
//此令牌的唯一ID
新建(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString(“N”)),
新的(JwtRegisteredClaimNames.Email,user.Email),
//使用标识名的用户名,以填充HttpContext.User.Identity.name值
新建(ClaimsIdentity.DefaultNameClaimType,user.UserName),
//添加用户Id,以便UserManager.GetUserAsync可以基于Id找到用户
新声明(ClaimTypes.NameIdentifier,user.Id)
};
//创建用于生成令牌的凭据
签名凭据凭据=
新的签名凭据(SymmetricSecurityKey(Encoding.UTF8.GetBytes(配置[“Jwt:SecretKey]”)),
安全算法(HmacSha256);
//生成在到期前持续一小时的Jwt令牌
JwtSecurityToken令牌=
新JwtSecurityToken
(配置[“Jwt:Issuer”],
配置[“Jwt:观众”],
索赔:索赔,
签署证书:证书,
expires:DateTime.Now.AddHours(1));
//返回生成的令牌。
返回新的JwtSecurityTokenHandler().WriteToken(令牌);
}
}
在具有JWT授权的api控制器中,我可以通过HttpContext获得用户
var user=await\u userManager.GetUserAsync(HttpContext.user)代码>在控制器中为您的令牌请求添加[AllowAnonymous],如下所示:
[AllowAnonymous]
[HttpPost]
[Route("token")]
public async Task<IActionResult> Token([FromBody] UserLoginRequest user)
{
// snip...
}
[AllowAnonymous]
[HttpPost]
[路由(“令牌”)]
公共异步任务令牌([FromBody]UserLoginRequest用户)
{
//剪断。。。
}
在令牌请求的控制器中,尝试添加[AllowAnonymous],如下所示:
[AllowAnonymous]
[HttpPost]
[Route("token")]
public async Task<IActionResult> Token([FromBody] UserLoginRequest user)
{
// snip...
}
[AllowAnonymous]
[HttpPost]
[路由(“令牌”)]
公共异步任务令牌([FromBody]UserLoginRequest用户)
{
//剪断。。。
}
在请求书签时,您是否随请求一起发送承载令牌?其次,您的mvc身份验证失败,因为您已将JWT身份验证指定为defualtauthentication方案。My bookmarks实体有一个UserId属性,我使用该属性从该特定用户检索所有书签。在MVC中,我可以轻松地使用(User.FindFirstValue(ClaimTypes.nameignifier))检索userId,但在我的API调用中,我得到的书签为零@Jeffery@Jeffery还有,我该怎么做才能使会话身份验证和JWT身份验证都成为默认设置对于我所做的所有JWT身份验证,我已经编写了自己的JWT令牌生成器,其中我指定了声明类型,如NameIdentifier和其他我可能特别需要的声明。我发布了我的代码作为答案,并提供了一些帮助。请查看它是否解决了您向书签发出请求的问题,您是否随请求一起发送承载令牌?第二,你的mvc aut