今天帮学院写了个小网站,根据要求要用数字沈航帐号登录,还没办法与数字沈航的工作人员交流,无奈想出了个使用curl这个解决方案。
数字沈航(http://i.sau.edu.cn)是我们学校全部数字服务的入口,之前有朋友要写爬虫也问过我如何登录数字沈航,我当时也没多想,简单说了下最通用的方案(直接POST表单),并没有尝试,今天做的时候发现原来有个csrf_token验证。
在这里记录一下解决的方案:
1、首先就是先审查元素看一下表单的代码,查看有哪些元素。
2、发现元素不少,于是提交一次看Request内容。
3、这里看到了有个lt字段,是一段随机码(猜测是csrf_token),并且密码也是md5加密过的了。(这里是演示,所以输入的是假密码,所以不用再试了...)
4、于是我们只要很简单的构造表单,至于lt字段,我的做法是,先抓一遍页面,然后正则匹配到这段字符串,然后用就用这个提交,果然奏效了。
5、最后根据返回的字符,就能判断是否登录成功了。(爬虫当然也可以这么做)
以下是php代码:function i_sau_validate($username, $password) {
$login_url = 'http://cas.sau.edu.cn:8080/cas/login';
$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 10000);
$content = curl_exec($ch);
$csrf_token_matches = [];
$csrf_token = '';
preg_match('//i' ,$content, $csrf_token_matches);
if($csrf_token_matches)
$csrf_token = $csrf_token_matches[1];
$login_url = 'http://cas.sau.edu.cn:8080/cas/login';
$password = md5($password);
$post_fields = "serviceName=0&loginErrCnt=0&username=$username&password=$password<=$csrf_token";
$ch = curl_init($login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 10000);
$content = curl_exec($ch);
curl_close($ch);
if(!$content) {
return "timeout";
} else if(preg_match('/mistake_notice/i', $content)){
return 'denied';
} else if(preg_match('/window\.location="cas\.sau\.edu\.cn:8080\/cas"/i', $content)) {
return "ok";
} else {
return "unknow";
}
}