叶测试 发布的文章

JS美化json数据

项目日志列表中需对报错数据详细信息进行查阅,需对json格式进行美化,如图:

145.png

样式代码:

<style>
    .key{
        color: red;
    }
    .string{
        color: green;
    }
    .layui-layer-content{
        padding: 10px;
    }
</style>

layer弹窗展示数据:

table.on('tool(table-toolbar)', function(obj){
    var data = obj.data;
    var str = prettyFormat(data.data);
    if(obj.event === 'detail'){
        layer.open({
            type: 1,
            title: '数据详情',
            skin: 'layui-layer-rim', //加上边框
            area: ['600px', '500px'], //宽高
            content: str
        });
    }
});

//json格式美化
function prettyFormat(json) {
    try {
        // 设置缩进为2个空格
        //str = JSON.stringify(JSON.parse(str), null, 2);
        str = JSON.stringify(json, null, 2);
        str = str
            .replace(/&/g, '&')
            .replace(/</g, '<')
            .replace(/>/g, '>');
        str = str.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
            var cls = 'number';
            if (/^"/.test(match)) {
                if (/:$/.test(match)) {
                    cls = 'key';
                } else {
                    cls = 'string';
                }
            } else if (/true|false/.test(match)) {
                cls = 'boolean';
            } else if (/null/.test(match)) {
                cls = 'null';
            }
            return '<span class="' + cls + '">' + match + '</span>';
        });
        return "<pre>"+str+"</pre>"
    } catch (e) {
        alert("异常信息:" + e);
    }
}

curl函数post、get数据速度非常慢的处理办法

实际项目中使用curl进行数据请求,访问速度异常的慢,基本上要5s以上的时间,最终通过以下设置得以解决。

//curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); //强制协议为1.0
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Expect:']); //头部要送出'Expect: '
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); //强制使用IPV4协议解析域名

2048位RSA非对称密钥加密

快速获取RSA密钥对:http://www.metools.info/code/c80.html

示例代码:

<?php

class App extends BaseController
{
    private $syncUrl = 'https://www.xxx.com/api/event/sync';

    private $privateKey; //私钥
    private $publicKey; //其他系统公钥

    private $keyLen = 2048;
    private $appId = 1;
    private $identity = 'hello';


    public function __construct()
    {
        $this->privateKey = file_get_contents((app()->getRootPath() . 'private_key.pam'));
        $this->publicKey = file_get_contents((app()->getRootPath() . 'cert_public.pam'));
    }

    //新版接口
    public function test($uid='', $token='')
    {
        //请求tokenIsValidSync判断请求是否合法
        $data = [
            'app_id'=>$this->appId,
            'app_identity'=>$this->identity,
            'timestamp'=>time(),
            'rnd_str'=>uniqid(),
            'event'=>'tokenIsValidSync',
            'uid'=>$uid,
            'token'=>$token,
            'profile'=>1
        ];
        $enData = $this->privateEncrypt($data);

        $postData = [
            'app_id'=>$this->appId,
            'data'=>$enData
        ];

        $ret = HttpService::postRequest($this->syncUrl, $postData);
        $info = json_decode($ret, true);
        $decryptData = $this->publicDecrypt($info['data']);
        $userInfo = json_decode($decryptData, true);
    }

    /**
     * 私钥加密
     *
     * @param string|array $data 待加密数据
     * @return string 已加密的内容
     */
    public function privateEncrypt($data)
    {
        //如果是数组,则转换为JSON字符串
        if (is_array($data)) $data = json_encode($data);
        if (!is_string($data)) {
            return null;
        }

        $encrypted = '';
        //采用默认的 OPENSSL_PKCS1_PADDING 填充格式,数据长度必须小于密钥长度 - 11
        $part_len = $this->keyLen / 8 - 11;
        $parts = str_split($data, $part_len);

        foreach ($parts as $part) {
            $encrypted_temp = '';
            openssl_private_encrypt($part, $encrypted_temp, $this->privateKey);
            $encrypted .= $encrypted_temp;
        }

        return base64_encode($encrypted);
    }

    /**
     * 公钥解密
     *
     * @param string $encrypted 待解密内容
     * @return string 已解密内容
     */
    public function publicDecrypt($encrypted = '')
    {
        if (!is_string($encrypted)) {
            return null;
        }

        $decrypted = '';
        $part_len = $this->keyLen / 8;
        $base64_decoded = base64_decode($encrypted);
        $parts = str_split($base64_decoded, $part_len);

        foreach ($parts as $part) {
            $decrypted_temp = '';
            openssl_public_decrypt($part, $decrypted_temp, $this->publicKey);
            $decrypted .= $decrypted_temp;
        }

        return $decrypted;
    }


}

登录页AES加密提交帐号密码信息

前端参考代码如下,后台PHP代码参考上篇文章。

其中,key为后台动态生成的16位随机字符串并写入cache中,登录验证verify方法中需先判断此key的缓存是否存在。

引入相关js:

<script src="{__PLUG_PATH}crypto-js/core.js"></script>
<script src="{__PLUG_PATH}crypto-js/cipher-core.js"></script>
<script src="{__PLUG_PATH}crypto-js/aes.js"></script>
<script src="{__PLUG_PATH}crypto-js/mode-ecb.js"></script>
<script src="{__PLUG_PATH}crypto-js/enc-base64.js"></script>

登录操作:

