概述:
小伙伴说遇到了一个问题,有个客户ACG本地Web认证成功之后无法跳转到设置的成功跳转页面,看了实验室成功的抓包发现不是通过HTTP 302 跳转的,不知道具体什么跳转原理也无从排查,我看了下正常跳转的报文交互,以及从Wireshark下看HTTP传输的JS页面源码,发现还是挺有趣的。
先看结论:
ACG在本地web认证成功之后不是通过http 302、Location header
方式执行页面跳转。
ACG在进行认证页面跳转的时候发送302 Location
,Location
的url携带了参数:weburl
,通过该参数携带了认证成功之后跳转的地址,之后通过js脚本在浏览器侧判断是否认证成功、并执行跳转。
所以想要跳转成功:
1. ACG给PC 302 location
重定向的url中需要携带weburl
这个参数,携带的地址也得正确
2. PC的浏览器可以正常执行JS
脚本。
可以自己新建一个html文件用浏览器打开测试下,是否可以正常执行JS的跳转:
<!DOCTYPE html>
<html>
<body>
<form >
<input type="button" value="JS window open跳转" onclick="javascript:window.open('http://www.baidu.com')">
</form>
<p>点击submit,打开baidu</p>
</body>
</html>
下面部分不感兴趣可以不用看了。
页面代码中相关
点击认证时候的ajax部分
执行跳转页面的function
获取跳转页面的function
获取跳转页面url的function
function get_url_special_string(name){
var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null)return unescape(r[2]); return null;
}
这段代码百度上很容易找到解释:链接。甚至代码都一毛一样(除了函数名字不一样),一个字都没改,ctrl c、ctrl v
大法赛高。
该函数作用是获取 http
请求的url
中?
后边的部分,也就是url
中携带的参数。
整个认证过程中http
头部携带的参数就只有一个:weburl
。
GET /portal/local/index.html?weburl=http%3A%2F%2F1.1.1.2 HTTP/1.1
最开始我以为这个weburl
作用是表明ACG认证页面是从哪个原始地址跳转过来的,但是看代码似乎并不是,而是表明认证成功之后跳转的页面。
想想也是,ACG全程在url参数中携带认证之前的url地址干啥,认证之后又不会给跳转回去.....,主要这个抓包里认证前访问的地址刚好也是1.1.1.2,跳转页面也是1.1.1.2,容易让人误解。
执行跳转页面的function
function btn_win_open(url){
if(url !='null'){
$('#redirect').unbind();
$('#redirect').click(function(){window.open(url)});
$("#redirect").trigger("click");
}
}
传入一个url,通过window.open(url)
在浏览器中打开这个url,也就是所谓的页面跳转。
点击认证时候的ajax部分
$.ajax({
url: '../../portal.cgi',
type: 'POST',
data: 'username=' + encodeURI(username) + '&password=' + password +'&language='+language+ '&submit=submit'
async: false,
timeout: 30000,
success: function(data) {
var weburl = decodeURIComponent(get_url_special_string("weburl")),logincookie= '';
if(weburl){
btn_win_open(weburl);
if(weburl){
btn_win_open(weburl);
}
向/portal.cgi
提交认证的账号密码,中间省略一堆内容,如果认证成功(success),执行一个函数,在函数中存在一个判断条件:
if(weburl)
也就是weburl
如果存在,执行 btn_win_open
函数,也就是跳转页面的函数,完成认证成功后跳转到页面的功能。