首頁  >  問答  >  主體

laravel - guzzle post 請求 登入 api, response回傳 404,錯在哪裡呢?

筆者的guzzle程式碼是這樣的:

use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\RequestException;

class getSegmentfaultArticle extends Command
{
    protected $signature = 'segmentfault:artical';

    protected $description = '获取 Segmentfault 文章的信息';

    protected $client;
    protected $crawler;

    protected $user = [];

    protected $login_page_url = '/user/login';
    protected $login_url = '/api/user/login?_=775250c435a29c7a335a11ab2f641423';
    protected $sessionId = 'web2~04u8m9qfpnt6abl6ljuqae59l0';
    protected $my_seg_home_url = '/u/greenlightt/articles';

    public function __construct(Crawler $crawler) {
        parent::__construct();

        $this->client  = new Client([
            'base_uri' => 'https://segmentfault.com',
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0',
                 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
            ],
            'cookies' => true,
            'http_errors' => true,
        ]);
        $this->crawler = $crawler;

        // 获取登录名及密码
        $this->user['email'] = config('services.segmentfault.email');
        $this->user['password'] = config('services.segmentfault.password');
    }

    public function handle() {
        // 较验 auth
        if (is_null($this->user['email']) || is_null($this->user['password'])) {
            $this->error('请在 .env 文件填写 Segmentfault 账号及密码');
            return;
        }
        // 登录获取 cookies
        $this->client->request('GET', $this->login_page_url);
        $this->updateCookies();
        
        $response = $this->client->request('POST', $this->login_url,
            array(
                'form_params' => [
                    'username' => $this->user['email'],
                    'password' => $this->user['password'],
                ],
                'headers' => [
                    'Referer' => '/user/login'
                ]
            )
        );
    }
    
    /*                                                                          
     * 修改 Cookie 中的 PHPSESSID 值                                            
     */                                                                         
     protected function updateCookies() {                                        
        $config = $this->client->getConfig();                                   
        $cookie = $config['cookies']->toArray()[0];                             
        $cookie['Value'] = $this->sessionId;                                    
                                                                                    
        $config['cookies']->setCookie(                                          
           new SetCookie($cookie)                                              
        );                                                                      
     }   
}

結果報錯如下:

#
女神的闺蜜爱上我女神的闺蜜爱上我2708 天前1569

全部回覆(1)我來回復

  • 三叔

    三叔2017-06-13 09:26:33

    login?_=後面的token不是固定的,你要手動從window.SF.token裡面取出來。

    另外請求的時候cookie也沒有帶,所以SF判斷你是非法請求,404.

    鑑於樓主認為_後面的token屬於隨意的字段,下面來驗證一下,以下給出運行正確的代碼(沒有用laravel)

    因為SF的token有混淆字段,php應該不能簡單的解析出來,所以直接用shell_exe呼叫node來取得token。

    <?php
    require_once __DIR__ . '/vendor/autoload.php';
    use GuzzleHttp\Client;
    use GuzzleHttp\Cookie\CookieJar;
    use GuzzleHttp\Exception\RequestException;
    
    $login_page_url = '/user/login';
    $login_url = '/api/user/login?_=';
    
    $client = new Client([
        'base_uri' => 'https://segmentfault.com',
        'headers' => [
            'User-Agent' => 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0',
            'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
        ],
        'cookies' => true,
        'http_errors' => true,
    ]);
    
    $user = [
        'email' => '1@qq.com',
        'password' => '2333',
    ];
    
    $response = $client->request('GET', $login_page_url);
    $body = (string) $response->getBody();
    preg_match_all('/<script[\s\S]*?<\/script>/', $body, $matches);
    $script = null;
    foreach ($matches[0] as $value) {
        if (strpos($value, 'w.SF.token') !== false) {
            $script = $value;
            break;
        }
    }
    $script = str_replace(['<script>', '</script>'], '', $script);
    file_put_contents(__DIR__ . '/test.js', 'var window = {};' . "\r\n" . $script . "\r\n" . 'console.log(window.SF.token);');
    $token = shell_exec('/usr/local/bin/node test.js' . " 2>&1");
    $token = trim($token);
    
    // get cookie
    $config = $client->getConfig();
    $cookie = $config['cookies']->toArray()[0];
    
    $cookieJar = CookieJar::fromArray([
        $cookie['Name'] => $cookie['Value'],
    ], $cookie['Domain']);
    
    try {
        $response = $client->request('POST', $login_url . $token,
            array(
                'cookies' => $cookieJar,
                'form_params' => [
                    'username' => $user['email'],
                    'password' => $user['password'],
                ],
                'headers' => [
                    'Referer' => '/user/login',
                ],
            )
        );
    } catch (RequestException $e) {
        echo $e->getMessage();
    }
    
    echo (string) $response->getBody();
    

    輸出結果:

    回覆
    0
  • 取消回覆