【PHP】Chatwork 通知用の Proxy API を作ってみる

こんにちは。
とある案件でお客様 Zabbix サーバから Chatwork にアラートを通知する必要がございました。
通常であれば、Chatwork の API を叩くスクリプトを用意すればよいのですが、お客様管理の Zabbix サーバですので、セキュリティ的な要因から Chatwork の APIトークンを使うことができません。
ついては、自社サーバに API トークンを配置した Proxy API を用意してみます。

コード

前回は cURL関数 を使ったので、今回は file_get_contents を使ってみます。

<?php
/*
$api_key = "";
$password = "";
*/
include('../../.env');

// リクエストの body を取得
$json = file_get_contents("php://input");
$contents = json_decode($json, true);

// POST されたデータが正しいか判定
if (isset($contents['cw_endpoint']) && is_numeric($contents['cw_endpoint']) && isset($contents['message']) && isset($contents['auth_id'])){
    $cw_endpoint = $contents['cw_endpoint'];
    $message = $contents['message'];
    $auth_id = $contents['auth_id'];
    } else {
        echo "Bad Request.\n";
        http_response_code(400);
        exit();
    }

// 認証情報が正しいか判定 
if ($password !== $auth_id){
    echo "Forbidden.\n";
    http_response_code(403);
    exit();
}

// HTTP ヘッダ
$header = array(
        "Content-Type: application/x-www-form-urlencoded",
        "X-ChatWorkToken: $api_key",
);

// HTTP リクエスト
$context = array(
        "http" => array(
                "method"  => "POST",
                "header"  => implode("\r\n", $header),
                "content" => http_build_query(array(
                    'body' => $message,
                )),
        )
);

// ChatWork API にリクエスト送信
$scc = stream_context_create($context);
$url = "https://api.chatwork.com/v1/rooms/$cw_endpoint/messages";
$res = file_get_contents($url, false, $scc);
echo $res . "\n";

APIトークン と 認証情報は外部より参照できないように、ドキュメントルートより上位に配置しておきます。

<?php
$api_key = "";
$password = "";
?>

使用例

POSTメソッド で HTTPリクエストを投げれば OK です。

・パラメータ
cw_endpoint:通知するルームID
message:通知内容
auth_id:xxxxxx

・curl の例

curl -X POST -d '{"cw_endpoint":"xxxxxxx", "message":"これはテスト", "auth_id":"xxxxxxxxxxxxxx"}' https://xxx.xxx.xxx.xxx/api/proxy.php

【PHP】Cookie を保存/送信して認証が必要なページをスクレイピングしてみる【curl】

こんにちは。
先日、CakePHP で作られた外部システムからデータを引っ張ってくる必要がありました。
ただ、データ取得用の API 等が用意されているわけでもなかったため、curl で叩いてデータを引っ張ってくることにします。

最初のログインページの認証後に Cookie を維持する必要があったので、その処理を PHP で実装してみます。

コード

PHPには cURL 関数が用意されているのでありがたく使わせて頂きます。

<?php

class PHPCurl {
    
    private $getCookieUrl;
    private $targetUrl;
    private $username;
    private $password;
    private $saveCookieFile;

    /**
     * コンストラクタ
     * 
     * @param string $getCookieUrl Cookie取得用のURL
     * @param string $targetUrl    CurlのターゲットURL
     * @param string $username     ログイン情報(ユーザ名)
     * @param string $password     ログイン情報(パスワード)
     */
    public function __construct($getCookieUrl, $targetUrl, $username, $password){
        $this->getCookieUrl = $getCookieUrl;
        $this->targetUrl = $targetUrl;
        $this->username = $username;
        $this->password = $password;
        $this->saveCookieFile = stream_get_meta_data($fp = tmpfile());
    }

    /**
     * Cookie取得用のメソッド
     */
    public function getCookie(){
        $data = array(
            'data[User][username]' => $this->username,
            'data[User][password]' => $this->password,
        );

        $curl = curl_init($this->getCookieUrl);
        curl_setopt($curl, CURLOPT_POST, TRUE);
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));

        curl_setopt($curl, CURLOPT_COOKIEJAR, $this->saveCookieFile['uri']);
        curl_setopt($curl, CURLOPT_COOKIEFILE, $this->saveCookieFile['uri']);
        curl_exec($curl);
        curl_close($curl);
    }

    /**
     * コンテンツ取得用のメソッド
     * 
     * @return string HTMLコンテンツ
     */
    public function getContent(){
        $curl = curl_init($this->targetUrl);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_COOKIEFILE, $this->saveCookieFile['uri']);
        $result = curl_exec($curl);
        curl_close($curl);

        return $result;
    }
}

$curlInfo = new PHPCurl('https://xxxxxx.xxx/login', 'https://xxxxxx.xxx/target', 'finger', 'ease');

$curlInfo->getCookie();
$content = $curlInfo->getContent();

echo $content;

※ POST の bodyデータ は適宜置き換えてくださいね。
あとは必要なデータをパースするだけです。

おまけ

curl だったら下記 2 行だけなんですよね。

curl -c ./cookie.txt -d "data[User][username]=finger" -d "data[User][password]=ease" "https://xxxxxx.xxx/login"
curl -b ./cookie.txt "https://xxxxxx.xxx/target"