从前端(角度)调用时,User.FindFirst(ClaimTypes.NameIdentifier)不检索任何内容

时间:2019-12-05 20:07:22

标签: c# asp.net angular typescript

我正面临一个新问题-就像标题中所说的那样。我将设法检查问题出在哪里,但无法解决。我将从顶部开始。

在后端(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还不够?但是,当前端调用登录方法时,这些声明也可以在后端从登录方正确地提出来。

1 个答案:

答案 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中。