iOS uiwebview向.net后端发起请求无效的问题

原文网址:http://supermariobean.github.io/ios/2015/01/12/使用uiwebview向.NET后端发起请求无效的问题.html

BUG

这是一个bug引发的故事,主要涉及的技术环境:客户端部分,在iOS 8.1.2系统下,使用控件UIWebView实现了native部分的Hybrid框架;Web部分,以.NET 4.0环境作为后端,H5+js+css作为了H5部分的hybrid前端框架,并简单基于框架写了一个应用,应用暂时只对向后端做一次简单ajax,在请求之前,通过将native中保存的登录态转移至UIWebView中的localstorage实现登录信息传递,而本次请求也主要是携带Auth信息确认用户登录态而已。

既然是一个bug,那就按bug单来对待

  • What steps will reproduce the problem?

    通过native端的自定义UIWebView打开指定的URL链接,就会出现不正常的结果

  • What is the expected output? What do you see instead?

    期望输出:指定的URL链接正确通过登录态检查,显示出正常的登录验证后页面 实际输出:登录态验证失败,页面逻辑失败

  • What version of the product are you using? On what operating system?

    iOS 8.1.2 iPhone5s, .NET 4.0

  • Please provide any additional information below. / Please use labels and text to provide additional information.

    就目前的测试来看,Android系统没有任何问题,该问题只发生在iOS系统上; 而在iOS系统上,自带浏览器Safari没有任何问题;只有使用开发组件UIWebView才会出现; 服务端日志可以看出,请求进入了请求处理逻辑,但是其中的POST参数为空,服务端按照普通的异常逻辑处理并响应结果

解决过程

bug单的信息已经描述的比较清晰,但是还是要自己亲自验证一遍,经过验证后结果也基本相同。问题的重点就在Safari可用和UIWebView不可用上了。

有一点需要提一下的,由于使用了Hybrid框架,所以通过Safari打开URL,Web APP的生命周期是一个单纯的Web应用;但是通过natitve端Hybrid的UIWebView打开URL,因为桥接JS代码的作用,该Web APP的部分数据通过桥接JS代码在native和H5之间相互传递。

为了排除是自己代码的问题,因为继承了框架中的UIWebView的子类,虽然实现的逻辑不多,但也需要排除。通过应用中的其他native Hybrid入口加载URL,得到了同样结果,所以首先可以确认自己的代码没有问题。既然是Web APP,浏览器调试少不了,通过Safari与iOS APP内的UIWebVIew联调,没有发现其它什么明显的错误,于是直接找到登录验证的ajax请求,查看详细的请求和响应内容,发现了以下问题:

  • 1.请求路径被加入了一段奇怪的字符串,而正常运行的Safari环境下请求的路径没有发生任何改变。

    http://m.supermariobean.com/(F(vy2ebt45imfkmjjwboow3l55 ))/ajax.ashx
    
  • 2.请求POST参数正常。这与服务端的请求处理逻辑中打出的日志显示POST参数传入为空矛盾。

  • 3.响应体结构正常,内容是处理POST参数为空情况下返回的响应。这与服务端的日志吻合。

以上大致说明了几个问题,在自定制的Hybrid框架环境中,ajax请求的路径被重写了,增加了一个字符串;请求被IIS接受,并被路由到了正确了处理函数中,说明这一段字符串并不是无意义的,既然可以被IIS接受,那么很可能是.NET框架在处理请求响应的过程中加入的;请求POST参数在发送时存在,IIS接收后路由到相应的处理函数后就没有了,进一步说明了问题可能出在IIS和.NET框架中。

在验证这个猜想之前,我们还是尽量排除自定制的Hybrid框架的干扰。分别对Hybrid框架的native端和H5端都进行了跟踪调试,发现,native端压根就没有捕获并修改ajax请求的机会,而H5端,跟踪js代码直到请求url被移交给XHttpRequest对象,url都没有任何改动。

至此,基本可以确定,公司框架也没有问题,问题应该是iOS的Cocoa Touch框架、IIS Web服务器和.NET框架

