我正面临一个新问题-就像标题中所说的那样。我将设法检查问题出在哪里,但无法解决。我将从顶部开始。
在后端(ASP.NET 3.0)中,我有一个使用登录方法的类AuthController
,它看起来像这样:
[HttpPost("login")]
public async Task<IActionResult> Login(LoginedUserDTO loginedUser)
{
var userToLogin = await _authService.Login(loginedUser.Username.ToLower(), loginedUser.Password);
if (userToLogin is null)
return Unauthorized();
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, userToLogin.Id.ToString()),
new Claim(ClaimTypes.Name, userToLogin.Username)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("AppSettings:Token").Value));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims),
Expires = DateTime.Now.AddDays(1),
SigningCredentials = creds
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(tokenDescriptor);
return Ok(new
{
token = tokenHandler.WriteToken(token)
});
}
长话短说,它会在用户登录后创建声明-前端站点上的一切似乎都很好-令牌随后放置在浏览器的LocalStorage中。
现在有一种方法会引起麻烦:
[HttpPost]
public async Task<IActionResult> CreateTicket(TicketBody ticketBody)
{
//var userId = Guid.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
if (ticketBody.CurrentUserId != Guid.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value))
return Unauthorized();
var ticket = await _ticketService.CreateTicket(ticketBody.Id, ticketBody.CurrentUserId);
return new JsonResult(ticket);
}
如您所见,有一种方法User.FindFirst(ClaimTypes.NameIdentifier)
应该获取本地令牌并找到用户,但它甚至没有启动或发现任何东西。问题相当奇怪,因为当我使用相同的方法但不使用Angular时,仅使用Postman并像Angular中那样放置完全相同的标记时,这种方法可以找到声明类型以解决用户是否为有效用户,因此效果很好。但是,当我试图从前端接触整个post方法时,ClaimTypes东西根本无法工作。
我想念什么?前端方面的东西?但是前端的方法非常简单。前端的userId毫无问题地传递给post方法-它只在必须声明时才中断,但是正如我所说的-当同一件事通过邮递员时它就起作用了。可能是我没有在这些方法上使用[授权]的问题?但是,当我应该如何更改前端(或后端)时,才能从Angular一侧进行[Authorize]的授权-到目前为止,我不确定应该怎么做。
编辑:按照@Papa Kojo的要求-我添加了一些前端代码,这些代码在我想为的母板上是相对的:
从前端登录方法-令牌已添加到localStorage。
login(model: any) {
return this.http.post(this.baseUrl + 'login', model)
.pipe(
map((response: any) => {
const user = response;
if (user) {
localStorage.setItem('token', user.token);
this.decodedToken = this.jwtHelper.decodeToken(user.token);
console.log(this.decodedToken);
}
})
);
}
有一小段代码,其中调用post方法,这是paypal API的一部分。
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.paidFor = true;
console.log(order);
this.trackIdBody.id = this.trackObj.trackId;
this.trackIdBody.currentUserId = this.authService.decodedToken.nameid;
console.log(this.trackIdBody);
this.http.post('http://localhost:5000/tickets/', this.trackIdBody).subscribe(response => {
console.log(response);
}, error => {
console.log(error);
});
上面片段中的 this.trackIdBody
是具有两个值的JSON-后端已在HttpPost CreateTicket方法中正确接收了它。
也许从前端将令牌放入localStorage还不够?但是,当前端调用登录方法时,这些声明也可以在后端从登录方正确地提出来。
答案 0 :(得分:0)
在一些帮助下,我设法找到了确切的问题和实际的解决方案。似乎在后端方法:User.FindFirst(ClaimTypes.NameIdentifier).Value
不会在http方法中不包含标头时触发自身(在这种情况下为post)。因此,起初我一直在尝试向http.post添加一个标头-它很可能会工作(标头实际上已包含在邮递员中-因此它可以工作),但是有一种更简单的方法将标头附加到每个http方法自动。
我要做的就是将这个小片段添加到imports子句中的app.module.ts
:
JwtModule.forRoot({
config: {
tokenGetter
}
在app.module.ts的顶部,我不得不告诉什么是tokenGetter-就像那样:
export function tokenGetter() {
return localStorage.getItem('token');
}
它从localStorage获取令牌,并且每次在我的问题中方法authController中的每次登录时,都会将此令牌添加到localStorage中。