PHP 日记 - 优化
抽空把站内资源都优化了一遍,包括 SSL 与重定向、多说与 SSL 相关问题、七牛云图床、Geetest 等。文章主要作日志使用,方便自己日后回顾这些问题,如果你所处环境为 Typecho 且有相关问题,可以详细阅读一下。
SSL
免费 SSL 可选择的范围不多,先是申请了 StartSSL 的一年免费证书,但发现其一年免费证书已被移除信任。接着找到SSL For Free这个 Let's Encrypt 第三方,操作步骤很详尽,验证主机提供了三种选择方案。同样的,Let's Encrypt 证书需要每三个月更新一次,如果你没有 Let's Encrypt 所需要的环境,那么可以借由此服务获得证书。
重定向
如果希望所有 http 访问重定向到 https,那么可以修改 Apache 或 Nginx 重写规则。关于 Apache,可以按以下规则修改.htaccess
(Typecho 适用):
/* http 301 到 https */
RewriteCond %{SERVER_PORT} !^443$
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [L,R=301]
/* 一级域名定向到 www 二级域名 */
RewriteCond %{HTTP_HOST} ^yourdomain.com
RewriteRule ^(.*)$ www.yourdomain.com/$1 [L,R=301]
/* 部分资源不重定向(不完整片段) */
RewriteCond %{REQUEST_URI} !^/root/
RewriteCond %{REQUEST_URI} !/plugin/
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [L,R=301]
最终,若希望所有一级域名定向到 www 二级域名、http 301 到 https 且部分资源不重定向,可以把规则合并为:
RewriteEngine On
RewriteBase /
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTP_HOST} ^yourdomain.com [NC]
RewriteCond %{REQUEST_URI} !^/root/
RewriteCond %{REQUEST_URI} !/plugin/
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [L,R=301]
多说 SSL 兼容
全站 SSL 后,寻找多说评论框的替代品可谓一波三折。国外评论平台响应稍慢,国内又未能找到可以满足所有要求的平台——支持 HTTPS、支持自定义样式、支持评论后台回调。苦于种种高要求,只好继续沿用多说评论框。多说的功能其实比较完整,既支持无登录评论,又能够定义所有样式,可惜管理团队不上心,服务停滞不前。多说最让人诟病的是经常无法加载拖慢网页响应,且第三方登录头像仍未支持 HTTPS。对此,我们可以进一步优化。
多说第三方头像兼容 HTTPS1:
- 下载官方embed.js并格式化;
- 搜索关键字
avatar
并如图修改; - 把修改后的文件重新上传到云端(建议使用 CDN 服务);
- 修改多说评论模版地址(Typecho 适用)。
多说资源异地保存,基本解决拖网速问题:
- 主要为embed.compat.js,其次为embed.default.css,同时还有smilies.js,分别下载三个文件;
- 把下载好的 embed.compat.js 重命名为
libs/embed.compat.js
,embed.default.css 重命名为styles/embed.default.css
,smilies.js 重命名为libs/smilies.js
,分别上传到云端(建议使用 CDN 服务); - 向 embed.js 搜索关键词
STATIC_URL
并如图修改; - 保存 embed.js 方法同上。
七牛云图床
七牛云有免费的 HTTP 下载流量,但 HTTPS 仍要收费。如果希望图片及文件能够上传到七牛云的同时备份到本地服务器,可以利用七牛空间的镜像功能。
- 直接使用插件SimpleCDN;
- 或搜索关键字
content(
,如图修改/var/Widget/Abstract/Contents.php
文件(Typecho 适用)。
值得注意的是,修改本地文件不能影响七牛云镜像,如有修改请务必手动上传更改。
Geetest
Geetest for Typecho 可通过插件解决2。
- 下载并启用插件Geetest;
新增
/admin/geetest-code.php
文件;<?php if (!defined('__DIR__')) { define('__DIR__', dirname(__FILE__)); } define('__TYPECHO_ADMIN__', true); /** 载入配置文件 */ if (!defined('__TYPECHO_ROOT_DIR__') && !@include_once __DIR__ . '/../config.inc.php') { file_exists(__DIR__ . '/../install.php') ? header('Location: ../install.php') : print('Missing Config File'); exit; } /** 初始化组件 */ Typecho_Widget::widget('Widget_Init'); /** 如果插件已启用, 则输出极验服务器响应数据 */ /** 之前旧版本写法(已废弃) $exists = Typecho_Plugin::exists('Geetest'); if(false !== $exists) { Typecho_Plugin::factory('gt')->server(); } **/ if(!empty(Helper::options()->plugins['activated']['Geetest'])) { Typecho_Plugin::factory('gt')->server(); }
修改
/admin/login.php
代码(建议对比修改);<?php include 'common.php'; if ($user->hasLogin()) { $response->redirect($options->adminUrl); } $rememberName = htmlspecialchars(Typecho_Cookie::get('__typecho_remember_name')); Typecho_Cookie::delete('__typecho_remember_name'); $bodyClass = 'body-100'; include 'header.php'; ?> <div class="typecho-login-wrap"> <div class="typecho-login"> <h1><a href="http://typecho.org" class="i-logo">Typecho</a></h1> <form action="<?php $options->loginAction(); ?>" method="post" name="login" role="form"> <p> <label for="name" class="sr-only"><?php _e('用户名'); ?></label> <input type="text" id="name" name="name" value="<?php echo $rememberName; ?>" placeholder="<?php _e('用户名'); ?>" class="text-l w-100" autofocus /> </p> <p> <label for="password" class="sr-only"><?php _e('密码'); ?></label> <input type="password" id="password" name="password" class="text-l w-100" placeholder="<?php _e('密码'); ?>" /> </p> <?php Typecho_Plugin::factory('gt')->render(); ?> <p class="submit"> <button type="submit" class="btn btn-l w-100 primary"><?php _e('登录'); ?></button> <input type="hidden" name="referer" value="<?php echo htmlspecialchars($request->get('referer')); ?>" /> </p> <p> <label for="remember"><input type="checkbox" name="remember" class="checkbox" value="1" id="remember" /> <?php _e('下次自动登录'); ?></label> </p> </form> <p class="more-link"> <a href="<?php $options->siteUrl(); ?>"><?php _e('返回首页'); ?></a> <?php if($options->allowRegister): ?> • <a href="<?php $options->registerUrl(); ?>"><?php _e('用户注册'); ?></a> <?php endif; ?> </p> </div> </div> <?php include 'common-js.php'; /** 如果插件已启用, 则输出极验服务器响应数据 */ $geePluginEnable = !empty(Helper::options()->plugins['activated']['Geetest']) ? true : false; ?> <script> $(document).ready(function () { $('#name').focus(); <?php if($geePluginEnable):?> //极客验证码验证 (function(){ var handler = function (captchaObj) { // 将验证码加到id为captcha的元素里 captchaObj.appendTo("#captcha"); }; $.ajax({ // 获取id,challenge,success(是否启用failback) url: "geetest-code.php?rand="+Math.random()*100, type: "get", dataType: "json", // 使用jsonp格式 success: function (data) { // 使用initGeetest接口 // 参数1:配置参数,与创建Geetest实例时接受的参数一致 // 参数2:回调,回调的第一个参数验证码对象,之后可以使用它做appendTo之类的事件 initGeetest({ gt: data.gt, challenge: data.challenge, product: type, // 产品形式float-浮动式 embed-嵌入式 offline: !data.success //支持本地验证 }, handler); } }); })(); <?php endif;?> }); </script>
修改
/var/Widget/Login.php
代码(建议对比修改);<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; class Widget_Login extends Widget_Abstract_Users implements Widget_Interface_Do { public function action() { // protect $this->security->protect(); /** 如果已经登录 */ if ($this->user->hasLogin()) { /** 直接返回 */ $this->response->redirect($this->options->index); } /** 初始化验证类 */ $validator = new Typecho_Validate(); $validator->addRule('name', 'required', _t('请输入用户名')); $validator->addRule('password', 'required', _t('请输入密码')); /** 截获验证异常 */ if ($error = $validator->run($this->request->from('name', 'password'))) { Typecho_Cookie::set('__typecho_remember_name', $this->request->name); /** 设置提示信息 */ $this->widget('Widget_Notice')->set($error); $this->response->goBack(); } /** 极客验证码校验 **/ $this->verifyGeeTest(); /** 开始验证用户 **/ $valid = $this->user->login($this->request->name, $this->request->password, false, 1 == $this->request->remember ? $this->options->gmtTime + $this->options->timezone + 30*24*3600 : 0); /** 比对密码 */ if (!$valid) { /** 防止穷举,休眠3秒 */ sleep(3); $this->pluginHandle()->loginFail($this->user, $this->request->name, $this->request->password, 1 == $this->request->remember); Typecho_Cookie::set('__typecho_remember_name', $this->request->name); $this->widget('Widget_Notice')->set(_t('用户名或密码无效'), 'error'); $this->response->goBack('?referer=' . urlencode($this->request->referer)); } $this->pluginHandle()->loginSucceed($this->user, $this->request->name, $this->request->password, 1 == $this->request->remember); /** 跳转验证后地址 */ if (NULL != $this->request->referer) { $this->response->redirect($this->request->referer); } else if (!$this->user->pass('contributor', true)) { /** 不允许普通用户直接跳转后台 */ $this->response->redirect($this->options->profileUrl); } else { $this->response->redirect($this->options->adminUrl); } } private function verifyGeeTest() { $status = array( 'empty' => '请进行拼图验证', 'failed' => '验证失败', 'success' => '验证通过', 'down' => '请求超时,请重试', 'error' => '服务器异常,请重试' ); /** 如果插件已启用, 则进行验证 */ if(!empty(Helper::options()->plugins['activated']['Geetest'])) { $data = $this->request->from('geetest_challenge', 'geetest_validate', 'geetest_seccode'); $response = Typecho_Plugin::factory('gt')->verify($data); if($response == 'success') { } else { $error = !empty($status[$response]) ? $status[$response] : $status['error']; $this->widget('Widget_Notice')->set($error); $this->response->goBack(); } } } }
值得注意的是,Geetest 访问 HTTPS 需要用户付费,使用时请自行斟酌。
声明
在此,再次感谢引用到的作者与资源。文章聚合这些资源主要为个人日后回顾使用,如有侵犯请及时告知。
- 出自:多说完美https改造,是能够搜索到的最高效的方案。 ↵
- 出自:typecho极验验证插件。 ↵
如有问题,欢迎留言或邮件咨询
修改于 November 4, 2018 03:57:20 (6 年前) - « 上一篇:Workflow - Music Launcher
- 下一篇:Module - Page Up and Down »