postman模拟带验证码登录问题

今天研究一个问题,就是用postman模拟网站的带验证码登录。本文把这一过程做个流水账式记录。

我最初的设想是这样:

http是一种无连接无状态协议,请求相应完毕连接即断开,由于其无状态,重复请求的身份认证一般通过session、cookie、url重写这几种方式来实现,我们的网站登录采用第三方库生成图片验证码,同时把验证码值存入session中。那么我可以先用浏览器debug登录请求,获取jsessionid的cookie写入postman中,然后拼装登录json进行登录。

实际结果:

登录失败,验证码错误。

猜测:是不是跟user-agent有关?

验证:postman添加了跟chrome一样的user-agent,依然无效。

猜测:header里面发现了Connection:keepAlive,这是什么?是不是连接不关闭了导致外部请求即使有jsessionid也不能访问这个session?

验证:keepalive是新版本http中加入的功能,作用是在服务器和浏览器都支持的前提下让连接不关闭,这样就避免了频繁重建连接带来的效率问题。怎么才是支持呢?浏览器如果支持,会在请求头添加这个Connection:keepAlive,服务器如果支持,在接到之后会在响应头部也添加这一字段。拿百度来验证,请求和响应都带有这个字段,明显百度是支持这个功能的,但是我们的服务器并不支持。所以这不是原因。

猜测:是不是传的cookie参数无效,两次访问属于不同session?

验证:确实不一样。

插播广告:我想在服务端看看request的header都是些什么玩意,就在controller里面加了个httprequest参数,我觉得Spring框架会自动注入,就像httpSession一样,结果程序挂了。后来发现httpRequest是apache包下的,这个并不能自动注入,得改成HttpServletRequest才可以。

广告播完了,上面那个不一样的原因也出来了。就是我在postman里面写的headercookie被覆盖掉了。。其他属性都正常传过去,只有cookie,也就是jsessionid被覆盖了。原因如下:

postman是基于浏览器的插件,发出的请求都是通过调用ajax/xmlhttprequest的方式,必然受到浏览器的安全限制:

  1. 首先 XMLHttpRequest 出于安全考虑是不支持跨域的, 这一点postman已经向浏览器声明了需要跨域的权限

postman模拟带验证码登录问题_第1张图片

  1. 其次,部分header同样由于安全原因,是无法在浏览器中set的,受制于浏览器的用户特性

postman模拟带验证码登录问题_第2张图片

具体哪些header不能set,要看XMLHttpRequest.js的源码实现

var forbiddenRequestHeaders = [
    "accept-charset",
    "accept-encoding",
    "access-control-request-headers",
    "access-control-request-method",
    "connection",
    "content-length",
    "content-transfer-encoding",
    "cookie",
    "cookie2",
    "date",
    "expect",
    "host",
    "keep-alive",
    "origin",
    "referer",
    "te",
    "trailer",
    "transfer-encoding",
    "upgrade",
    "via"   ];

经验证,以上属性在postman中设置全部无效。解决方案是打开postman的拦截器,之后就可以正常添加cookie了。

你可能感兴趣的:(java)