jwj 发布的文章

最近新买了辆摩托车来代步,但没有驾驶证比较危险,万一路上被逮到,C1驾照就不保了。
想了想还是去增加摩托车E好点,以下是本人在韶关市报考摩托车的经历,其它城市流程不一定一样,仅供参考。
去报了两次,第一次不大顺利,第二次顺利报上。

要准备资料

  • 身份证原件
  • 身份证正反面复印件两张
  • 驾驶证原件
  • 驾驶证正反面复印件两张
  • 照片及照片回执
  • 安装登录 12123 APP
驾驶证仅增驾时需要提供,如果没有驾驶证,不是增驾就不用驾驶证。
照片可以去照相馆照,以前拍了照的,只有照片不行,要有一个回执才行。

需要检查内容

  • 交管12123上的身份证是否已过期,如果过期需要先更新一下
  • 驾驶证上的通讯地址和身份证的通讯地址是否一样,如果不一样,需要去车管所变更换新证(自助柜机也可以尝试办理)

体检

报考前,需要进行体检,体检是免费的,就在西联考场外面,可以在地图搜索“职业病防治院驾驶员体检处”。
体检需要身份证复印件一张、驾驶证复印件一张,如果没有复印件,会收取一元复印费。
几分钟就体检完,然后会给你一张体检表。

办理报考

进去西联考场里面,提交身份证、驾驶证、复印件、提交表、照片回执和照片,然后缴纳235元考试费,选择考试时间,完成报考。

考试时间一般只能约周二和周四,所有科目都当天考,中午12:20前带身份证到西联考场考试。

笔试(科目一、三)

12:30 开考,先签到进考场考科目一,考完签名。签完名出去签到,然后再进去考场考科目三。

实操(科目二)

14:30 开考,开考前先领取表格,然后等候考试。考完之后,将表格交还考官。
很不幸,我在第一关(绕桩)就挂科了,只能回去练练再重新补考。。。

补考

补考要去西联考场办理,如果考试不及格,要先在12123网站上查询下考试成绩,如果成绩出来了,就可以马上办理补考预约。
如果成绩没出来(笔试成绩很快出来,但是实操的成绩要等一天左右),只能等成绩出来后再去办理补考预约业务。

下证

第二次补考成功,差点第二次补考也不过,幸好后面成功过了。

每次考试都有两次机会,第二次补考的第一次机会,忘了戴头盔,刚考就挂了。。。
第二次机会戴上头盔,后面的项目一次性就过了,万幸。

通过后,将考试表给考官签名,然后给身份证给两位考官核对签名。核对没问题后,直接办理驾驶证邮寄,等着新驾驶证邮寄过来即可。

场地细节

绕桩

两个桩之间的距离是2.7米,两条边线的距离是2.4米,共五个桩。绕桩要绕两次(来回各一次,共两次),绕桩时脚不能下地。
建议考之前练一下,别觉得开了这么久,没什么问题,我去了两次,很多人都挂在这里,都是没有练过。

你说他们菜,青年和大叔都有,你说他们开了多久摩托车呢?我在家自己练的时候,我爸去尝试,刚开始也不能一次过。我爸开摩托车也十几二十年了,能说不会开吗?所以建议自己得先练一下再去考。

最近考虑给父母装一条移动宽带,一开始还满怀期待的,但漫长的等待让我从开心到不满。还没用上,服务就先给我不满了,相比电信的当天装,当天用,时间实在是差别很大。

时间线

2021年2月24日

前往营业厅,报装移动宽带。资费:一年三百多,含 100M 宽带和 IPTV。
满足家里父母用手机和看电视的需求,个人觉得那些 200M、300M 和 1000M 有点浪费,父母不下载,只看电视刷手机视频和网页, 100M 是完全够了的。

随即,收到10086的电话,确定安装时间,收到预约26日上门安装短信。

安装短信里面的师傅联系号码为 #N1 ,应该为模板变量,但未被替换成师傅的实际电话,是什么问题就不知道了。

2021年2月28日

过了26日的预约时间,无运维安装人员电话联系我这边。
因为没有师傅联系电话,想起可以查询宽带安装进度,从里面找到师傅的安装电话,主动拨打过去。
经过沟通,是派错单,派错区域,单子已转到负责我家这边的师傅。

2021年3月1日

因为转给了新的师傅,安装进度没更新,进度上还是旧的师傅。
于是主动电话联系 1008616 进行催促。
十多分钟后,安装运维师傅才打电话过来约定上门时间,约定一两个小时后上门安装。
同时,告知我家附近只有一个总机箱,可能装不了。

一个半小时后,师傅短信告知,确定只有一个总机箱,需要工程队安装分箱之后才行。
之后我短信回复询问,分箱具体什么时候可以装好,但没有得到回复。

2021年3月4日

安装一直没进度,也不知道什么时候可以安装,随机又主动电话联系安装运维师傅,询问分箱进度及安装时间。
师傅回复分箱由另外的部门负责安装,他这边无法控制,只能再帮我催催。

2021年3月8日

安装还是没收到新的进度消息,静悄悄的,方法我没报装过似的。
主动电话联系 1008616 ,得知无权处理,需要上级部门来处理,已帮我上报处理,由上级部门48小时内给我答复。
随机,手机上收到投诉工单已受理的短信提示。

一小时后,收到上级部门回复,说帮我安排处理下,让我稍后留意。

2021年3月9日

收到 10086 的电话,告知暂时没有分箱,需要等待。询问要多久,客服无法给出准确时间。
想了想,要求客服帮我取消安装。刚开始要我去营业厅办理,经过沟通,同意了在线上取消。

准备报装电信宽带...

2021年3月12日

中午休息时间,去电信营业厅办理了两条宽带业务。

隔了一个小时后,分别收到两条宽带的区域运维电话,约定上门时间。
两条宽带都可以当天装,但自己要上班,就推到了周末。

2021年3月13日

两条宽带分别于中午和上午进行了安装调测。
但是家里的路由器刷的是 PandorBox ,运维师傅没用过,我也不在家,没能直接连上网。
师傅打电话让我回来后,自己配置下路由器,他不会整(哈哈)。

结束

最终还是选择了电信,虽然价格贵,但是效率没得说。

fork 仓库后同步上游仓库的修改,个人总结了两种方法,个人感觉第一种适合仓库所有者使用,第二种适合仓库贡献者使用。

方法一

拉取上游更新

git fetch upstream

检出代码

git checkout -b master upstream/master

合并代码

会产生一条 Merge remote-tracking branch 'upstream/master'记录
git merge upstream/master

推送到github

git push origin master

方法二

拉取上游更新

git fetch upstream

检出代码

远程仓库的代码和提交记录会强制覆盖本地
git checkout -B master upstream/master

推送到github

强制推送到 github
git push -f origin master

其它命令

查看所有分支和当前所处分支

git branch -a

拉取仓库更新

git fetch origin
git fetch upstream

在自己电脑(Windows)开发测试代码都没问题,但一上生产环境就报错了。经过对比,本机和服务器的PHP版本和OpenSSL版本不一样,猜测可能是这个原因导致的。经过一番查找,找到了从代码上解决问题的办法,规避了调整生产服务器的风险。

报错的代码

/**
 * 字符串加密(加密方法:DES-ECB)
 * @param string $data 待加密字符串
 * @param string $key 对称加密密钥
 * @return string
 */
function encryptData(string $data, string $key)
{
    // 获取密码iv长度
    $length = openssl_cipher_iv_length('DES-ECB');
    // 生成一个伪随机字节串
    $iv = openssl_random_pseudo_bytes($length);
    // 加密数据
    $ciphertext = openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA, $iv);

    // 把包含数据的二进制字符串转换为十六进制值,然后返回结果
    return bin2hex($ciphertext);
}

报错信息

Fatal error: Uncaught Error: Length must be greater than 0 in frame.php:87
Stack trace: 
    #0 frame.php(87): openssl_random_pseudo_bytes()
    #1 frame.php(60): encryptData()
    #2 {main} thrown in frame.php on line 87

根据报错信息,主要问题是openssl_cipher_iv_length()返回的长度为0,而openssl_random_pseudo_bytes()的参数的长度必须大于0,所以就产生了报错。
但是openssl_cipher_iv_length()为什么返回0呢?难道是不支持DES-ECB加密方法?
使用openssl_get_cipher_methods()方法获取可用的加密算法的列表,发现DES-ECB在列表内,那应该是支持的!
这时候,我就猜想是不是openssl低版本的BUG,因为以前也见过一些因为openssl版本过低导致的问题,于是继续Google一番。
经过查找,发现了两条有用的结果:

在第一条中得知ECB 加密模式是不安全的,因为它没有初始化矢量openssl_cipher_iv_length()返回的长度为0的原因就得知了。

