Android Basic验证造成的问题
今天是元旦,节日快乐。
我这两天就为这个问题,晚上终于解决了。
问题是这样的,我写个Android程序访问http服务,服务端使用Http Basic验证。开始使用的是httpclient,先用jvm测试,访问成功。然后用android UnitTest就不行了,返回错误是
400
Bad Request
Your browser sent a request that this server could not understand.
apache的错误是
client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23)
这我就纳闷了,刚开始还以为是https配置错误(服务端使用的是ssl)。
结果切换为http还是一样的错误。
于是乎我就找到了
http://stackoverflow.com/questions/12418458/client-sent-http-1-1-request-without-hostname-see-rfc2616-section-14-23-from/12434731#12434731
这位老兄和我一样的情况,最后他说是android 上http请求host头没设置造成的。
(就是他害我思路错误啊!)
我也试了一下,加了个Host头,而且要放在Authentication头之前。
这样client sent HTTP/1.1 request without hostname (see RFC2616 section 14.23)
这个错倒是没有了,但是发现发送的内容服务器接收不到。
那就只好看看到底发的是什么东西了,这里要用到tcpdump:
具体见http://www.growprogress.com/vcommon/?p=1293
使用http://www.strazzere.com/android/tcpdump 这个链接下载android上可运行的较好。
当获得日志后还要配合wireshark来分析。
wireshark需要先启动npf http://ask.wireshark.org/questions/1281/npf-driver-problem-in-windows-7
sc qc npf查询npf是否运行
sc start npf启动npf
我也试过直接wireshark监控模拟器或android-x86的请求,但是看不到,还是需要通过tcpdump。
如果是ssl请求那就更麻烦了,参见http://blog.csdn.net/jasonhwang/article/details/2350723
因此我是切换到http来测试的。
从请求中没看到什么问题(这里又犯错误,问题就在这里,没有仔细比较,所以没看出来)
于是怀疑是不是httpclient有问题,巧的是就有文章说这个问题 http://jackyrong.iteye.com/blog/1228220
另外这个项目更新了android自带的httpclient
https://code.google.com/p/httpclientandroidlib/
于是乎我就切换到httpurlconnection,把我的工具类重写了一遍……
结果,还是一样的问题,OMG,简直要崩溃了,这时脑子也很疲劳了,
一段时间来对Android的牢骚几乎就要爆发了(这个牢骚免不了,日后定一吐为快……)。
就在这时,这篇文章救了我
http://stackoverflow.com/questions/5092561/http-post-request-with-authorization-on-android/5095189#5095189
原来是Android上Basic编码的问题,多了个换行符,
怪不得Host放在Basic64编码之前就不报client sent HTTP/1.1 request without hostname 这个错。
而且我想起来tcpdump日志看起来有点怪,原来是这个问题。
解决方案就是
private String getB64Auth (String login, String pass) { String source=login+":"+pass; String ret="Basic "+Base64.encodeToString(source.getBytes(),Base64.URL_SAFE|Base64.NO_WRAP); return ret; }
测试通过,真是无语啊。
为什么我不是高富帅,
如果我是高富帅,
我就吃苹果去了,
左手ipad,
右手iphone,
膝上托着macbook pro……