繁体   English   中英

如何使用 JWT 令牌检索 .NET Core API 中的当前用户数据?

[英]How use a JWT token to retrieve current user data in .NET Core API?

我已经实现了 JWT 令牌,以了解当前用户在 MVC controller 正在使用的 API 应用程序中是谁。 我正在构建类似论坛应用程序的东西。 用户必须登录才能发帖,所以我基本上是在尝试使用 JWT 令牌来存储当前用户的 email。 当用户单击“创建帖子”时,操作应该获取令牌及其值,问题是我不知道如何使用令牌来保护控制器或从当前用户检索数据,我已经复制并粘贴了jwt.io 中的 token 以检查数据是否正确存储在 token 中以及值(用户的电子邮件)是否正确存储。

带有“登录”操作的 API controller:

    public async Task<IActionResult> login([FromBody] Usuario model)
    {
                //check if user exists and the password is correct

                //generates the token
                    var SecretKey = config.GetValue<string>("SecretKey");
                    var key = Encoding.ASCII.GetBytes(SecretKey);

                    var claims = new ClaimsIdentity(new Claim[] 
                    {
                        new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
                        new Claim(ClaimTypes.Name, user.Mail)
                    });
                    claims.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Mail));

                    var tokenDesc = new SecurityTokenDescriptor
                    {
                        Subject = claims,
                        Expires = DateTime.UtcNow.AddMinutes(20),
                        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
                    };

                    var tokenHandler = new JwtSecurityTokenHandler();
                    var createdToken = tokenHandler.CreateToken(tokenDesc);

                    string bearer_token = tokenHandler.WriteToken(createdToken);

                    using(var client = new HttpClient())
                    {
                        client.DefaultRequestHeaders.Add("Authorization", "Bearer" + bearer_token);
                    }

                    return Ok(bearer_token);
                }
    }

使用 API 的 MVC controller :

    public async Task<IActionResult> login(Usuario model)
    {
            HttpClient hc = new HttpClient();
            hc.BaseAddress = new Uri("https://localhost:44325/api/Usuarios/");

            var login = await hc.PostAsJsonAsync<Usuario>("login", model);

            //check the response

            var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
            identity.AddClaim(new Claim(ClaimTypes.Name, model.Email));

            var principal = new ClaimsPrincipal(identity);

            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);

            HttpContext.Session.SetString("JWToken", login.ToString());

            hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", login.ToString());

            return RedirectToAction("IndexForumList", "ForumControllerMVC");
        }
    }

这是“创建帖子”的 API 方法以及应该使用令牌的位置,这里的userId是 null:

    public async Task<IActionResult> createPost([FromForm]ForumModel model)
    {
        string userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        
        //retrieves the current user email, validates and save the content to database
        
    }

这是“创建帖子”的 MVC 方法:

public async Task<IActionResult> createPost(ForumModel model)
    {
        HttpClient hc = new HttpClient();
        hc.BaseAddress = new Uri("https://localhost:44325/api/Usuarios/");

        //var userPost = hc.PostAsJsonAsync<ForumModel>("Usuarios/createPost", model);

        var userPost = await hc.PostAsync("createPost", formContent);

        if(userPost.IsSuccessStatusCode == true)
        {
            return RedirectToAction("IndexForumList", "ForoControllerMVC");
        }
    }

由于我对 JWT 缺乏了解,我一直为此受苦,感谢您的帮助。

更新

startup.cs

public void ConfigureServices(IServiceCollection services)
    {
        var key = Encoding.ASCII.GetBytes(Configuration.GetValue<string>("SecretKey"));

        services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddJwtBearer(x =>
        {
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
        });
        services.AddSession(
            options =>
            {
                options.IdleTimeout = TimeSpan.FromMinutes(10);
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
            });
    }

如果我正确理解您的问题,为了保护您的 API,您可以使用 [Authorize] 属性对其进行装饰。 例如 -

    [Authorize]
    [HttpGet]
    public IActionResult GetAll()
    {
        var users = _userService.GetAll();
        return Ok(users);
    }

并且要验证您的令牌,因为您将 .netcore 用于 api,您必须创建一个中间件,在您的请求到达 API 端点之前验证令牌。 您可以按照教程了解有关如何将 JWT 与 ASP.NET 内核一起使用的更多详细信息。

要在您的情况下获取用户 ID,您必须先验证令牌,然后提取 UserId。 尝试将 createPost api 中的代码更改为此 -

public async Task<IActionResult> createPost([FromForm]ForumModel model)
{
    var tokenHandler = new JwtSecurityTokenHandler();
    var SecretKey = config.GetValue<string>("SecretKey");
    var key = Encoding.ASCII.GetBytes(SecretKey);
    var token = HttpContext.Request.Headers["Authorization"];       
    
    tokenHandler.ValidateToken(token, new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false,
        ValidateAudience = false,
        ClockSkew = TimeSpan.Zero
            }, out SecurityToken validatedToken);

        var jwtToken = (JwtSecurityToken)validatedToken;
        var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "NameIdentifier").Value);
}

尽管这应该在中间件中处理,然后您可以将经过身份验证的用户附加到当前的 HttpContext.Items 集合,以使其在当前请求的 scope 中可访问。 所有这些都在教程中详细解释。 希望有帮助。!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM