3

正如我在这里发现的,我不能打电话

HttpContext.GetOwinContext().Authentication.SignIn(...)

在 FacebookAuthenticationProviderOnAuthenticated事件中。这似乎是一个不同的背景。

我的用户将来自 Facebook,这意味着我将需要检索数据,例如idemail... 此信息可在OnAuthenticated活动中访问,我需要此信息才能登录。

我需要在我的控制器上访问此信息...

我在活动中尝试了这个:

context.OwinContext.Set("FacebookUser", rawUserObjectFromFacebookAsJson);

但是在控制器上,如果我尝试检索它,它是空的。

var fbuser = HttpContext.GetOwinContext()
                 .Get<Newtonsoft.Json.Linq.JObject>("FacebookUser");

所以我的问题是,如何将这些数据传递给控制器​​以便我可以登录?

4

1 回答 1

12

通过查看这个答案并弄清楚我能做什么,我找到了一种方法。

使用Claims我可以添加从 Facebook 检索到的所有值并放入身份声明中。

OnAuthenticated = (context) =>
{
    const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";

    var rawUserObjectFromFacebookAsJson = context.User;

    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "Facebook"));
    foreach (var x in context.User)
    {
        var claimType = string.Format("urn:facebook:{0}", x.Key);
        string claimValue = x.Value.ToString();
        if (!context.Identity.HasClaim(claimType, claimValue))
            context.Identity.AddClaim(new System.Security.Claims.Claim(claimType, claimValue, XmlSchemaString, "Facebook"));

    }

    return Task.FromResult(0);
}

然后在我的控制器上,我可以通过使用它来获得该身份

ClaimsIdentity identity = await HttpContext.GetOwinContext().Authentication
    .GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

然后我将有我的行动

[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
    ClaimsIdentity identity = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);

    var user = new IdentityUser()
    {
        Id = identity.GetUserId(),
        UserName = identity.Name,
    };

    await LoginAsync(user, identity);

    if (!identity.IsAuthenticated)
    {
        return RedirectToAction("Login");
    }

    return RedirectToAction("Index", "Home");
}

还有我的 LoginAsync 方法

private async Task LoginAsync(IdentityUser user, ClaimsIdentity identity)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

    // I can't just use the identity I got on Facebook
    // I need to create this one, or else it will not signin properly
    // The authentication type has to be ApplicationCookie and the property
    // is readonly, so...
    var userIdentity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    // now we have to transfer the claims, adding a check to avoid duplicates
    foreach (var claim in identity.Claims)
    {
        if (!userIdentity.HasClaim(c => c.Type == claim.Type))
            userIdentity.AddClaim(claim);
    }

    // then it will signin successfully
    AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = true }, userIdentity);
}

然后我可以访问

HttpContext.GetOwinContext().Authentication.User.Claims

随时取回我需要的东西。

于 2013-11-04T00:08:57.420 回答