form.on('submit(login)', function(obj){
    let data = obj.field;
    let key = CryptoJS.enc.Utf8.parse(data.key);
    let password = CryptoJS.enc.Utf8.parse(data.password);
    let encrypted = CryptoJS.AES.encrypt(password, key, {iv:key, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7});
    var hexStr = encrypted.ciphertext.toString();
    var oldHexStr = CryptoJS.enc.Hex.parse(hexStr);
    let base64 = CryptoJS.enc.Base64.stringify(oldHexStr);
    data.password = base64;

    $.ajax({
        url: "{:url('verify')}"
        ,data: data
        ,method: "POST"
        ,dataType: "json"
        ,success: function(res){
            if(res.code == 200){
                layer.msg('登录成功', {time: 1000}, function(){
                    location.href = "{:url('index/index')}";
                });
            }else{
                //重置验证码
                $('#vercode').trigger('click');
                $('#code').val('');
                layer.msg(res.msg, {time: 2000});
            }
        }
    });
});

AES加密、解密类

<?php
/**
 * Desc: AES加密解密
 * User: SenSen Wechat:1050575278
 * Date: 2021/4/27
 * Time: 14:14
 */

namespace sensen\services;

class AesService
{
    protected static $method = "AES-128-CBC";
    const KEY = 'fei1zui2you3jie!';
    const IV = 'hello202105world';

    /**
     * 加密
     * @param string|array $data 待加密
     * @param string $key 秘钥
     * @param string $iv 偏移量
     * @return string|string[]|array
     */
    public static function encrypt($data, $key=self::KEY, $iv=self::IV)
    {
        if(is_array($data)){
            $res = [];
            foreach ($data as $v){
                $text = openssl_encrypt($v, static::$method, $key, OPENSSL_RAW_DATA, $iv);
                $res[] = self::safetyBase64Encode($iv . $text);
            }
        }else{
            $text = openssl_encrypt($data, static::$method, $key, OPENSSL_RAW_DATA, $iv);
            $res = self::safetyBase64Encode($iv . $text);
        }
        return $res;
    }

    /**
     * 解密
     * @param string|array $text 待解密
     * @param string $key 秘钥
     * @param string $iv 偏移量
     * @param false $login 是否为登录
     * @return false|string|array
     */
    public static function decrypt($text, $key=self::KEY, $iv=self::IV, $login=false) {
        if(is_array($text)){
            $data = [];
            foreach ($text as $v){
                $cipherText = self::safetyBase64Decode($v);
                $cipherText = substr($cipherText, strlen($iv));
                $data[] = openssl_decrypt($cipherText, static::$method, $key, OPENSSL_RAW_DATA, $iv);
            }
        }else{
            $cipherText = self::safetyBase64Decode($text);
            if($login){
                //仅方便登录使用,登录时iv与key相同
                $data = openssl_decrypt(base64_decode($text), static::$method, $key, OPENSSL_RAW_DATA, $iv);
            }else{
                $cipherText = substr($cipherText, strlen($iv));
                $data = openssl_decrypt($cipherText, static::$method, $key, OPENSSL_RAW_DATA, $iv);
            }
        }

        return $data;
    }

    /**
     * base64安全编码
     * @param string $text
     * @return string|string[]
     */
    public static function safetyBase64Encode($text)
    {
        $text = base64_encode($text);
        $text = str_replace(['+','/'],['-','_'],$text);
        return $text;
    }

    /**
     * base64安全解码
     * @param string $text
     * @return false|string
     */
    public static function safetyBase64Decode($text)
    {
        $text = str_replace(['-','_'],['+','/'],$text);
        $text = base64_decode($text);
        return $text;
    }

}

加载字体跨域问题

apache

具体步骤如下:
1.开启apache的mod_headers模块
LoadModule headers_module modules/mod_headers.so

2.设置Access-Control-Allow-Origin


Header set Access-Control-Allow-Origin "*"

nginx

微信截图_20210407111855.png

字体转base64并替换原引用

字体转base64编码网址:https://transfonter.org/

ThinkPHP6 二级目录安装

由于某些特殊原因,可能需要将thinkphp系统安装到二级目录中,可参考以下操作(仅供参考):

网站目录:/www/wwwroot/website
运行目录:/subdir/public

伪静态:

location ~ .*\.(txt|TXT|gif|GIF|jpg|JPG|jpeg|JPEG|png|PNG|bmp|BMP|swf|SWF|css|CSS|js|JS|ico|ICO|doc|DOC|xls|XLS|xlsx|XLSX|docx|DOCX|json|JSON|woff2|WOFF2|woff|WOFF|ttf|TTF|pdf|PDF|zip|ZIP|rar|RAR|7z|7Z|svg|cur|map|properties|bcmap|htm|gz|log)$
{
  
  valid_referers xxx.cn *.yyy.cn;
  if ($invalid_referer){
     return 404;
  }
  
  rewrite  ^/subdir/(.*)$  /$1  last;   break;
  
}

set $flag "";
location  /subdir/ {
  index index.php;

  if ($request_uri ~* (get_file|get_auth_file|download|auth_download)){
    set $flag "${flag}1";
  }
  if ($http_referer !~* (xxx|yyy)){
    set $flag "${flag}1";
  }
  if ($flag = '11'){
    return 404;
  }
  
  if (!-e $request_filename){
    rewrite  ^/subdir/(.*)$  /index.php?s=$1  last;   break;
  }
}

Nginx配置:root /www/wwwroot/website/subdir/public;

ThinkPHP源码修改以支持二级目录访问

  1. 修改helper.phpurl方法默认domain参数为:true
  2. 修改Url.phpparseDomain方法返回值为:return $scheme . $domain .'/subdir'

Route::buildUrl($data['avatar'])->suffix(false)->domain(true)->build();