Phonegap (Android) 上的 ASP.NET 表单身份验证问题
Posted
技术标签:
【中文标题】Phonegap (Android) 上的 ASP.NET 表单身份验证问题【英文标题】:Issues with ASP.NET Forms Authentication on Phonegap (Android) 【发布时间】: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 中是否有可能导致这种行为的东西?还有什么我可以测试的吗?请帮忙!
如果需要,我很乐意提供更多信息。
编辑: 受到 F*** 评论的启发,我将注销方法更改为:
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。 【参考方案1】:PhoneGap 从file://
协议加载文件。不幸的是,不允许跨源请求,除非您打开来自所有主机*
的跨源请求,否则此问题将无法解决。
有多种方法可以解决这个问题,但它们真的很长。
从http://
加载Html
从网络服务器而不是本地存储加载整个网站。这消除了跨源请求的所有问题。好处是您在更改 UI 时不需要发布新版本的应用程序。但是你必须实现非常强大的缓存,并且第一次打开应用程序需要更长的时间。
拦截http://
并传递本地文件
如您所知,phonegap 仅使用 WebView,在所有平台上,您都可以简单地覆盖 Url 协议以从应用程序的本地存储中注入文件。这会更快,并且浏览器会认为它正在从同一资源加载 html。
设置 OAuth + 自定义标头进行身份验证
-
重定向到您网站上托管的登录页面,例如
http://domain.com/api/login
登录成功后,使用PhoneGap localStorage
(不是浏览器的localStorage)来存储授权。
从应用导航到您的本地 html 页面,对于您发送到服务器的每个 json api 请求,将授权标头作为单独的标头发送到 ajax 请求中。
设置授权模块,如果您的授权是通过 http 请求中的自定义标头发送的,您可以在其中手动授权 asp.net 请求
【讨论】:
感谢您的详细解答。我认为您是对的,解决此问题的正确方法是将身份验证方法更改为 OAuth 或类似方法。【参考方案2】:我相信我已经找到了解决方案。根据documentation,您的config.xml 文件中的Phonegap 版本是cli-5.1.1,其中包括Android Phonegap 版本4.0.2。
版本的问题在于,Android Phonegap 团队似乎最终修复了版本 5.2.0 上的 cookie 存储问题。可以在release notes中找到:
CB-10896我们从未在 WebView 上启用 cookie
因此,将您的 Phonegap 更新到最新版本应该可以解决问题。
【讨论】:
你在哪里找到 OP 的 config.xml 文件? 我认为我没有得到这个问题。你能说得更具体一点吗? 不幸的是,这并没有解决问题。我现在使用的是 cli-6.3.0 (Android 5.2.1),登录/注销的行为完全相同。【参考方案3】:根据MSDN:
FormsAuthentication.SignOut 方法删除 来自 cookie 的表单身份验证票信息。
这就是您注销用户所需的全部内容。您不需要过期或删除您的 cookie 本身。只需将您的 Logout()
更改为:
[ActionName("logout")]
[AllowAnonymous]
public String Logout()
FormsAuthentication.SignOut();
return "home";
【讨论】:
以上是关于Phonegap (Android) 上的 ASP.NET 表单身份验证问题的主要内容,如果未能解决你的问题,请参考以下文章
eclipse / Android上的Cordova phonegap
PhoneGap 的 getPicture() 调用不会保存到 Android 手机上的图库
如何避免仅在 Android 上的 Phonegap 应用程序黑屏?