好像已经有好久没更新这个定番了,掐指一算已经有半年了吧(c_c) 主要是不想让归档里面充斥着我的网站更新日志,而不是正经的文章(嗯,一定是这样的)。

不过这不等于小站一直没更新哦,要想感受我这半年来辛勤的汗水的话(误)请转到ToDo Next Week 4

一般来说,Velas电波站每完成/新增一个功能,我都会在ToDo里面更新相关内容 (而且很多时候一个功能是在做完后才有ToDo的) 我想这大概也能满足那些更新 (shi jian) 爱好者的好奇心。

下面就让我简单概括一下这半年来Velas电波站的大事件吧。(说好了是Velas Weekly呢)

网站结构调整

熟悉本站的小伙伴应该能记得:半年前电波站的一级导航是由「首页」、「频道」、「碎碎念」、「留言」和「更多」组成的,而小站的文章分类被放到了「频道」下面。

一级导航
原谅我只找到了这张图

这也就意味着如果有人要来我站看小说的话 (一定会有这样的人的),就要先点开「频道」,然后再在子页面里面找「小说」的入口。要知道,每增加一次跳转都有可能造成用户流失,这对以文章为生的电波站来说是相当不利的 (试图为没人看小说找个借口)

改版后的一级导航
改版后的网站结构

改版后的电波站把文章分类提到了一级导航,将以前的三大板块「频道」、「碎碎念」和「网站日志」缩减为「频道」和「网站日志」,而「碎碎念」则和以前的「科技」分类合并成「杂聊」,被归并到「频道」下(顺便把留言板给藏了起来)。

同时,小站还调整了首页的信息呈现方式。从以前的只呈现每个分类下最新的三篇文章,改为了按时间顺序呈现所有「频道」下的文章。这也使得访客可以在不离开首页的情况下看完电波站所有的文章(网站日志那叫日志,所以就不放首页了,只留给geek看)。

虽然这次改动其实相当巨大,不论是前端还是后端都要配合着做调整,甚至因为板块的变动需要调整文章的数据库结构(Velas 8.0?)。但个人认为改版后的电波站对第一次来的人更友好了,而且也更方便大家找到自己感兴趣的文章,所以总的来说还是觉得值得的。

然而我还是觉得,把网站的其它页面一股脑都放到「更多」里面是蛮偷懒的。但反之,也就意味着要把其他页面在导航栏上摊开来,这对电波站当前的设计来说又相当不友好。在我想到一个更好的解决方案之前,只能让它先保持这个样子了(大家能找到留言板就行)。

改域名

由于xyz后缀在大陆待遇不佳(被微信墙、被百度冷落),所以为了电波站的未来着想,电波站在2019年12月29日启用了新域名www.velasx.com。而原来的域名www.velas.xyz将与新域名长期(至少在两年内)共存,并会自动跳转到新域名。虽然在改域名之后第一时间发了通知,但这里再提醒一遍吧。以前转载了本站文章、或加了本站友链的亲朋好友们要记得把小站的链接修改一下哦,非常感谢你的支持。