但结论没有经过仔细论证。也不知道为什么java为什么要ECB。
在第二条中找到了调整代码的思路。
最终得到了以下没有报错的代码~
/**
 * 字符串加密(加密方法:DES-ECB)
 * @param string $data 待加密字符串
 * @param string $key 对称加密密钥
 * @return string
 */
function encryptData(string $data, string $key)
{
    // 获取密码iv长度
    $length = openssl_cipher_iv_length('DES-ECB');
    // 生成一个伪随机字节串
    if ($length > 0) {
        $iv = openssl_random_pseudo_bytes($length);
    } else {
        $iv = '';
    }
    // 加密数据
    $ciphertext = openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA, $iv);

    // 把包含数据的二进制字符串转换为十六进制值,然后返回结果
    return bin2hex($ciphertext);
}

在制作项目中,难免会遇到有跨域问题,需要增加指定响应头来满足跨域的需求。但ThinkPHP5.1版本的手册中,对跨域怎么设置提供的方法比较局限,所以这里经过研究,总结出了几种办法,推荐使用第三种。

一、路由

这方法是手册当中介绍的,这里简单复制下,深入了解可以查看手册

如果某个路由或者分组需要支持跨域请求,可以使用

Route::get('new/:id', 'News/read')->ext('html')->allowCrossDomain();
Route::group('index', function() {
    Route::get('new/:id', 'News/read');
})->prefix('index/')->allowCrossDomain();

这方法,仅适合定义了路由的情况下使用,如果是默认路由,这方法不适用。

二、header()函数

可以在入口文件index.php、公共函数文件common.php等文件里使用header()函数定义跨域响应头。代码如下:

header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE');
header('Access-Control-Allow-Headers: Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With');
header('Access-Control-Allow-Origin: *');
全局允许跨域的话,在入口文件或全局公共函数文件里增加跨域代码
单模块允许跨域的话,在模块公共函数文件里增加跨域代码
单控制器允许跨域的话,在控制器文件里增加跨域代码(命名空间与类声明之间区域)
单方法允许跨域的话,在方法代码开头增加跨域代码。或者使用路由设置跨域。

这个方法可能会存在响应头被覆盖的问题(框架输出响应内容时,设置了相同的响应头,后设置覆盖前设置)

三、中间件

可以使用中间件,更改响应输出内容。这种方法适合全局或部分模块使用。
创建application/http/middleware/AllowCrossDomain.php文件,文件内容如下:

注意修改允许跨域的域名
<?php
namespace app\http\middleware;

/**
 * 跨域中间件
 * @package app\http\middleware
 */
class AllowCrossDomain
{
    /**
     * @param \think\Request $request
     * @param \Closure $next
     * @return mixed|\think\Response
     */
    public function handle($request, \Closure $next)
    {
        // 允许跨域的域名
        $allowOriginDomain = ['www.kancloud.cn', 'll00.cn'];
        // HTTP请求头中的Origin
        $origin = $request->header('origin', '');
        // 附加响应头
        $header = [];

        if (!empty($origin)) {
            $domain = explode('://', $origin)[1] ?? '';
            if (in_array($domain, $allowOriginDomain)) {
                $header['Access-Control-Allow-Credentials'] = 'true';
                $header['Access-Control-Allow-Methods']     = 'GET, POST, PATCH, PUT, DELETE';
                $header['Access-Control-Allow-Headers']     = 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With';
                $header['Access-Control-Allow-Origin']      = '*';
            }
        }

        return $next($request)->header($header);
    }
}

application/middleware.phpapplication/index/middleware.php文件加入

\app\http\middleware\AllowCrossDomain::class

示例:

<?php
return [
    // 允许跨域
    \app\http\middleware\AllowCrossDomain::class,
    // 登录认证
    //\app\wxamp\middleware\CheckLogin::class,
    // 权限验证
    //\app\wxamp\middleware\CheckPermission::class,
];

四、输出响应对象实例设置

可以在json()jsonp()xml()等函数里设置跨域响应头,如:

return json(
    [
        'code' => 0,
        'msg'  => '操作成功',
    ],
    200,
    [
        'Access-Control-Allow-Credentials' => 'true',
        'Access-Control-Allow-Methods'     => 'GET, POST, PATCH, PUT, DELETE',
        'Access-Control-Allow-Headers'     => 'Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, X-Requested-With',
        'Access-Control-Allow-Origin'      => '*',
    ]
);