Home  >  Q&A  >  body text

laravel - guzzle post request login api, response returns 404, what's wrong?

The author's guzzle code is like this:

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)                                              
        );                                                                      
     }   
}

The result error is as follows:

女神的闺蜜爱上我女神的闺蜜爱上我2708 days ago1567

reply all(1)I'll reply

  • 三叔

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

    login?_=The following token is not fixed, you have to manually take it out from window.SF.token.

    In addition, the cookie is not included when requesting, so SF judges that you are making an illegal request, 404.

    Since the author believes that the token after _ is an arbitrary field, let’s verify it. The following is the code that runs correctly (without laravel)

    Because the SF token has obfuscated fields, PHP should not be able to simply parse it out, so we directly use shell_exe to call node to obtain the 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();
    

    Output result:

    reply
    0
  • Cancelreply