.NET7独立Azure Function:如何覆盖HttpRequestData.Identities的ClaimIdentity
问题描述
我正在使用.NET 7独立Azure Function,在执行业务逻辑前需要向ClaimIdentity添加更多信息,编写了如下代码:
public async Task<IActionResult> PreprocessingRequestAsync(HttpRequestData request, Func<Task<IActionResult>> logic) { var hasId = request.Headers.TryGetValues("id", out var id); var hasUsername = request.Headers.TryGetValues("username", out var username); var hasEmail = request.Headers.TryGetValues("email", out var email); if (hasId && hasUsername && hasEmail) { var user = new ClaimsIdentity(new[] { new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier", id.FirstOrDefault()), new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname", username.FirstOrDefault()), new Claim("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", email.FirstOrDefault()) } , "ByPassAuth"); request.Identities.Append(user); var response = await ContinueToProcessBusinessLogicAsync(logic, request, false); return response; } }
但上述代码未达到预期效果(无法向ClaimIdentity添加信息),我知道Identities是只读属性,请问是否有可行的实现方法?
可行实现方法
方法1:通过扩展方法替换身份集合(依赖内部实现)
HttpRequestData.Identities返回的是只读集合,但可以通过反射修改其内部存储的列表:
public static void AddIdentity(this HttpRequestData request, ClaimsIdentity identity) { var identitiesField = typeof(HttpRequestData).GetField("_identities", BindingFlags.Instance | BindingFlags.NonPublic); if (identitiesField != null) { var currentIdentities = (List<ClaimsIdentity>)identitiesField.GetValue(request); currentIdentities.Add(identity); } }
替换原代码中的request.Identities.Append(user);为:
request.AddIdentity(user);
注意:该方法依赖Azure Functions SDK的内部字段实现,版本更新可能导致失效,需做好兼容性验证。
方法2:将身份信息存入请求Items集合(稳定推荐)
不依赖内部实现,直接把自定义ClaimsIdentity存入请求的Items字典,后续业务逻辑从这里读取:
// 预处理时存储 request.Items["CustomClaimsIdentity"] = user; // 业务逻辑中读取使用 if (request.Items.TryGetValue("CustomClaimsIdentity", out var identityObj) && identityObj is ClaimsIdentity customIdentity) { // 操作customIdentity中的声明信息 }
这种方式无版本兼容风险,适合生产环境使用。
方法3:通过HttpContextAccessor传递身份信息
如果业务逻辑依赖ClaimsPrincipal,可以将自定义身份封装为ClaimsPrincipal,通过IHttpContextAccessor注入到当前请求上下文:
var principal = new ClaimsPrincipal(user); var httpContextAccessor = request.HttpContext.RequestServices.GetRequiredService<IHttpContextAccessor>(); httpContextAccessor.HttpContext.User = principal; // 业务逻辑中直接获取 var currentUser = _httpContextAccessor.HttpContext.User;
需要确保项目已注册IHttpContextAccessor服务。
内容的提问来源于stack exchange,提问作者Dan Van
相关产品推荐
相关产品推荐

