【问题标题】:Add ClaimsIdentity to ClaimsPrincipal - JwtBearer将 ClaimsIdentity 添加到 ClaimsPrincipal - JwtBearer
【发布时间】:2018-05-22 09:38:18
【问题描述】:

我的系统包含两个授权步骤(但不是标准方式)。

我的客户端应用程序首先通过登录名和密码与服务器连接(它就像 ApiSecret 和 ApiKey)。

接下来,经过身份验证后,服务器返回带有基本信息(用户名、角色等)的不记名令牌。但请注意,这个用户就像 ApiClient 不是活人 :)

接下来,应用程序显示登录表单。这是一个活着的人登录的时候了。所以他将他的凭据传递给 API,该 API 检查该用户是否可以登录。

这是我有问题的地方。直到现在我都认为它会像这样工作:

如果用户可以登录到应用程序,我会创建新的 ClaimsIdentity 并将其添加到 ClaimsPrincipal Identities。

这个想法很棒,但它不起作用:/事实证明,下一个请求不会发送第二个身份信息。我什至知道为什么。 Becase ClaimsPrincipal 是根据收到的不记名令牌创建的。但是这些知识并不能解决我的问题。

我应该怎么做才能将新的 ClaimsIdentity 添加到现有的 ClaimsPrincipal 并在请求之间存储此值? (直到用户退出应用程序)

【问题讨论】:

  • 我不了解您的架构。您的应用程序如何与客户端通信? (用户)- ASP.Net MVC?
  • 发行另一个不记名令牌?
  • 很难想象你想要做什么。发布代码,发布相关框架版本(WebApi?EF Identity?)。你是说要同时有两个并行的身份,还是要替换第一个(api用户vs物理用户)?听起来您使事情变得过于复杂,这在身份验证/授权方面几乎不是一个好主意
  • 我正在使用 WebApi 和 EF Identity。我只有 2 个用户——第一个是 api 客户端——你可以说这个用户是“登录”到 WebApi 的客户端应用程序。另一个用户是登录到客户端应用程序的人。

标签: c# claims-based-identity


【解决方案1】:

经过大量挖掘和研究,我能够创建一个解决方案(.Net Core 2)。 您必须在配置服务中添加 Cookie 身份验证,所有这些都应如下所示:

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            })
            .AddJwtBearer(cfg =>
            {
                 //standard settings
            })
            .AddCookie(AuthTypes.CLIENT_AUTHENTICATION_TYPE, cfg =>
                {
                    //cookie settings; the most important is following event:
                    cfg.Events.OnValidatePrincipal = (CookieValidatePrincipalContext ctx) =>
                    {
                        ClaimsPrincipal mainUser = ctx.HttpContext.User; //get ClaimsPrincipal from JwtBearer
                        ClaimsPrincipal cookieUser = ctx.Principal; //get ClaimsPrincipal read from Cookie

                        Debug.Assert(mainUser.Identities.Count() == 1);

                        //now we have to add ClaimsIdentity to main ClaimsPrincipal (from JwtBearer). We add only those absent in main ClaimsPrincipal (here is simplified solution) 
                        var claimsToAdd = cookieUser.Identities.Where(id => id.AuthenticationType != mainUser.Identities.ElementAt(0).AuthenticationType);
                        mainUser.AddIdentities(claimsToAdd);
                        return Task.CompletedTask;
                    };
                }

            );

AuthTypes.CLIENT_AUTHENTICATION_TYPE - 它只是带有您的身份验证类型名称的字符串。

接下来我们必须稍后在 ConfigureServices 中配置默认​​策略过滤器(基本配置):

services.AddMvc(config =>
{
    var defaultPolicy = new AuthorizationPolicyBuilder(new[] { JwtBearerDefaults.AuthenticationScheme, AuthTypes.CLIENT_AUTHENTICATION_TYPE })
        .RequireAuthenticatedUser()
        .Build();
    config.Filters.Add(new AuthorizeFilter(defaultPolicy));
});

这里重要的是在 AuthorizationPolicyBuilder 中传递这个数组。

现在 Authorization 会考虑 JwtBearer,但也会读取 cookie。

现在如何设置 cookie。这可以是额外的登录过程(您在控制器级别进行):

var authProps = new AuthenticationProperties
{
    IsPersistent = true,
    IssuedUtc = DateTimeOffset.Now
};

await HttpContext.SignInAsync(AuthTypes.CLIENT_AUTHENTICATION_TYPE, User, authProps);

User 这里只是带有附加 ClaimsIdentities 的 ClaimsPrincipal。 这就是所有人:)

【讨论】:

    猜你喜欢
    • 2014-09-01
    • 2017-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-28
    • 2016-11-14
    相关资源
    最近更新 更多