获取Google Oauth2 JWT签名

首先获取服务账号密钥文件 google-gce.json

use Google\Auth\OAuth2;

require 'vendor/autoload.php';

function getGoogleJWT($scopes, $jsonKey) {
    $jsonKey = json_decode(file_get_contents($jsonKey), true);
    $config = [
        'audience' => 'https://oauth2.googleapis.com/token',
        'issuer' => $jsonKey['client_email'],
        'scope' => $scopes,
        'signingAlgorithm' => 'RS256',
        'signingKey' => $jsonKey['private_key'],
        'sub' => NULL,
        'tokenCredentialUri' => 'https://oauth2.googleapis.com/token'
    ];
    $auth = new OAuth2($config);
    return $auth->toJWT();
}

$scopes = ['https://www.googleapis.com/auth/drive.readonly'];

echo getGoogleJWT($scopes, 'google-gce.json');

然后用 JWT 签名就可以获取 Access Token 密钥,有效期为一小时

function getAccessToken($jwt) {
    $params = ['grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt];
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'https://oauth2.googleapis.com/token');
    curl_setopt($curl, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
    $data = curl_exec($curl);
    curl_close($curl);
    return $data;
}

$jwt = 'JWT';

echo getAccessToken($jwt);
发布日期:
分类:php

PHP独立使用Illuminate Database数据库组件

1 安装

composer require illuminate/database
composer require illuminate/events
composer require illuminate/container

2 使用

use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;

require 'vendor/autoload.php';

$capsule = new DB;

$capsule->addConnection([
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'test',
    'username'  => 'root',
    'password'  => '123456',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
]);

$capsule->setEventDispatcher(new Dispatcher(new Container));
$capsule->setAsGlobal();
$capsule->bootEloquent();

$data = DB::table('user')->select('*')->get();

var_dump($data);
发布日期:
分类:php

WordPress 禁用 REST

添加以下代码到插件文件里,可以实现:

  1. 已登录用户可以正常使用 wp-json API
  2. 未登录用户禁止使用 wp-json API
/*
 *  disable rest api
 */
function disable_rest_api($access)
{
    if (is_user_logged_in()) {
        return $access;
    } else {
        return new WP_Error('rest_disabled', __('The REST API on this site has been disabled.'), ['status' => rest_authorization_required_code()]);
    }
}

add_filter('rest_authentication_errors', 'disable_rest_api');
发布日期:
分类:php

阿里云刷新CDN缓存

PHP版本的刷新阿里云CDN缓存最小SDK


define('DebugModel', true);
define('AccessKeyId', 'AccessKeyId');
define('AccessKeySecret', 'AccessKeySecret');

/**
 *  刷新网址
 */
function freshURL($urls = [], $type = 'File')
{
    $sign = getSign(['Action' => 'RefreshObjectCaches', 'ObjectPath' => formatURL($urls), 'ObjectType' => $type]);
    $url = 'https://cdn.aliyuncs.com/?' . $sign['url'] . '&Signature=' . $sign['sign'];
    $request = json_decode(httpRequest($url));
    if (isset($request->Code) && $request->Code == 'OK') {
        return true;
    } else {
        if (DebugModel) {
            var_dump($request);
        }
        return false;
    }
}

/**
 *  格式化网址
 */
function formatURL($urls = [])
{
    $urls = array_map(function($v) {
        return str_replace(['http://', 'https://'], ['', ''], $v);
    }, $urls);
    return implode('\n', $urls);
}

/**
 *  获取签名
 */
function getSign($add)
{
    $data = array(
        "Version" => "2018-05-10",
        "SignatureMethod" => "HMAC-SHA1",
        "SignatureNonce" => uniqid(mt_rand(0, 0xffff), true),
        "SignatureVersion" => "1.0",
        "AccessKeyId" => AccessKeyId,
        "Timestamp" => gmdate("Y-m-d\TH:i:s\Z"),
        "Format" => "JSON",
    );
    $data = array_merge($data, $add);
    ksort($data);
    $format = http_build_query($data);
    $signUrl = 'GET&%2F&' . urlencode(str_replace(['+', '*', '%7E'], ['%20', '%2A', '~'], $format));
    $sign = urlencode(base64_encode(hash_hmac('sha1', $signUrl, AccessKeySecret . '&', true)));
    return array('url' => $format, 'sign' => $sign);
}

/**
 *  发起 HTTP 请求
 */
function httpRequest($url)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    $data = curl_exec($curl);
    $error = curl_error($curl);
    curl_close($curl);
    if ($error) {
        return $error;
    } else {
        return $data;
    }
}

function main() {
    freshURL(['https://abc.com/login/', 'https://abc.com/user/12']);
}

main();
发布日期:
分类:php

phpMyAdmin登录MySQL8

MySQL8使用了新的密码验证插件,所以pma不能直接登录,解决办法是创建一个旧验证方式的用户和密码,比如用户www密码123456,然后就可以登录了

CREATE USER 'www'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
GRANT ALL PRIVILEGES ON *.* TO 'www'@'%';
FLUSH PRIVILEGES;
发布日期:
分类:php

阿里云绿网内容安全API

PHP版本:


define('AccessKeyId', 'AccessKeyId');
define('AccessKeySecret', 'AccessKeySecret');

/**
 *  获取签名
 */
function getSign($md5, $date, $rand)
{
    $data = array(
        "x-acs-version" => "2018-05-09",
        "x-acs-signature-nonce" => $rand,
        "x-acs-signature-version" => '1.0',
        "x-acs-signature-method" => "HMAC-SHA1",
    );
    ksort($data);
    $signUrl = '';
    foreach ($data as $k => $v) {
        $signUrl .= $k . ':' . $v . "\n";
    }
    $signUrl = sprintf("POST\napplication/json\n%s\napplication/json\n%s\n%s/green/text/scan", $md5, $date, $signUrl);
    $sign = base64_encode(hash_hmac('sha1', $signUrl, AccessKeySecret, true));
    return $sign;
}