一想到微软和苹果这两家公司的恩怨,我就知道应该没错了…

因为大致定位了问题的方向,搜索的关键字确定如下:

iOS UIWebView urlrewrite .NET IIS

在搜索结果中定位了微软关于IISUsing the URL Rewrite Module的文章,已知问题这一节如下:

Known Issues

UseUri mode in ASP.NET Forms authentication uses rewritten URL for redirection. For example, if the requested URL is “/article.htm” and URL Rewrite module rewrites the URL to “/article.aspx”, which is protected by Forms authentication, then ASP.NET will redirect to “/(S(vy2ebt45imfkmjjwboow3l55 ))/article.aspx”.

ASP.NET rewrites back to the original URL when using URI-based authentication or cookie-less session state. For example, when a request is made to “/(S(vy2ebt45imfkmjjwboow3l55 ))/article.htm” and URL rewrite module rewrites “/article.htm” to “/article.aspx”, then ASP.NET will rewrite the URL back to “/article.htm”, which may result in a “404 - File Not Found” error.

如前所述,Web APP并没有使用任何authentication,所以排除这里面的authentication条件,就只剩下cookie-less session state。大致的意思是在IIS中,如果发送请求的UserAgent处于cookie disable的状态,则会是请求的url重写为带有/(S(vy2ebt45imfkmjjwboow3l55 ))的形式,虽然目前还不知道重写后为何可以响应请求,但无法得到POST参数的原因。至少找到一条新的线索,也就是cookie开启的问题。

接下来搜索关键字如下:

iOS UIWebView enable cookie .NET

Enable Cookies in UIWebView (iPhone)中介绍了一种非常类似的情况。当使用ASP.NET作为后端,而使用UIWebView作为UserAgent时,需要修改请求的UserAgent字段,否则会导致问题,同时也会重定向到另一中模式的url

/(F(vy2ebt45imfkmjjwboow3l55 ))/

情况很类似,但是仍旧不是正确解答。通过重新查看Hybrid框架的native代码,发现框架中已经考虑过了UserAgent的重写和cookie问题,也就是说,客户端应该是正确处理的。这是虽然有点气馁,但是还有一个地方,就是服务端和WEB服务器配置。后面又得知后端并没有使用公司现有的gateway模式,所以很有可能是后端问题,于是搜索如下:

UIWebView cookie .NET

搜到了SO中的问答Asp.Net Forms Authentication when using iPhone UIWebView,在题主所遇到的问题和处境和我们非常相似:

  • safari正常,UIWebView有问题(题注的测试更详细,几乎所有的浏览器都正常)

  • cookie开启后依旧不正确

最终的解答是需要在.NET项目中加入一个.browser文件,并在文件中声明如下xml:

<browser refID="Mozilla" >
  <capabilities>
    <capability name="cookies"  value="true" />
  </capabilities>
</browser>

有关browser这个元素的解释链接在MSDN。虽然题主的问题是基于form authentication,但是同样适用于cookieless session state的情况。最终可以解决这个BUG的原因可能是,.NET框架对于Mozilla的每一种Useragent(safari也是其中之一)都有相应的xml配置,但是由于UIWebView这种特殊的组件,导致了.NET对于其Useragent的默认处理,从服务端disable了其cookie的使用,这也就解释了为何在客户端设置cookie enable不起作用的原因。在.NET项目中设置Mozilla的默认cookie设置,也就开启了UIWebView对应Useragent的cookie功能,从而解决了这个问题。

解决问题后重新验证请求,发现请求Path中/(F(vy2ebt45imfkmjjwboow3l55 ))/的字段消失,请求返回正常。删除开启客户端cookie的代码,效果一样,说明客户端的UIWebView是默认开启cookie的,整个问题的核心是cookie的问题,关键是服务端对于不同浏览器useragent的默认处理行为导致了这次bug的产生。当然也要注意,当使用.NET form authentication时也会有相同情况出现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值