【问题标题】:User.FindFirst(ClaimTypes.NameIdentifier) doesn't retrieve anything when called from frontend (Angular)User.FindFirst(ClaimTypes.NameIdentifier) 从前端(Angular)调用时不检索任何内容
【发布时间】:2020-03-30 19:45:10
【问题描述】:

我遇到了一个新问题 - 就像标题所说的那样。我会设法检查问题发生在哪里,但我无法解决它。我会从头开始。

在后端 (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 方法 - 它只是在它必须获得声明时中断,但正如我所说 - 当同样的事情通过邮递员时它工作。可能是我没有在这些方法上使用 [Authorize] 的问题吗?但是当我这样做时,我应该如何更改前端(或后端),以便它可以通过 Angular 端的 [Authorize] - 到目前为止,我不确定我应该做什么。

编辑:应@Papa Kojo 的要求 - 我正在添加一些前端代码,我想这些代码是相关的:

从前端登录方法 - 令牌被添加到本地存储。

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);
            });

上面 sn-p 中的this.trackIdBody 是具有两个值的 JSON - 它正在被后端在 HttpPost CreateTicket 方法中正确接收。

也许从前端将令牌放入 localStorage 是不够的?但是,当前端调用它时,这些声明也在后端的登录方法中正确地提出。

【问题讨论】:

  • 您应该检查您的网络以查看是否有任何请求/错误。此外,一些前端代码将有助于解决这个问题
  • 我已经编辑了代码。
  • stackoverflow.com/questions/62853455/… 请看这里,需要帮助。

标签: c# asp.net angular typescript


【解决方案1】:

在一些帮助下,我设法找到了确切的问题和实际的解决方案。后端的这种方法:User.FindFirst(ClaimTypes.NameIdentifier).Value 似乎在 http 方法中没有包含标头时不会触发自身(在这种情况下是 post)。因此,起初我一直试图在 http.post 中简单地添加一个标头 - 它很可能会起作用(标头实际上包含在邮递员中 - 所以它起作用了)但是有一种更简单的方法可以将标头附加到每个 http 方法自动。

我所要做的就是将这个小sn-p添加到导入子句中的app.module.ts

JwtModule.forRoot({
         config: {
          tokenGetter
}

在 app.module.ts 的顶部,我必须告诉什么是 tokenGetter - 就像这样:

export function tokenGetter() {
   return localStorage.getItem('token');
}

它从 localStorage 获取令牌,并且在我的问题中的方法中,每次登录 authController 时,都会将相同的令牌添加到 localStorage。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多