如何使用应用服务对 Azure Functions 应用进行身份验证/授权?

Posted

技术标签:

【中文标题】如何使用应用服务对 Azure Functions 应用进行身份验证/授权?【英文标题】:How can I authenticate/authorize an Azure functions app with an app service? 【发布时间】:2017-11-07 07:54:25 【问题描述】:

我有一个 Azure 应用服务 以及一个 functions 应用(我目前正在学习 Azure,如果有其他方法可以实现我想要的,我愿意建议)。应用服务包含一个简单的表,我想与一个应用同步(它已经在工作),并且我想实现一个函数,其中包含一个填充简单表的 blob 存储输入绑定或计时器触发器。

由于似乎没有简单表的输出绑定,我遵循this answer 并使用MobileServiceClient 实现了访问。

MobileServiceClient client = new MobileServiceClient("https://my-app.azurewebsites.net");
var table = client.GetTable<MyTableClass>();
await table.InsertAsync(myObject);

只要表是公开可写的,它就可以工作,但是当它可以匿名读取时它当然不起作用,但只有经过身份验证的用户才可写。为了验证我的功能,我创建了一个 Azure Active Directory 并为该 AD 中的应用程序创建了一个 API 密钥,然后我尝试通过

验证MobileServiceClient
await client.LoginAsync(MobileServiceAuthenticationProvider.WindowsAzureActiveDirectory, 
                        new JObject "access_token", "<my API key>");

但这并没有成功。我总是收到错误

请求无法完成。 (未经授权)。

显然这行不通(以这种方式使用 API 密钥实际上只是在黑暗中拍摄),但我不确定如何从我的函数应用程序中完成身份验证。我知道当我在应用程序中使用MobileServiceClient 时,我可以将用户重定向到登录,但这(显然)不适用于函数。

如何使用现有应用服务验证我的函数,以便写入不可匿名写入的表?

【问题讨论】:

【参考方案1】:

应用服务无法通过 API 密钥进行简单访问,但访问应用服务需要通过 Active Directory 进行完整身份验证。为此,可以使用 ADAL (Active Directory Access Library)。

AuthenticationContext

ADAL 定义了AuthenticationContext 类,它是使用 Active Directory 进行身份验证的助手。先新建一个AuthenticationContext

var authenticationContext = new AuthenticationContext("https://login.microsoftonline.com/<Directory ID>");

您可以通过访问 Azure 门户中的 Azure Active Directory 找到 Directory ID,然后从 Azure Active Directory 菜单打开 属性。在属性菜单中有一个包含Directory ID的文本框。

使用 Azure Active Directory 进行身份验证

您现在可以使用身份验证

var authenticationResult = await authenticationContext.AcquireTokenAsync(
      "https://batch.core.windows.net/", 
      new ClientCredential("<app ID>", "<app secret>"));

我假设已经有 一个已注册的应用程序。要获取应用 ID,请访问 Azure Active Directory应用注册,您可以在其中找到应用程序 ID(也在 Properties 下)。

接下来,您必须为应用创建密钥。因此访问 Azure Active Directory应用注册Keys。在那里您可以创建一个密钥,只需输入一个密钥名称和一个到期时间,然后单击保存。保存后会显示密钥。 (注意: Key 之后无法恢复。请将其保存在某处。)

MobileServiceClient

最后一步是创建MobileServiceClient。由于 UI 登录不可用,我们必须手动创建登录用户(请参阅here)。

MobileServiceClient client = new MobileServiceClient("https://my-app.azurewebsites.net");
client.CurrentUser = new MobileServiceUser("Foo:123456789");
client.CurrentUser.MobileServiceAuthenticationToken = authenticationResult.AccessToken;

现在MobileServiceClient 已通过身份验证并可以使用。

进一步阅读

https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-service-to-service

https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-authentication-scenarios#web-application-to-web-api

https://docs.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.clients.activedirectory.authenticationcontext?view=azure-dotnet

https://docs.microsoft.com/en-us/azure/batch/batch-aad-auth

【讨论】:

【参考方案2】:

您可以使用托管服务身份向应用服务验证您的功能。

您的应用程序可以像自己一样与其他 Azure 服务进行通信 使用托管的 Azure Active Directory 标识。

您可以在此处查看如何启用和使用托管标识:

https://docs.microsoft.com/en-us/azure/app-service/app-service-managed-service-identity

希望这会有所帮助!

【讨论】:

我无法尝试,但从我读到的内容看来,我似乎仍然需要请求身份验证令牌(不是使用 ADAL,而是使用 AzureServiceTokenProvider ),因此我真的不明白这如何使事情变得更简单(除了不必自己找出租户 ID 和应用程序密码)。 此解决方案是官方支持的跨多个 Azure 服务“作为服务”执行请求的方式。您标记了自己的答案,但甚至没有尝试实施正确的方法……对我来说似乎很可疑,并且会引导人们找到错误的解决方案。 这是不是受支持的方式,而是一种预览 - 相应的库也是如此。无论如何,我没有标记我的解决方案,因为我看到指向未来支持的方式有其存在和被承认的权利。

以上是关于如何使用应用服务对 Azure Functions 应用进行身份验证/授权?的主要内容,如果未能解决你的问题,请参考以下文章

Azure Functions 中的 DI

Azure基础:何时使用Azure Functions无服务器计算(11)

如何从 Azure 移动应用服务调用 HTTP(Azure Functions)?

Azure Functions 的身份验证

如何从 Azure Functions 中的存储容器读取多个文件

身份验证如何在 Azure Functions 上工作