如何在BLOB存储中从Azure函数连接到托管站点?

发布于 2025-02-09 17:31:20 字数 2959 浏览 1 评论 0 原文

我有一个存储HTML文件的BLOB存储容器。有了公共访问级别,我可以看到HTML,但是想法是将其设置为私人。我想让用户进行身份验证并访问HTML文件。

为此,我创建了一个代码中最相关的部分的Azure函数:

    #r "Newtonsoft.Json"

using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log, string version, string route)
{
    var blobUri = "https://mybloburi.blob.core.windows.net/" + route;

    var expiresOn = req.Headers.FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-expires-on", 
    StringComparison.OrdinalIgnoreCase)).Value.FirstOrDefault();

    log.LogInformation($"expires On : {expiresOn}");
    log.LogInformation($"blob uri : {blobUri}");
    
    var isTokenExpired = (DateTime.Parse(expiresOn, styles: DateTimeStyles.AdjustToUniversal) - DateTime.UtcNow).TotalMinutes < 5;

    var bearerToken = isTokenExpired? await RefreshToken(req, log) : req.Headers.
    FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-access-token", StringComparison.OrdinalIgnoreCase)).
    Value.FirstOrDefault();

    log.LogInformation($"bearer token: {bearerToken}");

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
        client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
        client.DefaultRequestHeaders.Add("Accept", "*/*");
        client.DefaultRequestHeaders.Add("x-ms-version", "2017-11-09");
        
        var response = await client.GetAsync(blobUri);

        log.LogInformation($"response: {response}");

        var contentType = response.Content.Headers.FirstOrDefault(p => p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase));
        var byteArray = await response.Content.ReadAsByteArrayAsync();
        
        const string defaultContentType = "application/octet-stream";
        
        return new FileContentResult(byteArray, contentType.Value.Any() ? contentType.Value.First() : defaultContentType);
    }
}

在Azure函数的集成部分中,我添加了此配置:

“在此处输入图像描述”

然后我创建了一个应用程序注册。在Azure函数的授权选项下,启用了应用程序服务身份验证。在那里,我添加了一个新的身份提供商作为Microsoft,作为提供商,我添加了创建的应用程序注册。我创建了一个具有访问BLOB存储容器的角色组,并将其应用程序ID设置为“允许的令牌受众”。

测试时,我可以对AAD进行身份验证。但是,HTTP客户端获得函数失败,

<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. 

我不知道其他配置要做什么,而且我似乎在文档中找不到任何可以帮助的东西

I have a blob storage container that stores HTML files. With the public access level, I can see the HTML, but the idea is to set it to private. I want to have users authenticate and access the HTML file.

For that I created an Azure Function with the most relevant part of the code being:

    #r "Newtonsoft.Json"

using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log, string version, string route)
{
    var blobUri = "https://mybloburi.blob.core.windows.net/" + route;

    var expiresOn = req.Headers.FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-expires-on", 
    StringComparison.OrdinalIgnoreCase)).Value.FirstOrDefault();

    log.LogInformation(
quot;expires On : {expiresOn}");
    log.LogInformation(
quot;blob uri : {blobUri}");
    
    var isTokenExpired = (DateTime.Parse(expiresOn, styles: DateTimeStyles.AdjustToUniversal) - DateTime.UtcNow).TotalMinutes < 5;

    var bearerToken = isTokenExpired? await RefreshToken(req, log) : req.Headers.
    FirstOrDefault(p => p.Key.Equals("x-ms-token-aad-access-token", StringComparison.OrdinalIgnoreCase)).
    Value.FirstOrDefault();

    log.LogInformation(
quot;bearer token: {bearerToken}");

    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
        client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
        client.DefaultRequestHeaders.Add("Accept", "*/*");
        client.DefaultRequestHeaders.Add("x-ms-version", "2017-11-09");
        
        var response = await client.GetAsync(blobUri);

        log.LogInformation(
quot;response: {response}");

        var contentType = response.Content.Headers.FirstOrDefault(p => p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase));
        var byteArray = await response.Content.ReadAsByteArrayAsync();
        
        const string defaultContentType = "application/octet-stream";
        
        return new FileContentResult(byteArray, contentType.Value.Any() ? contentType.Value.First() : defaultContentType);
    }
}

In the Integration section of the Azure Function, I added this config:

enter image description here

Then I created an App Registration. Under the Authorization option of the Azure Function, I enabled the App Service Authentication. In there I added a new Identity Provider as Microsoft and as a provider I added the created App Registration. I created a Role Group with access to the Blob Storage Container and set its App Id to the "Allowed token audiences".

When I test, I am able to authenticate to the AAD. However, the HTTP Client get function fails with

<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature. 

I don't know what other configuration to do and I cant seem to find anything in the documentation that could help

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

⊕婉儿 2025-02-16 17:31:20

@thomas建议。是的,我们确实有一个静态网站,我们有简化的身份验证。
默认情况下,您将对一系列预配置的提供商进行访问,或者您甚至可以注册自定义提供商。

”在此处输入映像说明“

为了配置静态Web应用程序,用于将其用作API函数以进行角色分配,您需要添加 RoleSsource 属性属性属性到 auth ,这是API函数的路径。

{
  "auth": {
    "rolesSource": "/api/GetRoles",
    "identityProviders": {
      // ...
    }
  }
}

有关更多信息,您可以检查此 document 。。

As suggested by @Thomas. Yes, we do have a static website where we have a streamlined authentication.
For which you will be having a by default access to a series of pre-configured providers, or you can even register a custom provider.

enter image description here

To configure static web apps for using it as an API function for role assignment you need to add rolesSource property to auth and that is the path of API function.

{
  "auth": {
    "rolesSource": "/api/GetRoles",
    "identityProviders": {
      // ...
    }
  }
}

For more information you can check this document.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文