我创建了一个新的功能应用程序,为其启用了应用服务身份验证/授权(“使用身份验证/授权来保护您的应用程序并使用每用户数据”)并禁用未经身份验证的请求。
到目前为止,一切似乎都正常。如果我尝试请求我的HttpTrigger
ed函数,则需要我先登录;一旦我登录,所有请求都将按原样处理。所以“保护你的应用程序”部分没有问题。
但是,我完全坚持“使用每用户数据”部分。我的Azure函数被调用为
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
HttpRequestMessage
中与身份验证无关。 (AuthorizationLevel.Anonymous似乎控制了完全不同的东西 - 即,如果该函数可以被任何人调用,或者只能由具有固定API密钥的人调用。)
如何获取调用该函数的经过身份验证的用户的身份?
答案 0 :(得分:2)
使用Azure Function runtime v2.0.12309,您可以从通过Run
方法注入的authenticated user information实例中检索ClaimsPrincipal:
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
HttpRequest httpRequest,
ILogger logger,
ClaimsPrincipal claimsPrincipal)
{
// Explores the authenticated user's claims in claimsPrincipal.
}
答案 1 :(得分:0)
似乎可以从全局状态System.Security.Claims.ClaimsPrincipal.Current.Identity.Name
获取当前用户名(当我最初发布此问题时,我不知道)。但是,目前还不清楚这是否是一种可靠或推荐的登录用户信息的方法。
示例:
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
namespace FunctionApp
{
public static class Function1
{
[FunctionName("HttpTriggerCSharp")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
return req.CreateResponse(HttpStatusCode.OK, "Hello " + ClaimsPrincipal.Current.Identity.Name);
}
}
}
答案 2 :(得分:0)
与App Service EasyAuth的第一级集成还没有到位,但我们正在我们的回购here中进行跟踪。我们现在正在考虑这个问题,很快就会在这方面有一些改进。
正如您所发现的,您可以启用EasyAuth,它将需要登录,并将通过经过身份验证的主体,允许您通过标准.NET API(如ClaimsPrincipal.Current等)访问它。但问题是您必须使用auth级别Anonymous标记您的方法,这不是您想要的,并且要求您在方法中拒绝未经身份验证的请求(请参阅上面提到的问题中的注释)。
我们将在即将发布的版本中尽快解决所有这些问题。
答案 3 :(得分:0)
逻辑上,AuthorizationLevel.Anonymous 不会为您提供当前的声明主体。
不幸的是,只是更改为AuthorizationLevel.Function也无济于事: 对我来说,即使在通过Azure Active Directory B2C成功进行身份验证后,我发现ClaimsPrincipal.Current为null。
最后,我尝试了AuthorizationLevel.User,但azure函数目前不支持,请参阅here
我相信您需要按照this SO question上接受的答案执行相应的步骤(我现在正在尝试...)
答案 4 :(得分:0)
从我的问题复制,其目的是找到如何使用Azure Active Directory经过身份验证的用户在本地进行调试 https://stackoverflow.com/a/49402152/3602057
这适用于使用Azure功能在Azure上配置的任何提供程序,并且适用于本地调试和部署方案。
好几个小时后(OK,很多),我现在已经找到了解决方案。这适用于本地和部署方案。我在这里发布了一个模板解决方案:
https://github.com/Mike-EEE/Stash/tree/master/AzureV2Authentication/AzureV2Authentication
以下是概述整个过程的步骤:
function-name
.azurewebsites.net local.settings.json
并粘贴AuthenticationToken
设置中上一步的值。AuthenticationBaseAddress
这是主要事件:
public static class AuthenticationExtensions
{
public static Authentication Authenticate(this HttpRequest @this)
{
var handler = new HttpClientHandler();
var client = new HttpClient(handler) // Will want to make this a singleton. Do not use in production environment.
{
BaseAddress = new Uri(Environment.GetEnvironmentVariable("AuthenticationBaseAddress") ?? new Uri(@this.GetDisplayUrl()).GetLeftPart(UriPartial.Authority))
};
handler.CookieContainer.Add(client.BaseAddress, new Cookie("AppServiceAuthSession", @this.Cookies["AppServiceAuthSession"] ?? Environment.GetEnvironmentVariable("AuthenticationToken")));
var service = RestService.For<IAuthentication>(client);
var result = service.GetCurrentAuthentication().Result.SingleOrDefault();
return result;
}
}
请注意:
HttpClient
。这违反了最佳做法。为了完整起见,以下是其余感兴趣的课程:
public class Authentication // structure based on sample here: https://cgillum.tech/2016/03/07/app-service-token-store/
{
[JsonProperty("access_token", NullValueHandling = NullValueHandling.Ignore)]
public string AccessToken { get; set; }
[JsonProperty("provider_name", NullValueHandling = NullValueHandling.Ignore)]
public string ProviderName { get; set; }
[JsonProperty("user_id", NullValueHandling = NullValueHandling.Ignore)]
public string UserId { get; set; }
[JsonProperty("user_claims", NullValueHandling = NullValueHandling.Ignore)]
public AuthenticationClaim[] UserClaims { get; set; }
[JsonProperty("access_token_secret", NullValueHandling = NullValueHandling.Ignore)]
public string AccessTokenSecret { get; set; }
[JsonProperty("authentication_token", NullValueHandling = NullValueHandling.Ignore)]
public string AuthenticationToken { get; set; }
[JsonProperty("expires_on", NullValueHandling = NullValueHandling.Ignore)]
public string ExpiresOn { get; set; }
[JsonProperty("id_token", NullValueHandling = NullValueHandling.Ignore)]
public string IdToken { get; set; }
[JsonProperty("refresh_token", NullValueHandling = NullValueHandling.Ignore)]
public string RefreshToken { get; set; }
}
public class AuthenticationClaim
{
[JsonProperty("typ")]
public string Type { get; set; }
[JsonProperty("val")]
public string Value { get; set; }
}
interface IAuthentication
{
[Get("/.auth/me")]
Task<Authentication[]> GetCurrentAuthentication();
}
public static class Function1
{
[FunctionName("Function1")]
public static IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
var authentication = req.Authenticate();
return authentication != null
? (ActionResult)new OkObjectResult($"Hello, {authentication.UserId}")
: new BadRequestObjectResult("Authentication not found. :(");
}
}