(结果今天发现百度开始收录velas.xyz而撤回velasx.com的索引了。我真的是&…@!@…&Y%&……*&%¥FGHVJ@#!EKIY2e)

其他功能

详细的更新日志可以到ToDo Next Week 4里查阅,这里只介绍几个关键的。

Web Share API 支持

其实我一直很好奇到底有多少人会用到页面里面的「分享」功能。反正就我个人来说,我是除了电波站里面「扫二维码在微信里查看」这个功能用的比较多以外,其它几个分享都不怎么用的(或者大不了有时候发发微博吸引一下流量)。

我还特意观察了身边人的习惯。发现如果要分享一个网站的话,他们除了直接发送网址以外,更多会用的是系统自带的分享。为此,Velas电波站加入了对Web Share API的支持。这个API可以允许网站像一个原生App一样,直接调用系统的分享功能。

分享按钮
系统分享按钮

对于使用支持Web Share API的浏览器访问本站的朋友,你们可以在这两个地方找到这个特殊的分享按钮。点击后,界面上便会弹出系统自带的分享菜单,更方便大家分享和转发自己喜欢的文章(例如一键分享到朋友圈/Telegram什么的)。同时,得益于Web Share API的回调函数,电波站还能记录下相应文章累计被分享出去的次数,让站长俺知道到底什么样的文章会更受大家欢迎。也希望这个功能会对你有帮助。

可惜的是,桌面浏览器目前只有Safari支持Web Share API,而移动端也只有部分系统自带的浏览器支持。希望在不远的未来,能有更多的小伙伴能看到和用上这个按钮吧。

打赏功能

相信一直以来,会有那么一群可爱的小伙伴。他们打心底里热爱着电波站,却苦于没有有效的渠道可以更直接地表达他们的喜爱,以致于电波站至今只能处于用爱发电的状——(我知错了……别打……)

嘛,虽然在相当长的一段时间内本站还不至于因为资金链断裂而跑路,毕竟电波站从一开始就是为兴趣而生。但本站每年消耗的金钱还是蛮可观的,租用服务器和购买域名都要耗费相当大的一笔金钱,而这笔钱到目前为止还是用我的压岁钱在顶着。加上本站是个非盈利网站,且没有在站内加入任何广告,所以它从头到尾就是个用爱发电的东西。

在这次更新中,我也为本站加入了一个打赏的入口(位于每篇文章的最后)。如果喜欢本站的文章、设计、或者其他的什么的话,不妨考虑一下点一点文章页面最下方的打赏按钮,请站长俺喝杯可乐之类的(厚颜无耻)。虽然不期望能靠这个功能弥补服务器和域名的开销,但这对于一直坚持原创的我来说会是个足以开心一整天的鼓励。

说实话贵站能有人点一个赞或发一条评论我已经可以开心一整天了。

滚动动画

在这次更新之前,电波站是使用scrollIntoView()方法来处理锚点跳转的。但如果不设置scrollIntoViewOptions的话,该方法并不带任何过渡动画(点一下就直接跳到页面的某个位置)。然而Safari和Edge(还有上古时代的IE)并不支持scrollIntoViewOptions。所以一直以来,本站的锚点跳转在Edge和Safari上都不带平滑过渡效果。这不仅造成了使用体验上的割裂,也对苹果用户/系统自带浏览器党不公平。

更新后的电波站使用JS来统一处理锚点跳转行为,并利用setTimeout() 来为锚点跳转统一加入了平滑过渡的动画。值得一提的是,这里的“平滑过渡”与之前带scrollIntoViewOptionsscrollIntoView()所呈现的匀速(线性)滚动动画不一样。新的滚动动画是由快到慢的、非线性的动画。它在大幅度的锚点跳转(例如从页头跳到页尾)中所需的时间更短,带给人的视觉体验也更为舒适(有点像坐电梯的过程)。

这里也要感谢@熊猫小A。在他的帮助下,新的滚动动画支持用户自行中断滚动,给予了用户更大的控制自由。即在锚点跳转的过程中,假如用户突然不想跳转了,那他可以通过滚动鼠标滚轮/点击鼠标/点击触摸屏来打断滚动,而毋需等到页面滚动到目标位置才进行下一步操作。小A改进后的函数还使用了requestAnimationFrame()来代替setTimeout() ,使得整体的动画效果更加平滑。

这个处理锚点跳转的函数如下:

export const SmoothScroller = {
    // written by Zeee, optipmized & packed by AlanDecode
    target: null,
    smoother: 15, // 平滑器。数值越小,动画速度越快。
    raf: null, // 2020-3-19新增

    move: function() {
        let cur = document.documentElement.scrollTop;
        let step = Math.ceil(Math.abs(SmoothScroller.target - cur) / SmoothScroller.smoother);
        if (Math.abs(SmoothScroller.target - cur) <= 1) {
            SmoothScroller.removeEventListener();
            cancelAnimationFrame(SmoothScroller.raf); // 2020-3-19新增
            return;
        }
        cur >= SmoothScroller.target ? cur -= step : cur += step;
        document.documentElement.scrollTop = cur;
        SmoothScroller.raf = requestAnimationFrame(SmoothScroller.move); // 2020-3-19改动
    },
    addEventListener: function() {
        let passiveSupported = false;
        try {
            const options = Object.defineProperty({}, 'passive', {
                get: function() {
                    passiveSupported = true;
                }
            });
            window.addEventListener('test', null, options);
        } catch (err) {}

        window.addEventListener('wheel', SmoothScroller.stop, passiveSupported ? { passive: true } : false);
        window.addEventListener('mousedown', SmoothScroller.stop);
        window.addEventListener('touchstart', SmoothScroller.stop);
    },
    removeEventListener: function() {
        window.removeEventListener('wheel', SmoothScroller.stop);
        window.removeEventListener('mousedown', SmoothScroller.stop);
        window.removeEventListener('touchstart', SmoothScroller.stop);
    },
    scrollTo: function(target) {
        if (target === null) return;
        if (typeof target === 'object') {
            target = target.getBoundingClientRect().top + document.documentElement.scrollTop;
        } else if (typeof target === 'string') {
            target = document.getElementById(target).getBoundingClientRect().top + document.documentElement.scrollTop;
        }
        // 若超出顶部或无法到达
        target = Math.max(target, 0);
        target = Math.min(target, document.documentElement.getBoundingClientRect().height - document.documentElement.clientHeight);

        SmoothScroller.addEventListener();
        SmoothScroller.target = target;
        SmoothScroller.move();
    },
    stop: function() {
        SmoothScroller.scrollTo(document.documentElement.scrollTop);
    }
};

只需像下面这样调用这个函数即可:

SmoothScroller.scrollTo(SomeElement); // "SomeElement" is the target Element 

不过目前该函数存在着一定概率下无法在Safari下打断滚动效果的bug。如果知道怎么抓这只🐛的话,欢迎在评论区指出。 (bug已修复)

时刻暴露在危险之中

前几天当我翻看本站的百度统计数据的时候,偶然发现了“受访页面”一栏中出现了一条充满违和感的URL:

陌生的URL
当你在自家网站的受访页面统计中发现了一个陌生的地址时

然后在好奇心的驱使下,我点击了这个链接,结果来到了一个和我家网站一毛一样的站点。这时我的心里只剩一个想法:

电波站被恶意镜像了。

这个站点用着我CDN上的数据、像电波站一样向我的后端发着数据请求,我这些天来却完全没有察觉到!

Google搜索结果
甚至还骗过了Google

而且这个域名在各大搜索引擎的排名要比本站的velasx.com要高许多。要不是及时发现,相信假以时日,这个“假李逵”完全会把我这个真正的Velas电波站从搜索引擎上给挤下去。

于是我一气之下给电波站加上了JS域名检验。一旦有人不小心访问了镜像网站,页面便会自动跳转到本站上。

const MySite = 'www.velasx.com';
if (document.location.host !== MySite) {
    location.replace(location.href.replace(document.location.host, MySite))
}

同时由于这个镜像网站使用了CDN,我无法直接查到它的真正IP。所以我又连夜从服务器的访问日志中找到了它的主机IP,并把它加入了服务器黑名单。一轮操作下终于把这个网站520了。

虽然发生了镜像站事件,但也请各位不用担心。尽管Velas电波站使用了RESTful API方便本站文章和留言数据的获取。但所有权限高的API都需要经过OAuth 2.0授权验证。他人无法通过任何非法渠道获取到访客邮箱等隐私数据,也无法删改本站的数据。您在本站的浏览和数据安全是受保障的。

但这不等于永无后顾之忧了。相反,一切才刚刚开始。

我无法接受一个坚持原创的网站随便被别有用心的人剽窃、并拿它的外皮去做一些肮脏的勾当。相信这也是任何一个苦苦经营博客的人所不愿看到的。所以我也呼吁各位博主多留个心眼,不忽视诸如网站统计、搜索引擎上可疑的蛛丝马迹,时刻防备类似的恶意镜像站的出现。

而当翻看服务器访问日志时,我还发现日志中存在着许多恶意攻击行为的痕迹。最主要的当属URL语义攻击和URL注入攻击。下面是几个典型的例子:

/?a=fetch&content=<php>die(@md5(HelloThinkCMF))</php>
/index.php?s=/Index/\x5Cthink\x5Capp/invokefunction&function=call_user_func_array&vars[0]=md5&vars[1][]=HelloThinkPHP
/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=phpinfo&vars[1][]=1
POST //index.php/module/action/param1/${@print(eval($_POST[c]))}

似乎都是利用了ThinkPHP的某些漏洞……(所以攻击者一定没有看我的关于页面……连我站的技术栈都没弄清楚)

甚至还不乏想用枚举法试出我的admin登录页面的。(明明之前都说过了,我的admin页在另一个域)

对于所有的频繁恶意访问以及恶意攻击行为,我都对相关的IP一一做了拉黑处置。

即使之前加固电波站的防御、及时升级依赖库、修补漏洞……这些本来一直是我开发与维护本站的重中之重,但直到看到了那么鲜活的例子、以及仔细翻阅了访问日志后,才发现“网络安全”并非是什么虚无缥缈的事情,不能仗着小站不出名而松懈安全防护。因为数据库中存储的每一条「信息」对于小站来说是无价的。很多网络攻击甚至是无差别攻击,哪怕小站在攻击中倒下了,攻击者自己也可能毫不知情。

下一步?

眼下快要迎来Velas诞生的第五年。私以为小站在基础功能上已经基本成熟了,所以未来的一年里,本站不会再出现大功能更新,但一些小功能的加入还是可以期待一下的,例如支持评论表情、文章搜索(再写18篇文章就做这个)、文章集合等。另外还有一些功能正在评估中,如:支持夜间模式、查看热门的文章等。

而由于2020年前端圈将会迎来Vue 3.0和Nuxt 3.0的大更新,所以技术上的升级也可以期待一下(但我觉得在体验上不会有太大差别)(将电波站用TypeScript重写什么的还是先别想了)。

最重要的是:更文章、更文章、更文章

 

最后的最后说一声:新年快乐!

让我们下一篇文章见吧。

  • 文/Zeee

商业转载请联系站长获得授权;
非商业转载请注明文章来源及链接。