答案是这样的。我的意思是您可以使用现有的数据库和许多相同的库,但不能移植代码配置。 Functions 的默认身份验证是 1) 默认 API 令牌或 2) 在您链接的指南中包含在 App Services 中的 EasyAuth 提供程序之一。目前,您需要自行设置的任何其他解决方案。
假设您使用 JWT 选项,您需要关闭函数的所有内置身份验证。这包括将您的 HttpRequest 函数设置为 AuthorizationLevel.Anonymous。
在基本层面上,您需要创建两件事。颁发令牌的函数,以及用于检查令牌的 DI 服务或自定义输入绑定。
发行代币
Functions 2.x+ 运行时在 .NET Core 上,所以我要从 this blog post 借用一些描述使用 JWT 和 Web API 的代码。它使用System.IdentityModel.Tokens.Jwt 生成一个令牌,然后我们可以从函数返回。
public SecurityToken Authenticate(string username, string password)
{
//replace with your user validation
var user = _users.SingleOrDefault(x => x.Username == username && x.Password == password);
// return null if user not found
if (user == null)
return null;
// authentication successful so generate jwt token
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.Id.ToString())
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
return tokenHandler.CreateToken(tokenDescriptor);
}
验证令牌
有几个指南可用于在 Azure Functions 中验证 JWT。我喜欢 Ben Morris 的这个:https://www.ben-morris.com/custom-token-authentication-in-azure-functions-using-bindings/ (source code)。它描述了使用自定义输入绑定或 DI 进行身份验证。在两者之间,DI 是首选选项,除非有特定原因需要使用绑定。在这里,您需要使用 Microsoft.IdentityModel.JsonWebTokens 和 System.IdentityModel.Tokens.Jwt 库来完成大部分工作。
public class ExampleHttpFunction
{
private readonly IAccessTokenProvider _tokenProvider;
public ExampleHttpFunction(IAccessTokenProvider tokenProvider)
{
_tokenProvider = tokenProvider;
}
[FunctionName("ExampleHttpFunction")]
public IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "example")] HttpRequest req, ILogger log)
{
var result = _tokenProvider.ValidateToken(req);
if (result.Status == AccessTokenStatus.Valid)
{
log.LogInformation($"Request received for {result.Principal.Identity.Name}.");
return new OkResult();
}
else
{
return new UnauthorizedResult();
}
}
}