C# 自定义声明不会在中间件之外持久存在

C# 自定义声明不会在中间件之外持久存在,c#,asp.net-core,C#,Asp.net Core,我正在尝试创建自定义声明并在整个会话中保持它们。不幸的是,它们似乎不能在中间件本身之外持久存在。我错过什么了吗 using System; using System.Collections.Generic; using System.DirectoryServices.AccountManagement; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.A

我正在尝试创建自定义声明并在整个会话中保持它们。不幸的是,它们似乎不能在中间件本身之外持久存在。我错过什么了吗

using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Distributed;
using SRD.Data;
using SRD.Extensions;

namespace SRD.Security
{
    public class ServerClaimsMiddleware
    {
        private readonly RequestDelegate _next;

        public ServerClaimsMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        private const string ClaimsLastCheckedKey = "ClaimsLastChecked";

        public async Task Invoke(HttpContext context, DbContext dbContext, IDistributedCache cache)
        {
            if (context.User.Identity.IsAuthenticated)
            {
                var claimsLastChecked = await cache.RetrieveFromCache<DateTimeOffset?>(ClaimsLastCheckedKey);
                if (!claimsLastChecked.HasValue)
                {
                    var cs = new List<Claim>();

                    using (var principalContext = new PrincipalContext(ContextType.Domain))
                    {
                        if (context.User.Identity is ClaimsIdentity identity)
                        {
                            var user = UserPrincipal.FindByIdentity(principalContext, identity.Name);
                            if (user != null) cs.Add(new Claim(CustomClaimType.DisplayName.ToString(), user.DisplayName));
                        }
                    }

                    var roles = await dbContext.Roles.All();
                    foreach (var role in roles.Where(r => context.User.IsInRole(r.ADGroupName)))
                    {
                        var roleClaims = dbContext.Claims.ByRole(role.ADGroupName);
                        var customClaims = roleClaims.Select(x => new Claim(CustomClaimType.Permission.ToString(), x.Name));
                        cs.AddRange(customClaims);
                    }
                    if (cs.Any()) context.User.AddIdentity(new ClaimsIdentity(cs, "Kerbros"));

                    await cache.SaveToCache(ClaimsLastCheckedKey, DateTimeOffset.Now, new TimeSpan(0, 0, 15, 0));
                }
            }

            await _next(context);
        }
    }

    public static class ServerClaimsMiddlewareExtensions
    {
        public static IApplicationBuilder UseServerClaimsMiddleware(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<ServerClaimsMiddleware>();
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.DirectoryServices.AccountManagement;
使用System.Linq;
使用System.Security.Claims;
使用System.Threading.Tasks;
使用Microsoft.AspNetCore.Builder;
使用Microsoft.AspNetCore.Http;
使用Microsoft.Extensions.Caching.Distributed;
使用SRD数据;
使用SRD.Extensions;
名称空间SRD.Security
{
公共类ServerClaimsMiddle软件
{
private readonly RequestDelegate\u next;
公共服务器ClaimsMiddleware(RequestDelegate下一步)
{
_下一个=下一个;
}
private const string claimslastcheckey=“ClaimsLastChecked”;
公共异步任务调用(HttpContext上下文、DbContext DbContext、IDistributedCache缓存)
{
if(context.User.Identity.IsAuthenticated)
{
var claimsLastChecked=await cache.RetrieveFromCache(ClaimsLastCheckedKey);
如果(!claimsLastChecked.HasValue)
{
var cs=新列表();
使用(var principalContext=newprincipalcontext(ContextType.Domain))
{
if(context.User.Identity是ClaimsIdentity标识)
{
var user=UserPrincipal.FindByIdentity(principalContext,identity.Name);
if(user!=null)cs.Add(新声明(CustomClaimType.DisplayName.ToString(),user.DisplayName));
}
}
var roles=await dbContext.roles.All();
foreach(roles.Where(r=>context.User.IsInRole(r.ADGroupName))中的var角色)
{
var roleClaims=dbContext.Claims.ByRole(role.ADGroupName);
var customClaims=roleClaims.Select(x=>newclaims(CustomClaimType.Permission.ToString(),x.Name));
cs.AddRange(客户索赔);
}
if(cs.Any())context.User.AddIdentity(newclaimsidentity(cs,“Kerbros”);
SaveToCache(ClaimsLastCheckedKey,DateTimeOffset.Now,newtimespan(0,0,15,0));
}
}
等待下一步(上下文);
}
}
公共静态类ServerClaimsMiddlewareExtensions
{
公共静态IApplicationBuilder UseServerClaimsMiddware(
此IApplicationBuilder(应用程序生成器)
{
返回builder.UseMiddleware();
}
}
}

您正在将它们添加到ClaimsPrincipal中,但这不会将数据保留在任何地方。 当ASP.NET Core对请求进行身份验证时,它会从cookie/token/其他内容创建ClaimsPrincipal。 它不会自动转到另一个方向;修改主体纯粹是在内存中进行的

如果您的应用程序是创建cookie/令牌的应用程序, 我认为在修改主体后,可以通过在中间件中调用
context.SignInAsync()
来编写一个新的

// you need this import
using Microsoft.AspNetCore.Authentication;

// In your middleware Invoke()
await context.SignInAsync(context.User);
如果尚未配置默认登录方案,还可以为SignInAsync()指定身份验证方案