[英]Developing Azure functions locally
我領導着一個龐大的 azure 函數開發團隊。 因此,Microsoft 引用的大多數使用 azure Web 界面的示例對我都不起作用。 我正在使用模擬器在本地開發 Azure 函數以節省一些成本。 我通過 Visual Studio 將所有功能發布到我的集成環境中。
我正在開發一堆需要 api 網關來處理使用 Azure AD B2C 的身份驗證工作流的 azure 函數。 現在,沒有可以在本地運行的 api 網關模擬器或 Azure AD B2C 模擬器。 我的身份驗證工作流程涉及攔截對 api 的請求,將它們重定向到 AD B2C 進行身份驗證,隨后將 auth-token 添加到 http 標頭,然后調用 http 觸發的 azure 函數。
現在,問題變成了,我如何測試身份驗證工作流程? 如何設置 api 網關以將我在 Visual Studio 中本地運行的函數注冊為雲中 api 網關的 api 端點?
如果您正在開發通過Easy Auth使用 Azure-AD 或 Azure B2C 的 SPA,這是另一種選擇,它將為您執行 JWT 令牌驗證,並讓您執行以下操作:
您的 SPA 甚至會在本地獲得令牌,因此請執行以下操作:
下面是一些從頭中提取 JWT 令牌的示例代碼(HttpRequest 被注入到每個函數中):
private JwtSecurityToken ReadJwtTokenFromHeader(HttpRequest req)
{
if (req.Headers.ContainsKey("Authorization"))
{
var authHeader = req.Headers["Authorization"];
var headerValue = AuthenticationHeaderValue.Parse(authHeader);
var handler = new JwtSecurityTokenHandler();
return handler.ReadJwtToken(headerValue.Parameter);
}
return null;
}
注意:這需要 System.IdentityModel.Tokens.Jwt NuGet 包才能使用 JwtSecurityTokenHandler。
以@David-Yates 的回答,我在本地運行時替換了 Principal
module Debug = begin
open System.IdentityModel.Tokens.Jwt
open System.Net.Http.Headers
open System.Security.Claims
let setPrincipalFromBearerToken (log : ILogger) (req : HttpRequest) =
log.LogInformation ("Reading Authorization header")
let success, authHeader = req.Headers.TryGetValue("Authorization")
if not success
then log.LogWarning ("Authorization header missing")
else
match Seq.tryExactlyOne authHeader with
| None -> log.LogWarning ("Authorization header has 0 or more than 1 value")
| Some headerValue ->
let headerValue = AuthenticationHeaderValue.Parse(headerValue);
log.LogInformation ("Authorization header succesfully parsed")
let handler = new JwtSecurityTokenHandler();
let token = handler.ReadJwtToken(headerValue.Parameter);
log.LogInformation ("JWT succesfully parsed")
let identity =
ClaimsIdentity(
req.HttpContext.User.Identity,
token.Claims)//,
//Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme),
//"oid", "roles")
let principal = ClaimsPrincipal(identity)
req.HttpContext.User <- principal
let userIdClaim =
principal.Claims
|> Seq.where (fun c -> c.Type = "oid") // TODO: Use const from MS package if possible
|> Seq.head
log.LogInformation ("Principal succesfully updated, user ID '{0}'", userIdClaim.Value)
end
let isLocal = String.IsNullOrEmpty(Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"))
if isLocal then Debug.setPrincipalFromBearerToken log req
我做了什么:
優點:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.