/**
 *  发起 HTTP 请求
 */
function httpRequest($url, $body)
{
    $date = gmdate('D, d M Y H:i:s T');
    $md5 = base64_encode(md5($body, true));
    $rand = md5(rand(10000, 99999) . time());
    $sign = getSign($md5, $date, $rand);
    $header = array(
        'Accept: application/json',
        'Content-Type: application/json',
        'Content-MD5: ' . $md5,
        'Date: ' . $date,
        'x-acs-version: 2018-05-09',
        'x-acs-signature-nonce: ' . $rand,
        'x-acs-signature-version: 1.0',
        'x-acs-signature-method: HMAC-SHA1',
        'Authorization: acs ' . AccessKeyId . ':' . $sign,
    );

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $body);
    $data = curl_exec($curl);
    $error = curl_error($curl);
    curl_close($curl);
    if ($error) {
        return $error;
    } else {
        return $data;
    }
}

/**
 *  内容检测
 */
function greenTextScan($content) {
    $api = 'https://green.cn-beijing.aliyuncs.com/green/text/scan';
    $body = [
        'scenes' => ['antispam'],
        'tasks' => []
    ];
    foreach($content as $k=>$v) {
        $body['tasks'][] = [
            'dataId' => $k,
            'content' => $v
        ];
    }
    return httpRequest($api, json_encode($body));
}

function main()
{
    echo greenTextScan(['需要检测的文本']);
}

main();
发布日期:
分类:php

PHP构建JWT签名

// Google Oauth2.0 JWT
function JWT() {
    $time = time();
    $header = ['alg' => 'RS256', 'typ' => 'JWT'];
    $claims = [
        'iss' => 'app@01.iam.gserviceaccount.com', 
        'scope' => 'https://www.googleapis.com/auth/photoslibrary',
        'aud' => 'https://www.googleapis.com/oauth2/v4/token', 
        'exp' => $time + 3600,
        'iat' => $time
    ];
    $msg = Base64URLEncode(json_encode($header)) . '.' . Base64URLEncode(json_encode($claims));
    $privateKey = "-----BEGIN PRIVATE KEY-----\nKEY\n-----END PRIVATE KEY-----\n";
    $sign = '';
    openssl_sign($msg, $sign, $privateKey, 'SHA256');
    return $msg . '.' . Base64URLEncode($sign);
}

function Base64URLEncode($input) {
    return str_replace('=', '', strtr(base64_encode($input), '+/', '-_'));
}

echo JWT();
发布日期:
分类:php

使用CloudFlare的API自动更新域名DNS解析

CloudFlare的API文档地址

https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"
)

const (
	AuthEmail   = "YOUR_EMAIL"
	AuthKey     = "YOUR_AUTH_KEY"
	ZoneID      = "YOUR_ZONE_ID"
	DNSRecordID = "YOUR_RECORD_ID"
)

func apiRequest(url, data string) ([]byte, error) {

	var request *http.Request
	var err error

	if data == "" {
		request, err = http.NewRequest("GET", url, nil)
	} else {
		request, err = http.NewRequest("PUT", url, strings.NewReader(data))
	}

	if err != nil {
		return nil, err
	}

	request.Header.Add("X-Auth-Email", AuthEmail)
	request.Header.Add("X-Auth-Key", AuthKey)
	request.Header.Add("Content-Type", "application/json")

	client := &http.Client{}
	response, err := client.Do(request)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		return nil, err
	}

	if response.StatusCode == 200 {
		return body, nil
	} else {
		return nil, errors.New(string(body))
	}

}

func getRecord() string {
	url := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%s/dns_records/%s", ZoneID, DNSRecordID)
	r, err := apiRequest(url, "")
	if err != nil {
		return err.Error()
	}
	match := regexp.MustCompile(`"content":"([\d\.]+)"`).FindSubmatch(r)
	if len(match) == 2 {
		return string(match[1])
	}
	return "error 00"
}

func updateRecord(ip string) string {
	url := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%s/dns_records/%s", ZoneID, DNSRecordID)
	r, err := apiRequest(url, fmt.Sprintf(`{"type":"A","name":"share.moguapp.net","content":"%s"}`, ip))
	if err != nil {
		return err.Error()
	}
	if strings.Contains(string(r), `"errors":[]`) {
		return "success"
	}
	return "error 01"
}

func main() {
	u := updateRecord("127.0.0.5")
	fmt.Println(u)
	r := getRecord()
	fmt.Println(r)
}
发布日期:
分类:php

PHP批量重命名

function AutoRenameFolder($dir) {
    foreach (glob($dir . '/*') as $k => $v) {
        if (is_file($v)) {
            rename($v, sprintf('%s/%s.%s', dirname($v), substr(1001 + $k, 1), strtolower(pathinfo($v, PATHINFO_EXTENSION))));
        }
        if (is_dir($v)) {
            AutoRenameFolder($v);
        }
    }
}

function main() {
    $path = __DIR__;
    AutoRenameFolder($path);
}

main();
发布日期:
分类:php

PHP获取所有汉字的Unicode编码

$start = hexdec('4e00');
$end = hexdec('9fa5');

$s = [];

while(True) {
    $k = dechex($start);
    if ($start > $end) {
        break;
    }
    $s[] = $k . ' ' . json_decode('["\u'.$k.'"]')[0];
    $start++;
}

file_put_contents('u.txt', implode("\n", $s));
发布日期:
分类:php