【发布时间】:2015-11-10 04:09:22
【问题描述】:
我有一个 ASP.NET MVC/Web API 后端,我在其中为我的 Phonegap 应用程序实现了表单身份验证。通过 jQuery Ajax 调用发送用户凭据来执行登录,如下所示:
$.ajax({
type: "POST",
url: "/api/authentication/login",
data: JSON.stringify({ Username: username, Password: password }),
contentType: "application/json; charset=utf-8",
dataType: "TEXT",
statusCode: {
200: function (response, status, xhr) {
// successfully authenticated
Backbone.history.navigate("/", { trigger: true });
}
}
});
后端登录方法如下:
[ActionName("login")]
[AllowAnonymous]
public LoginResult Login(LoginCredentials credentials)
{
// doing all kinds of things here
// if valid credentials
FormsAuthentication.SetAuthCookie(loginID, true);
return loginResult;
}
我的 Web.config 中有这个:
<authentication mode="Forms">
<forms
name=".ASPXAUTH"
loginUrl="/login"
defaultUrl="/home"
protection="All"
slidingExpiration="true"
timeout="525600"
cookieless="UseCookies"
enableCrossAppRedirects="false"
requireSSL="true"
>
</forms>
</authentication>
现在 Android 的问题是 cookie 设置正确,登录后它确实可以在我的授权方法上运行,但有时(通常)当我关闭应用程序并再次打开它时,我不再登录. cookie 不存在了,我在请求中看不到它。这不应该发生,因为我已将超时设置为 525600。我注意到当我在登录后立即关闭应用程序时经常会出现此问题。另一方面,如果我在不关闭应用程序的情况下注销然后登录,则 cookie 会正确保存。
但是,如果我让 cookie 粘贴,那么大多数时候注销的行为也会很奇怪。这就是我执行注销请求的方式:
$.ajax({
type: "POST",
url: "/api/authentication/logout",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "text"
success: function (response) {
// successfully logged out
Backbone.history.navigate("api/login", { trigger: true });
}
});
后端:
[ActionName("logout")]
[AllowAnonymous]
public String Logout()
{
FormsAuthentication.SignOut();
HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie.Expires = DateTime.Now.AddYears(-1);
HttpContext.Current.Response.Cookies.Add(cookie);
return "home";
}
现在类似于登录的问题,首先注销似乎是成功的,并且不再随任何请求发送 cookie。但是当我关闭应用程序并再次打开它时,cookie 又回来了,我又重新登录了。通过将过期时间设置为过去,我可以看到该 cookie 的值与我认为我刚刚删除的那个相同。
我尝试过各种技巧,比如:
- 登录/注销后额外重新加载 (
location.reload()) - 多次执行注销/登录请求
- 登录/注销后对其他方法执行请求
- 登录/注销请求和重新加载之间的超时 1-10 秒
- 上述的各种变体
身份验证在 iOS 和 Windows Phone 上按预期工作。该问题仅在 Android 上出现(在 KitKat 和 Lollipop 上测试)。在 Android 模拟器上没有问题,但在真实设备和 Visual Studios Android 模拟器上,这种情况一直发生。
我不知道从这里往哪个方向走。 Android WebView 中是否有可能导致这种行为的东西?还有什么我可以测试的吗?请帮忙!
如果需要,我很乐意提供更多信息。
编辑: 受到 Fabian 评论的启发,我将注销方法更改为:
FormsAuthentication.SignOut();
HttpCookie cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];
cookie.Expires = DateTime.Now.AddYears(-1);
HttpContext.Current.Response.Cookies.Clear();
HttpContext.Current.Response.Cookies.Add(cookie);
return "home";
我没有创建一个新的 cookie,而是在响应中使用了那个。它没有用。
我还尝试了从这里找到的东西:http://techblog.dorogin.com/2013/01/formsauthentication-gotcha-with-signout.html 那也没有区别,路径不是问题。仍在寻找解决方案。
另一个编辑: 仍然无法找到解决方案。我不得不做出一个可怕的解决方法。
- 登录:我在登录后进行了两次重新加载,然后请求 一个虚拟的方法。这似乎每次都有效。
- 注销:我使用放置在 localStorage 中的标志来确定用户是否已注销并在启动时执行注销。这总是能正确删除 cookie。
我对这些 hack 不满意,我仍然希望有更好的解决方案。
【问题讨论】:
-
我认为您应该发布您的 Android 代码以获取更多信息。
-
“Android 代码”是什么意思?我说的是Phonegap应用程序,所有相关的JS代码都在问题中。
-
我的意思是你如何设置你的 WebView
-
Phonegap (Cordova API) 正在为我“设置”WebView。我只能通过config.xml 控制应用程序的设置。 AndroidManifest.xml 根据这些设置在构建中创建。
-
在黑暗中拍摄。您可以尝试将 HttpContext.Current.Response.Cookies.Add(cookie) 替换为 Response.Cookies[System.Web.Security.FormsAuthentication.FormsCookieName].Expires = DateTime.Now.AddYears(-1)。不确定它会改变什么,但可以防止您最终创建多个 cookie 并使用错误的 cookie。
标签: android asp.net cordova authentication cookies