Я занимаюсь разработкой приложения для 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);
и я предполагаю, что это является основой отслеживания того, авторизован посетитель или нет. Насколько я понимаю, когда посетитель пытается вызвать ActionResult, который требует [Авторизовать], тогда система проверит этот cookie.
Хорошо, может кто-нибудь объяснить, почему приведенный выше код работает в Chrome / Safari, но продолжает бесконечно циклически проходить через Login и затем OAuth в IE?
Мое приложение использует MVC 3, EF Code First и Facebook C # SDK 5.0.25