实现 JWT 身份验证 Azure Function 3.x - 使用 JWT 令牌获取当前用户的声明

Posted

技术标签:

【中文标题】实现 JWT 身份验证 Azure Function 3.x - 使用 JWT 令牌获取当前用户的声明【英文标题】:Implementing JWT authentication Azure Function 3.x - Get Current User's Claims Using JWT token 【发布时间】:2020-11-29 23:01:10 【问题描述】:

我正在使用 Azure 函数将新开发堆栈上的 dontcore Web API 转换为无服务器。

我认为我的应用程序应该使用 Identity 来存储用户凭据和其他详细信息。他应该通过身份数据库进行身份验证并使用 JWT 令牌生成。

我正在尝试获取一些示例,这些示例可能有助于了解如何在 Azure 函数中实现 JWT。

JWT 令牌生成过程

     public UserResponce AuthendicateUser(string username, string password)
        
            bool valid_user= ValidateUser(username,password);
            if (vlaid_user)
            

                // authentication successful so generate jwt token
                var tokenHandler = new JwtSecurityTokenHandler();
                var key = Encoding.ASCII.GetBytes(_jwtIssuerOptions.Value.JwtKey);
                var tokenDescriptor = new SecurityTokenDescriptor
                
                    Subject = new ClaimsIdentity(new Claim[]
                    
                    new Claim(ClaimTypes.Name, "1"),
                    new Claim(ClaimTypes.GivenName, username),
                    new Claim(ClaimTypes.Role, UserRoleEnum.superadmin.ToString()),
                    new Claim("hospitalid", "1")
                    ),
                    Expires = DateTime.UtcNow.AddMinutes(_jwtIssuerOptions.Value.JwtExpireMinutes),
                    IssuedAt = DateTime.UtcNow,
                    NotBefore = DateTime.UtcNow,
                    Audience = _jwtIssuerOptions.Value.JwtAuidence,
                    Issuer = _jwtIssuerOptions.Value.JwtIssuer,
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
                ;
                var token = tokenHandler.CreateToken(tokenDescriptor);
                string newJwttoken = tokenHandler.WriteToken(token);

                return new UserResponce
                

                    //HospitalId = user.HospitalId.Value,
                    Token = newJwttoken,
                    UserId = 1,
                    UserName = username,
                    Expires = DateTime.UtcNow.AddMinutes(_jwtIssuerOptions.Value.JwtExpireMinutes),
                ;
            
            else
            
                return null;
            

        

使用像 Bellow 代码这样的函数,其中用户、身份值获取 Nulls

        var user = req.HttpContext.User;
        var identity = claimsPrincipal.Identity;

功能代码

        [FunctionName("Get_User")]
        public async Task<IActionResult> GetUser(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Globals.UserRoute+"/getuser")] HttpRequest req, ILogger log, ClaimsPrincipal claimsPrincipal)
        

            log.LogInformation("C# HTTP trigger function processed a request started");
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            AuthendicateModel data = JsonConvert.DeserializeObject<AuthendicateModel>(requestBody);
            var user = req.HttpContext.User;
            var identity = claimsPrincipal.Identity;
            var details = _userService.Username();
            log.LogInformation("C# HTTP trigger function processed a request.");
            return new OkObjectResult(new ApiResponse(HttpStatusCode.OK, details, ResponseMessageEnum.Success.ToString()));

        

【问题讨论】:

您还有其他顾虑吗?如果您没有其他顾虑,您能否接受它作为答案(meta.stackexchange.com/questions/5234/…)? 【参考方案1】:

无需验证。就用这个包DarkLoop.Azure.Functions.Authorize

在你的启动类中初始化认证:

builder.Services
    .AddFunctionsAuthentication();
    .AddJwtBearer(options => 
     
        //your JWT configuration here just like in ASPNET Core
     );

builder.Services.AddFunctionsAuthorization();

那么您需要做的就是用FunctionAuthorizeAttribute 装饰您的函数或函数类,您就可以拥有与 ASPNET WebAPI 中相同的精细控制:

    [FunctionAuthorize]
    [FunctionName("Get_User")]
    public async Task<IActionResult> GetUser(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = Globals.UserRoute+"/getuser")] HttpRequest req, ILogger log)
    

        log.LogInformation("C# HTTP trigger function processed a request started");
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        AuthendicateModel data = JsonConvert.DeserializeObject<AuthendicateModel>(requestBody);
        var user = req.HttpContext.User;
        var identity = user.Identity;
        var claims = user.Claims;
        var details = _userService.Username();
        log.LogInformation("C# HTTP trigger function processed a request.");
        return new OkObjectResult(new ApiResponse(HttpStatusCode.OK, details, ResponseMessageEnum.Success.ToString()));

    

【讨论】:

【参考方案2】:

如果你想在 Azure 函数中验证你的 jwt 令牌,你可以使用 sdk System.IdentityModel.Tokens.Jwt 来实现它。更多详情请参考here

例如

var authorizationHeader = req.Headers?["Authorization"];
            string[] parts = authorizationHeader?.ToString().Split(null) ?? new string[0];
            string token = string.Empty;
            if (parts.Length == 2 && parts[0].Equals("Bearer"))
                token = parts[1];
            var tokenHandler = new JwtSecurityTokenHandler();
            
            var key = Encoding.ASCII.GetBytes("your jwt key vaule");
            // Validate Token and read claims

            // defile the validation Parameters according to your need
            var validationParameters = new TokenValidationParameters()
            
                RequireExpirationTime = true,
                IssuerSigningKey= new  SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            ;

            SecurityToken securityToken;
            try 
                // Validate Token
                ClaimsPrincipal principal = tokenHandler.ValidateToken(token, validationParameters, out securityToken);
                var name = principal.Identity.Name;
                log.LogInformation($"the name is name");
                // read claims
                foreach (var claim in principal.Claims) 
                    // process the claim
                
             catch (Exception ex) 
                
                // process exception
                 
            
            

此外,如果您在运行该函数时遇到关于Could not load file or assembly System.IdentityModel.Tokens.Jwt 的问题,请在您的.csproj 文件中添加以下设置。更多详情请参考here和here

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <AzureFunctionsVersion>v3</AzureFunctionsVersion>
     <_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
  </PropertyGroup>
  .....
</Project>

【讨论】:

以上是关于实现 JWT 身份验证 Azure Function 3.x - 使用 JWT 令牌获取当前用户的声明的主要内容,如果未能解决你的问题,请参考以下文章

Asp Core:Azure Ad Auth + 自定义 JWT + 自定义身份存储

构建 VSTS 扩展 azure webapp 身份验证 JWT 令牌验证失败

使用 Azure API 管理从身份提供者缓存 JWKS 以验证 JWT

api 的 Azure Apim 身份验证

启用Azure移动服务身份验证会导致POST请求中的“资源不支持GET”

使用带有 C# 的公钥验证 JWT