使用授权时 IE 无限循环

发布于 2024-11-07 17:27:42 字数 3385 浏览 0 评论 0原文

我正在开发一个 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

I'm developing a Facebook app, and i only want to allow access to certain views if the visitor is authorized through Facebook. This should be a pretty simple task, and i thought is was, until i tried it out in IE. The following code works fine in Chrome and Safari. I want to use Forms authentication, and therefore i have set

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

in web.config. This will direct the visitor to the following ActionResult when entering my app:

    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);
    }

Then the user is redirected to a Facebook page, and an access token is sent back into my 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");
    }

What i am trying to do here, is to first verify if the token i get back from the redirect is valid. If it is, then i pull some data about the visitor, like FacebookID and Name. I then match it with my database, to see if the user already exists, and if not, i create one. I also assign a role for the user in my custom Role provider, but i had the infinite loop problem before this. Then i set

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

and i assume this is the core of keeping track of wheter a visitor is authorized or not. As far as i understand, when the visitor is trying to call a ActionResult that requires [Authorize] then the system will check for this cookie.

Well, could someone please clarify why the above code is working in Chrome/Safari, but keeps looping through Login and then OAuth infinitely in IE?

My app is using MVC 3, EF Code First and Facebook C# SDK 5.0.25

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

末骤雨初歇 2024-11-14 17:27:42

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

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

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

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

Okay, so i figured out that the problem was triggered by the [Authorize] annotation, as expected. The Facebook SDK has a [CanvasAuthorize] annotation, and when i switch to using this, IE works fine and does not login forever.

Before this, i tried using cookieless authentication, but IE still didn't want to play along.

As far as i have figured out, the problem occurs because Facebook apps are inside an IFrame. This supposedly screws something up with cookies and trust. If someone knows why this is, i would appreciate to hear about it.

Also, if anyone knows how to use and maintain roles, easily, with this [CanvasAuthorize], i would be glad to know.

红衣飘飘貌似仙 2024-11-14 17:27:42

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

I know this seems obvious but are you sure cookies aren't disabled in IE? There is an option to disable cookies in developer tools.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文