从前端(角度)调用时,User.FindFirst(ClaimTypes.NameIdentifier)不检索任何内容 [英] User.FindFirst(ClaimTypes.NameIdentifier) doesn't retrieve anything when called from frontend (Angular)

查看:121
本文介绍了从前端(角度)调用时,User.FindFirst(ClaimTypes.NameIdentifier)不检索任何内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm facing a new problem - just like the title says. I'll managed to check where the problem happens but I can't resolve it. I'll start from the top.

在后端(ASP.NET 3.0)中,我的类 AuthController 具有登录方法,它的确如下所示:

In the backend (ASP.NET 3.0) I have a class AuthController with login method it does look like that:

        [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中.

Long story short it creates claims after the user was logged in - everything seems fine from the frontend site - the token is put in the LocalStorage on the browser after that.

现在有一种方法会引起麻烦:

Now there's a method that causing trouble:

        [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东西根本无法正常工作.

As you can see there's this method User.FindFirst(ClaimTypes.NameIdentifier) which should get the local token and find the user but it's not even starting or finding anything. The problem is rather weird because when I use the same method without Angular but using just only Postman and putting the exact same token just as in Angular - this very method with finding claim types to resolve if the user is a valid user is working perfectly. But when I'm trying to reach out this whole post method from the frontend the ClaimTypes thing isn't working at all.

我想念什么?前端方面的东西?但是前端的方法相当简单.来自前端的userId毫无问题地传递给post方法-它只在必须声明时才中断,但是正如我所说的-当同一件事通过邮递员时它就起作用了.可能是我没有在这些方法上使用[授权]的问题?但是,当我执行操作时,应该如何更改前端(或后端),以便可以从Angular一侧进行[Authorize]认证-到目前为止,我不确定应该怎么做.

What am I missing? Something from the frontend side? But the methods from the frontend are rather simple. The userId from frontend is passed without problems to the post method - it breaks just when it has to get claims but as I said - when the same thing goes through postman it works. Might it be the problem that I'm not using [Authorize] over these methods? But when I do how should I change the frontend (or backend) so it could go through the [Authorize] from the Angular side - so far I wasn't sure what should I do.

按照@Papa Kojo的要求-我添加了一些前端代码,这些代码在我想的母题上是无关紧要的:

As requested by @Papa Kojo - I am adding some frontend code which is relevent at the momemnt I suppose:

从前端登录方法-令牌已添加到localStorage.

Login method from frontend - token is added to the 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的一部分.

There's a little fragment of the code where post method is called, it's part of the 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方法中正确接收了它.

this.trackIdBody from above snippet is JSON with two values - it's being properly recived by the backend in the HttpPost CreateTicket method.

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

Maybe putting token into localStorage from the frontend side is not enough? But also these claims are beeing properly made in the login method from the backend side when the frontend calls it.

推荐答案

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

With some help I've managed to find the exact problem and the actual solution. It appears that this method on the backend: User.FindFirst(ClaimTypes.NameIdentifier).Value doesn't trigger itself when there's no header included in http method (post in that case). So at first I've been trying to add simply a header to the http.post - and it would work most likely (header was actually included in postman - so it worked) but there is an easier way to append header to every http method automatically.

我要做的就是在imports子句中的 app.module.ts 中添加以下小片段:

Everything I had to do is to add to the app.module.ts in the imports clause this little snippet:

JwtModule.forRoot({
         config: {
          tokenGetter
}

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

And on the top of the app.module.ts I had to tell what is tokenGetter - just like that:

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

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

It takes token from localStorage and this very same token is being added to localStorage on every login in the authController in the method from my question up here.

这篇关于从前端(角度)调用时,User.FindFirst(ClaimTypes.NameIdentifier)不检索任何内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