[英]How to use JWT token to authorize user from react to asp net core web api. When to use autorization header bearer token?
[英]How use a JWT token to retrieve current user data in .NET Core API?
我已经实现了 JWT 令牌,以了解当前用户在 MVC controller 正在使用的 API 应用程序中是谁。 我正在构建类似论坛应用程序的东西。 用户必须登录才能发帖,所以我基本上是在尝试使用 JWT 令牌来存储当前用户的 email。 当用户单击“创建帖子”时,操作应该获取令牌及其值,问题是我不知道如何使用令牌来保护控制器或从当前用户检索数据,我已经复制并粘贴了jwt.io 中的 token 以检查数据是否正确存储在 token 中以及值(用户的电子邮件)是否正确存储。
带有“登录”操作的 API controller:
public async Task<IActionResult> login([FromBody] Usuario model)
{
//check if user exists and the password is correct
//generates the token
var SecretKey = config.GetValue<string>("SecretKey");
var key = Encoding.ASCII.GetBytes(SecretKey);
var claims = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Mail)
});
claims.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Mail));
var tokenDesc = new SecurityTokenDescriptor
{
Subject = claims,
Expires = DateTime.UtcNow.AddMinutes(20),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var createdToken = tokenHandler.CreateToken(tokenDesc);
string bearer_token = tokenHandler.WriteToken(createdToken);
using(var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer" + bearer_token);
}
return Ok(bearer_token);
}
}
使用 API 的 MVC controller :
public async Task<IActionResult> login(Usuario model)
{
HttpClient hc = new HttpClient();
hc.BaseAddress = new Uri("https://localhost:44325/api/Usuarios/");
var login = await hc.PostAsJsonAsync<Usuario>("login", model);
//check the response
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, model.Email));
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
HttpContext.Session.SetString("JWToken", login.ToString());
hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", login.ToString());
return RedirectToAction("IndexForumList", "ForumControllerMVC");
}
}
这是“创建帖子”的 API 方法以及应该使用令牌的位置,这里的userId
是 null:
public async Task<IActionResult> createPost([FromForm]ForumModel model)
{
string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
//retrieves the current user email, validates and save the content to database
}
这是“创建帖子”的 MVC 方法:
public async Task<IActionResult> createPost(ForumModel model)
{
HttpClient hc = new HttpClient();
hc.BaseAddress = new Uri("https://localhost:44325/api/Usuarios/");
//var userPost = hc.PostAsJsonAsync<ForumModel>("Usuarios/createPost", model);
var userPost = await hc.PostAsync("createPost", formContent);
if(userPost.IsSuccessStatusCode == true)
{
return RedirectToAction("IndexForumList", "ForoControllerMVC");
}
}
由于我对 JWT 缺乏了解,我一直为此受苦,感谢您的帮助。
更新
startup.cs
public void ConfigureServices(IServiceCollection services)
{
var key = Encoding.ASCII.GetBytes(Configuration.GetValue<string>("SecretKey"));
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddSession(
options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(10);
options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
}
如果我正确理解您的问题,为了保护您的 API,您可以使用 [Authorize] 属性对其进行装饰。 例如 -
[Authorize]
[HttpGet]
public IActionResult GetAll()
{
var users = _userService.GetAll();
return Ok(users);
}
并且要验证您的令牌,因为您将 .netcore 用于 api,您必须创建一个中间件,在您的请求到达 API 端点之前验证令牌。 您可以按照本教程了解有关如何将 JWT 与 ASP.NET 内核一起使用的更多详细信息。
要在您的情况下获取用户 ID,您必须先验证令牌,然后提取 UserId。 尝试将 createPost api 中的代码更改为此 -
public async Task<IActionResult> createPost([FromForm]ForumModel model)
{
var tokenHandler = new JwtSecurityTokenHandler();
var SecretKey = config.GetValue<string>("SecretKey");
var key = Encoding.ASCII.GetBytes(SecretKey);
var token = HttpContext.Request.Headers["Authorization"];
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
var jwtToken = (JwtSecurityToken)validatedToken;
var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "NameIdentifier").Value);
}
尽管这应该在中间件中处理,然后您可以将经过身份验证的用户附加到当前的 HttpContext.Items 集合,以使其在当前请求的 scope 中可访问。 所有这些都在教程中详细解释。 希望有帮助。!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.