【问题标题】:Get Current User From ASP.NET CORE 2从 ASP.NET CORE 2 获取当前用户
【发布时间】:2018-10-03 00:53:08
【问题描述】:

我在我的应用程序中创建更新用户,然后 我在 Postman 和 Web App 中测试我的应用程序,但创建了不同的结果。 当我在邮递员中尝试此代码时,它可以工作,但网络应用程序不起作用 (ASP.NET CORE 2.0 中的代码,使用 Angular 5 的 Web 应用)

[HttpPut("{id}")]
    public async Task<IActionResult> UpdateUser(int id, [FromBody] UserForUpdateDto userDto) {
        if(!ModelState.IsValid)
            return BadRequest(ModelState);

        var currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);
        var userFromRepo = await _orgRepo.GetUser(id);
        if(userFromRepo == null) 
            return NotFound($"User not found with id: {id}");
        if (currentUserId != userFromRepo.Id)
            return Unauthorized();

        _mapper.Map<UserForUpdateDto, User>(userDto, userFromRepo);

        if (await _orgRepo.SaveAll())
            return NoContent();

        throw new Exception($"Updating user {id} failed on save");
    }

从 WebApp 会产生错误: “对象引用未设置为对象的实例。”

当我调试应用程序时,似乎是这条线导致了

var currentUserId = int.Parse(User.FindFirst(ClaimTypes.NameIdentifier).Value);

我检查它并产生空值。

知道用户设置在哪里吗?

我的登录控制器:

[HttpPost("login")]
    public async Task<IActionResult> Login([FromBody]UserForLoginDto userForLoginDto)
    {
        var userFromRepo = await _repo.Login(userForLoginDto.Username.ToLower(), userForLoginDto.Password);

        if (userFromRepo == null)
            return Unauthorized();

        // generate token
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes(_config.GetSection("AppSettings:Token").Value);
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new Claim[]
            {
                new Claim(ClaimTypes.NameIdentifier, userFromRepo.Id.ToString()),
                new Claim(ClaimTypes.Name, userFromRepo.Username),
                new Claim(ClaimTypes.Role, "RegisteredUsers")
            }),
            Expires = DateTime.Now.AddDays(3),
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
                SecurityAlgorithms.HmacSha512Signature)
        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        var tokenString = tokenHandler.WriteToken(token);

        var user = _mapper.Map<UserForDetailDto>(userFromRepo);
        return Ok(new { tokenString, user });

    }

【问题讨论】:

  • “当我在邮递员中尝试此代码时,它可以工作,但网络应用程序不工作” – 然后准确检查是什么使网络应用程序中的请求与您的请求不同在邮递员中做过。
  • 如果您的 API 在 Authorization 标头中使用 JWT 令牌,则用户 ID 将在 JwtClaimTypes.Subject 声明(子)中。

标签: c# asp.net-core oauth .net-core asp.net-core-2.0


【解决方案1】:

如果 api 方法包含 [Authorize],则授权标头与请求一起发送。如果没有发送标头,则说明您没有用户。

[HttpPut("{id}")]
[Authorize(AuthenticationSchemes = "Bearer")]
public async Task<IActionResult> UpdateUser(int id, [FromBody] UserForUpdateDto userDto) 
   {    
       var sub = User.GetSubjectId();   // Subject Id is the user id
    }

【讨论】:

  • 虽然一般来说这可能是一个好主意(保护路由),但请注意,如果提供令牌,无论路由是否需要授权,身份验证中间件仍将对用户进行身份验证。
  • @poke 有链接吗?我从未见过在控制器级别或方法级别未指定的方法自动授权。我很想了解更多有关这方面的信息。
  • 您使用app.UseAuthentication() 添加的身份验证中间件将尝试对with the default authentication scheme 进行身份验证。因此,当 JwtBearer 是您的默认方案时,无论您的路由是否经过身份验证,都会解析用户。这也是普通 ASP.NET Core 标识(本质上只是 CookieAuth)能够在不需要授权路由的情况下显示当前登录用户的方式。
猜你喜欢
  • 2016-12-09
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-30
  • 1970-01-01
相关资源
最近更新 更多