簡體   English   中英

在本地開發 Azure 函數

[英]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 甚至會在本地獲得令牌,因此請執行以下操作:

  1. ClaimPrincipal注入您的函數
  2. 檢查用戶是否通過身份驗證(例如,principal.Identity.IsAuthenticated),如果沒有,則返回 UnauthorizedResult。
  3. 檢查發行人索賠。 如果委托人有一個,它通過了 Express Auth.,你的 JWT 令牌由它驗證,你可以立即從中獲得你的聲明。
  4. 如果沒有發行者,則是本地開發,您可以轉向標頭並自己提取 JWT 令牌並獲得您的聲明。 您也可以將其用於有條件的構建,以便您雙重確定它是本地開發。

下面是一些從頭中提取 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

我做了什么:

  1. 添加了一個“授權”API,用於處理針對外國當局的通用授權。 這個 API 返回我自己的 JWT 和我自己的自定義聲明,持續一段時間。
  2. 更改了我所有其他 API 以使用我的自定義 JWT。

優點:

  • 超級容易在本地測試。 我只是將 #if DEBUG 部分添加到授權 API 以跳過正常授權並為我提供設計的 JWT。
  • 我可以在聲明中放入任何我想要的內容,因此我將其用作緩存以減少外部授權調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM