首頁 後端開發 php教程 php curl模擬單一登入 PHP實作JS加密函數

php curl模擬單一登入 PHP實作JS加密函數

Mar 30, 2017 am 09:58 AM

php curl模拟单点登录

这里说的模拟登录,也就是抓站的基础部分, 模拟登录,获取登录后的状态,然后模拟人的访问流程,获取访问结果,分析保存之……

首先,抓站利器,httpwatch,也可以用firefox下的firebug或者chrome下自带的开发者工具,其实我原来一直都是用firefox或者chrome的,但是听说httpwatch很好,就拿来试用一下,结果用的还真是很舒服,不错。其次就是Snoopy.class.php,我用PHP,这个PHP类真是好用到极致了,用来抓站so easy。但是这个类用来抓一般的基于http的站是没问题的,如果要是https的就麻烦了,这个类在抓https的站时,采用的不是php本身的curl了,使用的是Linux/Unix下的原生CURL,所以这个类在windows下用着很麻烦,需要自己装一个windows下能用的curl,并且配置好环境。在sae下直接就是不行的了,如果是用Linux/Unix的话,就很方便了~~指定好curl的路径就可以了。我也有一个https的模拟登录签到的脚本,使用的是php的curl,没有使用Snoopy。

由于新浪采用了单点登录,所以一般的登录方法是不行的了,不是直接构造用户名密码POST到一个login action页面完事。先使用httpwatch抓取一下登录的流程吧。

php curl模擬單一登入 PHP實作JS加密函數

整个登录的流程是这样的:

1)、输入用户名密码,点击登录(在用户名输入完onblur的时候会有一个自动检测邮箱合法性的过程,我们模拟时候可以忽略)。

2)、访问一个页面,获取到几个特殊的值,包括servertime,pcid,nonce,这几个值用来干什么的呢,我们再分析一下JS就可以发现了,是用来加密用户名和密码的。

3)、将加密后的用户名、密码以及一些其它信息,提交到SSO的login去申请ticket。(ticket就是SSO登录中用到的票据啦)

4)、认证成功,访问几个其它站点种下Cookie,(相当于把票给人家看门的看看,告诉他我有访问你内部的权限了)。

5)、返回爱问首页。

主要需要做的就是如何实现用户名和密码的加密,因为客户端是用js实现的,但是我们是写在脚本里的,无法调用js,所以,只能通过PHP来模拟一下js加密的实现过程了。

新浪的JS采用的应该是Dean Edwards的packer算法,其实不用管什么算来,拿来之后在Google一下js解密,放进去就是还原后的代码了。

在还原后,大概看了看,就明白了一个流程,用户名和密码都分别进行了加密,最重要的部分,就是加密的这块了。用户名用base64加密,密码用hex_sha1加密后加密再加盐再加密。我们现在需要做的,就是用PHP来实现这两个加密方法。(其实通过分析后发现,用户名采用base64加密,并未加盐,所以每次加密后的数据都是一样的,我们也没必要去实现base64的加密方法了。)

//用户名加密
d["su"] = sinaSSOEncoder.base64.encode(bi(a));
//密码加密
b = sinaSSOEncoder.hex_sha1("" + sinaSSOEncoder.hex_sha1(sinaSSOEncoder.hex_sha1(b)) + 
k.servertime + k.nonce)
var sinaSSOEncoder = sinaSSOEncoder || {}; (function() {
    var n = 0;
    var o = 8;
    this.hex_sha1 = function(s) {
        return A(p(z(s), s.length * o))
    };
    var p = function(x, f) {
        x[f >> 5] |= 0x80 << (24 - f % 32);
        x[((f + 64 >> 9) << 4) + 15] = f;
        var w = Array(80);
        var a = 1732584193;
        var b = -271733879;
        var c = -1732584194;
        var d = 271733878;
        var e = -1009589776;
        for (var i = 0; i < x.length; i += 16) {
            var g = a;
            var h = b;
            var k = c;
            var l = d;
            var m = e;
            for (var j = 0; j < 80; j++) {
                if (j < 16) w[j] = x[i + j];
                else w[j] = v(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
                var t = u(u(v(a, 5), q(j, b, c, d)), u(u(e, w[j]), r(j)));
                e = d;
                d = c;
                c = v(b, 30);
                b = a;
                a = t
            }
            a = u(a, g);
            b = u(b, h);
            c = u(c, k);
            d = u(d, l);
            e = u(e, m)
        }
        return Array(a, b, c, d, e)
    };
    var q = function(t, b, c, d) {
        if (t < 20) return (b & c) | ((~b) & d);
        if (t < 40) return b ^ c ^ d;
        if (t < 60) return (b & c) | (b & d) | (c & d);
        return b ^ c ^ d
    };
    var r = function(t) {
return (t < 20) ? 1518500249: (t < 40) ? 1859775393:(t < 60) ? -1894007588 : -899497514
    }
    var u = function(x, y) {
        var a = (x & 0xFFFF) + (y & 0xFFFF);
        var b = (x >> 16) + (y >> 16) + (a >> 16);
        return (b << 16) | (a & 0xFFFF)
    };
    var v = function(a, b) {
        return (a << b) | (a >>> (32 - b))
    };
    var z = function(a) {
        var b = Array();
        var c = (1 << o) - 1;
        for (var i = 0; i < a.length * o; i += o) b[i >> 5] |= 
        (a.charCodeAt(i / o) & c) << (24 - i % 32);
        return b
    };
    var A = function(a) {
        var b = n ? "0123456789ABCDEF": "0123456789abcdef";
        var c = "";
        for (var i = 0; i < a.length * 4; i++) {
 c += b.charAt((a[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + b.charAt((a[i >> 2] >> 
 ((3 - i % 4) * 8)) & 0xF)
        }
        return c
    };
    this.base64 = {
        encode: function(a) {
            a = "" + a;
            if (a == "") return "";
            var b = &#39;&#39;;
            var c,
            chr2,
            chr3 = &#39;&#39;;
            var d,
            enc2,
            enc3,
            enc4 = &#39;&#39;;
            var i = 0;
            do {
                c = a.charCodeAt(i++);
                chr2 = a.charCodeAt(i++);
                chr3 = a.charCodeAt(i++);
                d = c >> 2;
                enc2 = ((c & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64
                } else if (isNaN(chr3)) {
                    enc4 = 64
                }
                b = b + this._keys.charAt(d) + this._keys.charAt(enc2) 
                + this._keys.charAt(enc3) + this._keys.charAt(enc4);
                c = chr2 = chr3 = &#39;&#39;;
                d = enc2 = enc3 = enc4 = &#39;&#39;
            }
            while (i < a.length);
            return b
        },
        _keys: &#39;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=&#39;
    }
}).call(sinaSSOEncoder);
登入後複製

后通过努力,把这个JS的对象封装成了一个PHP的类,具体的代码我就不贴出来了,好歹我也是浪人,自己就不危害自己啦,大家自己研究下,很简单的。

其中最难的亮点就是js中的 >>> 无符号右移 和 charCodeAt(i),PHP中没有这两个对应的实现,需要自己来写。

我把这两个难点贴出来供大家参考吧,其实这两个算法我也是参考的别人的,中间发现有一个算法是错的,浪费了我好长时间。。。。。

/**
 * 无符号32位右移 ;模拟实现JS的>>>,无符号右移。实现原理,化为二进制,先右移,后补零。
 * @param mixed $x 要进行操作的数字,如果是字符串,必须是十进制形式
 * @param string $bits 右移位数
 * @return mixed 结果,如果超出整型范围将返回浮点数
 */
function shr32($x, $bits){
    // 位移量超出范围的两种情况
    if($bits <= 0){
        return $x;
    }
    if($bits >= 32){
        return 0;
    }
    //转换成代表二进制数字的字符串
    $bin = decbin($x);
    $l = strlen($bin);
    //字符串长度超出则截取底32位,长度不够,则填充高位为0到32位
    if($l > 32){
        $bin = substr($bin, $l - 32, 32);
    }elseif($l < 32){
        $bin = str_pad($bin, 32, &#39;0&#39;, STR_PAD_LEFT);
    }
    //取出要移动的位数,并在左边填充0
    return bindec(str_pad(substr($bin, 0, 32 - $bits), 32, &#39;0&#39;, STR_PAD_LEFT));
}
//模拟实现JS的chaCodeAt()
function getUnicodeFromOneUTF8($word) {
  //获取其字符的内部数组表示,所以本文件应用utf-8编码!
  if (is_array( $word))
    $arr = $word;
  else
    $arr = str_split($word);
  //此时,$arr应类似array(228, 189, 160)
  //定义一个空字符串存储
  $bin_str = &#39;&#39;;
  //转成数字再转成二进制字符串,最后联合起来。
  foreach ($arr as $value)
    $bin_str .= decbin(ord($value));
  //此时,$bin_str应类似111001001011110110100000,如果是汉字"你"
  //正则截取
  $bin_str = preg_replace(&#39;/^.{4}(.{4}).{2}(.{6}).{2}(.{6})$/&#39;,&#39;$1$2$3&#39;, $bin_str);
  //此时, $bin_str应类似0100111101100000,如果是汉字"你"
  return bindec($bin_str); //返回类似20320,汉字"你"
  //return dechex(bindec($bin_str)); //如想返回十六进制4f60,用这句
}
登入後複製

是这两个算法了,还有一个无符号左移的,这里没用到,也贴下来,记录。

例子:

<?php
/**
 * 无符号32位左移
 * @param mixed $x 要进行操作的数字,如果是字符串,必须是十进制形式
 * @param string $bits 左移位数
 * @return mixed 结果,如果超出整型范围将返回浮点数
 */
function shl32 ($x, $bits){
    // 位移量超出范围的两种情况
    if($bits <= 0){
        return $x;
    }
    if($bits >= 32){
        return 0;
    }
    //转换成代表二进制数字的字符串
    $bin = decbin($x);
    $l = strlen($bin);
    //字符串长度超出则截取底32位,长度不够,则填充高位为0到32位
    if($l > 32){
        $bin = substr($bin, $l - 32, 32);
    }elseif($l < 32){
        $bin = str_pad($bin, 32, &#39;0&#39;, STR_PAD_LEFT);
    }
    //取出要移动的位数,并在右边填充0
    return bindec(str_pad(substr($bin, $bits), 32, &#39;0&#39;, STR_PAD_RIGHT));
}
登入後複製

有一个需要注意的是PHP和JS中的三元判断符的使用,PHP中是从右向左,JS中是从左向右。所以这个使用if…else…替代比较好。

还有一个就是JS的数组和PHP的数组问题,自己想办法解决吧。

解决了这个,剩下就没难题了,跟普通的抓站一样了。

构造好需要的POST数据,提交。

然后,获取返回的ticket,然后再模拟访问其它几个页面,把ticket给人家看门的看一眼,下次带Cookie直接访问里面就好了。

以上就是php curl模拟单点登录 PHP实现JS加密函数 的内容,更多相关内容请关注PHP中文网(www.php.cn)!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1670
14
CakePHP 教程
1428
52
Laravel 教程
1329
25
PHP教程
1274
29
C# 教程
1256
24
PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

PHP與Python:了解差異 PHP與Python:了解差異 Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

PHP行動:現實世界中的示例和應用程序 PHP行動:現實世界中的示例和應用程序 Apr 14, 2025 am 12:19 AM

PHP在電子商務、內容管理系統和API開發中廣泛應用。 1)電子商務:用於購物車功能和支付處理。 2)內容管理系統:用於動態內容生成和用戶管理。 3)API開發:用於RESTfulAPI開發和API安全性。通過性能優化和最佳實踐,PHP應用的效率和可維護性得以提升。

PHP的持久相關性:它還活著嗎? PHP的持久相關性:它還活著嗎? Apr 14, 2025 am 12:12 AM

PHP仍然具有活力,其在現代編程領域中依然佔據重要地位。 1)PHP的簡單易學和強大社區支持使其在Web開發中廣泛應用;2)其靈活性和穩定性使其在處理Web表單、數據庫操作和文件處理等方面表現出色;3)PHP不斷進化和優化,適用於初學者和經驗豐富的開發者。

PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

PHP和Python:代碼示例和比較 PHP和Python:代碼示例和比較 Apr 15, 2025 am 12:07 AM

PHP和Python各有優劣,選擇取決於項目需求和個人偏好。 1.PHP適合快速開發和維護大型Web應用。 2.Python在數據科學和機器學習領域佔據主導地位。

See all articles