1

我正在开发一个 Facebook 应用程序,如果访问者通过 Facebook 获得授权,我只想允许访问某些视图。这应该是一个非常简单的任务,我认为是,直到我在 IE 中尝试了它。以下代码在 Chrome 和 Safari 中运行良好。我想使用表单身份验证,因此我设置了

<forms loginUrl="~/Account/Login" timeout="2880" />

在 web.config 中。这将在进入我的应用程序时将访问者引导至以下 ActionResult:

    public ActionResult Login(string returnUrl)
    {
        ManagerGame2.Utilities.StaticDataContent.InitStaticData();

        var oAuthClient = new FacebookOAuthClient();
        oAuthClient.AppId = FacebookApplication.Current.AppId;
        oAuthClient.RedirectUri = new Uri(redirectUrl);
        var loginUri = oAuthClient.GetLoginUrl(new Dictionary<string, object> { { "state", returnUrl } });
        return Redirect(loginUri.AbsoluteUri);
    }

然后用户被重定向到 Facebook 页面,访问令牌被发送回我的 OAuth ActionResult:

public ActionResult OAuth(string code, string state)
    {
        FacebookOAuthResult oauthResult;
        if (FacebookOAuthResult.TryParse(Request.Url, out oauthResult))
        {
            if (oauthResult.IsSuccess)
            {
                var oAuthClient = new FacebookOAuthClient();
                oAuthClient.AppId = FacebookApplication.Current.AppId;
                oAuthClient.AppSecret = FacebookApplication.Current.AppSecret;
                oAuthClient.RedirectUri = new Uri(redirectUrl);
                dynamic tokenResult = oAuthClient.ExchangeCodeForAccessToken(code);
                string accessToken = tokenResult.access_token;

                DateTime expiresOn = DateTime.MaxValue;

                if (tokenResult.ContainsKey("expires"))
                {
                    DateTimeConvertor.FromUnixTime(tokenResult.expires);
                }

                FacebookClient fbClient = new FacebookClient(accessToken);
                dynamic me = fbClient.Get("me?fields=id,name");
                long facebookID = Convert.ToInt64(me.id);


                Account acc = (from x in db.Account.OfType<Account>() where x.FaceBookID == facebookID select x).FirstOrDefault();
                if (acc == null)
                {
                    acc = CreateAccount(me);
                }
                acc.LatestLogin = DateTime.Now;
                db.Entry(acc).State = EntityState.Modified;
                db.SaveChanges();

                MemoryUserStore.CurrentAccount = acc;

                UserRoleProvider usp = new UserRoleProvider();
                usp.GetRolesForUser(acc.AccountID.ToString());
                FormsAuthentication.SetAuthCookie(acc.AccountID.ToString(), false);

                if (Url.IsLocalUrl(state))
                {
                    return Redirect(state);
                }
                return RedirectToAction("Details", "Account", new { id = acc.AccountID });
            }
        }

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

我在这里要做的是首先验证我从重定向返回的令牌是否有效。如果是,那么我会提取有关访问者的一些数据,例如 FacebookID 和姓名。然后我将它与我的数据库进行匹配,以查看用户是否已经存在,如果不存在,我创建一个。我还在我的自定义角色提供程序中为用户分配了一个角色,但在此之前我遇到了无限循环问题。然后我设置

FormsAuthentication.SetAuthCookie(acc.AccountID.ToString(), false);

我认为这是跟踪访问者是否被授权的核心。据我了解,当访问者尝试调用需要 [Authorize] 的 ActionResult 时,系统将检查此 cookie。

好吧,有人可以澄清一下为什么上面的代码在 Chrome/Safari 中工作,但在 IE 中不断循环登录然后 OAuth 无限?

我的应用正在使用 MVC 3、EF Code First 和 Facebook C# SDK 5.0.25

4

2 回答 2

1

好的,所以我发现问题是由 [Authorize] 注释触发的,正如预期的那样。Facebook SDK 有一个 [CanvasAuthorize] 注释,当我切换到使用它时,IE 工作正常并且不会永远登录。

在此之前,我尝试使用 cookieless 身份验证,但 IE 仍然不想玩。

据我所知,出现问题是因为 Facebook 应用程序位于 IFrame 内。据说这用饼干和信任搞砸了。如果有人知道这是为什么,我会很高兴听到它。

另外,如果有人知道如何通过这个 [CanvasAuthorize] 轻松地使用和维护角色,我将很高兴知道。

于 2011-05-17T20:41:56.097 回答
0

我知道这看起来很明显,但你确定 IE 中没有禁用 cookie 吗?在开发人员工具中有一个禁用 cookie 的选项。

于 2011-05-17T11:02:44.393 回答