首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ExternalIdentity.BootstrapContext总是空的

ExternalIdentity.BootstrapContext总是空的
EN

Stack Overflow用户
提问于 2015-06-19 13:35:06
回答 1查看 1.2K关注 0票数 1

在我的当前应用程序中,我使用Owin + Aspnet身份以及Microsoft提供程序来处理身份验证。

到目前为止,除了我试图检索远程令牌以将其存储在我的数据库之外,一切都很好。

我在网上找到了一些文档,上面写着在saveBootstrapContext中启用“web.config”,所以我做到了:

代码语言:javascript
复制
<system.identityModel>
<identityConfiguration saveBootstrapContext="true">
  <securityTokenHandlers>
    <securityTokenHandlerConfiguration saveBootstrapContext="true"></securityTokenHandlerConfiguration>
  </securityTokenHandlers>
</identityConfiguration>
</system.identityModel>

我只在identityConfiguration上尝试,然后只在securityTokenHandlerConfiguration上尝试,然后两者在一起,但是结果总是一样的。在下面的代码中,externalData.ExternalIdentity.BootstrapContext始终为空。

SignIn方法在中间件调用的"ExternalLoginCallback“方法中被调用。

代码语言:javascript
复制
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Web;

// custom namespaces redacted
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;

public class AuthManager : IAuthManager
{
    private readonly IUserBusinessLogic userBusinessLogic;

    public AuthManager(IUserBusinessLogic userBusinessLogic)
    {
        this.userBusinessLogic = userBusinessLogic;
    }

    public void SignIn()
    {
        IAuthenticationManager manager = HttpContext.Current.GetOwinContext().Authentication;
        var externalData = manager.GetExternalLoginInfo();

        UserDto user = this.userBusinessLogic.GetUser(externalData.Login.LoginProvider, externalData.Login.ProviderKey);
        var token = ((BootstrapContext)externalData.ExternalIdentity.BootstrapContext).Token;

        if (user == null)
        {
            user = this.userBusinessLogic.AddUser(new UserDto(), externalData.Login.LoginProvider, externalData.Login.ProviderKey, token);
        }

        user.Token = token;

        var claims = new Claim[]
        {
            new Claim(ClaimTypes.NameIdentifier, user.ID.ToString()),
            new Claim(ClaimTypes.UserData, UserData.FromUserDto(user).ToString())
        };

        var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
        var properties = new AuthenticationProperties
        {
            AllowRefresh = true,
            IsPersistent = true
        };

        manager.SignIn(properties, identity);
    }

这里的其他一些帖子是这样说的:尝试重新启动IIS、重新启动机器、清空浏览器cookie和重新启动浏览器。我都试过了,但还是一无所获。如果我模拟令牌字符串,其他一切都能正常工作。

现在我显然遗漏了一些东西,但是我在网上找不到任何清晰的文档。

任何帮助都是非常感谢的。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-25 16:29:13

有时没有任何帮助是最好的帮助,因为我被迫越挖越深,最终找到解决方案。

正当的前提是,我当时完全混乱,我混合了三种不同的技术,而没有理解所有的含义。

我的例子在web.config中使用了WIF配置,但是代码端使用的是OWIN顶部的Aspnet (根本不使用web.config )。

一旦我理清了自己的想法,我就意识到以下几点:

  • WIF完全不需要,因此我摆脱了所有这些配置(以及WIF )。
  • 由于我的MS auth是由处理它的特定OWIN中间件执行的,所以我必须了解如何配置它以检索令牌。
  • Aspnet标识仅用于DefaultAuthenticationTypes静态类,它提供了一些字符串常量。为了简单起见,我保留了它,但我也可以删除它。

因此,我的重构代码(和工作代码)如下所示。首先,要使MS auth与令牌一起工作,在Startup.cs中使用中间件配置。

代码语言:javascript
复制
app.UseMicrosoftAccountAuthentication(new MicrosoftAccountAuthenticationOptions
{
    ClientId = "myClientId",
    ClientSecret = "myClientSecret",
    Provider = new MicrosoftAccountAuthenticationProvider
    {
        OnAuthenticated = context =>
        {
            // here's the token
            context.Identity.AddClaim(new System.Security.Claims.Claim("AccessToken", context.AccessToken));
            context.Identity.AddClaim(new System.Security.Claims.Claim("FirstName", context.FirstName));
            context.Identity.AddClaim(new System.Security.Claims.Claim("LastName", context.LastName));
            return Task.FromResult(true);
        }
    }
});

然后,重新检查SignIn方法:

代码语言:javascript
复制
public void SignIn()
{
    IAuthenticationManager manager = HttpContext.Current.GetOwinContext().Authentication;
    var externalData = manager.GetExternalLoginInfo();

    UserDto user = this.userBusinessLogic.GetUser(externalData.Login.LoginProvider, externalData.Login.ProviderKey);

    if (user == null)
    {
        user = this.userBusinessLogic.AddUser(
            new UserDto
            { 
                FirstName = externalData.ExternalIdentity.Claims.Single(c => c.Type == "FirstName").Value,
                LastName = externalData.ExternalIdentity.Claims.Single(c => c.Type == "LastName").Value
            },
            externalData.Login.LoginProvider,
            externalData.Login.ProviderKey,
            // here's the token claim that I set in the middleware configuration
            externalData.ExternalIdentity.Claims.Single(c => c.Type == "AccessToken").Value);
    }

    var claims = new Claim[]
    {
        new Claim(ClaimTypes.NameIdentifier, user.ID.ToString()),
        new Claim(ClaimTypes.UserData, UserData.FromUserDto(user).ToString()),
        new Claim("AccessToken", user.Token),
        new Claim("FirstName", user.FirstName),
        new Claim("LastName", user.LastName)
    };

    var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);
    var properties = new AuthenticationProperties
    {
        AllowRefresh = true,
        IsPersistent = true
    };

    manager.SignIn(properties, identity);
}

也许这对我来说是很困难的,但是无论如何,我在这里发布我的解决方案,希望它能避免一些头痛和一些天的咒骂一些同事开发人员。

快乐编码^^

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30939552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档