每周一记(8月的尾巴)

从万般抵触到欣然接受,没想到会这么快。

工作

我被转岗了,并且是在没有通知的情况下。

  • 上周五,老大让我去看某度统计的源代码,花了好长的时间,想了好多办法才拿到这份经过babel转译过的源码,可读性又差,我硬着头皮看了个大概。这大概若不是工作需要我可能永远不会去读的代码。
  • 周一,前去汇报,听说要做一个类似的项目,私底下用什么技术,如何去实现我都想好了,只等开工。
  • 周二,打开邮箱,转岗的邮件发过来了,在毫不知情的情况下,我因为业务需要被调岗了,甚至这次调岗老大都不知道。刚看到这份邮件的时候,我最开始的心情竟然是有点开心,因为在我们部门简直不要太闲,并且首页代码真的让人提不起兴趣。再者,我要去的部门是公司的核心部门,用公司前段时间说的,我这是从第一曲线往第二曲线上跨越。
  • 周三,在搬过去之前,我把首页的代码又仔细检查了一遍,确保所有生涩难懂的代码段都有注释,又解决了几个潜在的bug,最后提交一把,并交给小伙伴。晚上,下班,我一个人默默的搬了好几趟,心里说不出的难受。和小伙伴一起回家,路上我在吐槽,好不容易熟悉了一个环境,又要去一个陌生的环境,对于不善人情世故的我,真的是煎熬哎。
  • 周四,新部门的第一次晨会,我完全打消了心中的顾虑,我想我能够很好的融入这个集体。等拿到项目代码,又回到了React了,复杂的实现逻辑,理解起来真的让人头疼,但也让我欣喜,我喜欢挑战,虽然看起来这更多会是体力活。
  • 周五,在新的环境里,一切又回归平静。带上耳机,新的一天又开始了,这让我想起上学的时候,带上耳机听着音乐,脑子无比清醒,总能够很快的完成任务。

学习

  1. React

既然又入坑了,对于好几个月都没怎么用的技术了,当然需要花一些时间来温习下了。

  1. 微信小程序

源于在掘金上看到的一个沸点,我决定把开发小程序加入自己的技能树了,这可能需要花上很长的一段时间才能达到写demo的阶段,平时忙得不可开交,周末玩玩游戏健健身,学习的时间又少了,哎…电子书已下载好,写完周记就启动!

  1. SSR

上周花了很多时间去学习React服务端渲染,Demo也是写了毫无异常,昨天下班后尝试把以前做过的idea转到服务端渲染上,却怎么都不成功,也不报错,所以这才是周末的优先级,当然除了游戏时间外。

吐槽

虽然吐槽公司不怎么好,但是继收回所有开发的管理员权限后,公司又在网络上为大家着想了,原本每天只有200MB的流量可挥霍,下个稍大的软件都要开工单,现在工作机器要断网了,想上网查资料,滚去虚拟机去查!所以啊,机器本身配置一般般,以后虚拟机又要常驻内存了,开发体验在差的基础上,变成了如果不是为了生活

尾巴

虽然刚上大学不久就接触到了Web开发,接触Web前端开发也有好几年,毕业来公司作为前端也两个月了,React项目国际化,首页数万行祖传代码重构(重写)到几千行,但是我在下周还要参加公司的前端资格考试,只有考核成功,你才能正式成为前端搬砖师。

我想的是,需不需要准备啊什么的,要是到时候考试没通过,要被转去后端写C#,我肯定是不愿意,那就只有另谋高就了。

刚来公司上培训课的那段时间,公司前端新人十几个,竟然只有两个人是有经验的,其中有一个只是停留在使用过jQuery的阶段,那么问题来了。我排第几?

我觉得,虽然那些没有接触过前端开发的小伙伴能够在最近好好学习,但是作为一个几年了还在浑水摸鱼的前端,我我觉硬要排名的话,前五还是稳的。

考试前的准备,学生时代尚且没做好,不在乎早已根深蒂固。

结果如何,下周便知。

这次把尾巴也写成了吐槽😂

分享到 评论

每周一记(8月末)

找不到能形容这一周生活的词,除了愚蠢

照例谈工作

我觉得我现阶段的工作和大学里上自习没什么区别,没有人约束,仅凭自己的意愿,随心所欲。除了偶尔还需要补救盲目的重构带来的bug,偶尔需要切下图制作个广告页,剩下的时间就自己安排。

  1. 看书

自从知道在githubclone电子书可能会被关小黑屋后,在公司电脑上的电子书就只有当初年少无知下载下来的《你不知道的JavaScript》系列了,这也是我最喜欢的JavaScript开源电子书了。还是在学生时代,就完完整整的将整个系列看过一遍,如今一两个月的时间,差不多又看完一遍了,真的是有一种温故知新的感觉。在阅读整个电子书的过程中,有唯二不那么愉快的地方,第一,作者使用Markdown格式编写的,并且每一章单独成一个文件,有时候一章内容太多,断断续续需要一天才能读完,尤其是午后,读太久了犯困。第二,公司屏幕尺寸和素质不能让人满意,尤其是没有管理员权限去安装Markdown阅读器,只好在VS Code中打开并且使用分屏的预览,结果可读区域面积太小,读久了眼睛又受不了。

  1. React SSR

关于SSR(服务端渲染),我一直想纳入技能包,好在这周有充分的时间去学习。在掘金上看了两篇相关的入门文章,然后把大名鼎鼎的Next.js文档看过一遍。现在回顾一下,差不多只能记住rendertoStringgetInitialProps? 大概还在也许会写Demo的阶段吧。所以说呢,学习尚未成功,还要继续努力。

  1. 源码

看源码对于现阶段的我来说是奢侈的,如果加上通过各种途径去获得不容易获得的源码,再加上可读性为0,那就让人头疼了。

潜在的业务需要,我需要读一段某某公司开发的页面统计的代码,首先这些代码不是开源的,也不仅仅就通过引入这段JS路径就可以得到源码,并且其是不可读的,有多少不可读呢,举个例子吧,代码2000行左右,使用IIFE分成好几段,对于变量的命名,是没有规律可循的,都使用了A-Z a-z随机组合的方式,并且嵌套极深。例如af.c.cb.hcp

如何获取到源码这里不过多叙述,反正花的时间多余读源码的时间。

源码如果不可读,那就只读能够理解的地方,所以这么多代码,大概花了2个小时梳理了一下,大概知道了了其工作方式,需要记录的各种数据,至于实现,那是不可能梳理得清楚的。

看完一遍,发现该份源码写得十分规范,给大厂点个赞!

吐槽

周四,例行的下班后健身。结果坐电梯的时候发现五楼摁不了了,坐到三楼服务员告诉我,健身房倒闭了。WTF,两天前来还好好的,现在就倒闭啦?器材都被搬空,怕不是跑路了吧。我才买的的补剂呢!我才办的卡呢!

周五晚打完篮球,骑车回来,又路过那条街,发现有人在发办健身卡的传单,虽然不是开在一个地方。一想,真快哎,又为下一次跑路做准备了?

经过这次被跑路的经历,我是不可能再办健身卡了,民工挣点钱不容易,怕不是要被城市的套路消耗殆尽?但是呢,健身还得继续。

写在最后

换了电脑,把博客迁到PC上,试了各种网络上的办法,遇到各种各样的问题。结果我用最简单粗暴的方法,直接把目录拷贝过来,再安装依赖,就OK了。

刚买了新电脑,有点兴奋,每天下班后总会在快睡觉之前玩两把,玩完又睡不着觉,结果到了公司,第二天是真的困。要不得,要不得。

前端三连是:太复杂 看不懂 不会做。下次面试还有自以为是的面试官,直接就怼过去了。

分享到 评论

每周一记(18年8月中)

8月16号刚凌晨,伴随着手机提示音,工资卡中终于有了第一个月的工资。然后,那个晚上,竟然失眠了,整晚上我都在想,除去房租和必要的生活资金,我该如何花掉剩下的钱呢。周四,忙碌的一天,晚上下着大雨,从健身房中回来,有了最初的想法,既然健身是为数不多的爱好,那么补剂还是要买的,无聊的时候想玩玩游戏去网吧简直不要太贵,主机嘛,当然是要攒的。再加上每月固定的花呗,好了,花光了,期待下月…

谈工作

本周的工作总体来说是很轻松的,但是出现了很多问题,我应该反思。

掘金上看到一个沸点,说的是新人总喜欢抱着满腔热血去重构祖传代码,然后碰壁。这点恰是说中了我。来到公司的这一个月,我也是在按照我的想法,重构一块很重要的代码。一段名副其实的祖传代码。无论从项目目录结构,还是代码本身,我只想说一句,烂透了或者是我从没见过这么烂的代码。但是,抛开性能和开发体验上的问题,这段代码却很好用。借用罗老师的一句话“又不是不能用”来形容是最好不过的了。

当然吐槽归吐槽,重构还是要继续。准确来说,是重写。在检测过ES6支持程度后,我使用ES6重写了业务逻辑,并且抛弃了依然好用的表格布局,引入和AMD规范,并且在易用性和可扩展性上下了很大的功夫。

请注意,这一切都是我想到的,没有经过评审,我花了两周的时间,就重构完了。

然后,上线了,BUG铺天盖地。真的,除了失落和灰心,我想不到其它的词来形容我的心情。

极为不规范的成千上万行祖传代码怎么可能在很短时间内弄懂;不熟悉业务逻辑,很多隐藏的业务功能都没有实现;引入模块化是好,业务逻辑解耦也好,但是过多的模板,导致现有的项目太过臃肿,要是只有一个版本还好,多版本多语言简直就是灾难。

除了修BUG,我也在思考,然后并且了模块化,一下子少了四十多个入口文件,通过工具把配置文件整合在一个文件中,并且在实际部署的时候压缩配置文件,配置文件从24个到如今的一个,体积从300KB到现在的70KB。当然,改变还有很多,使用localStorage缓存文件,合并压缩样式文件,减少页面请求等。重构未完成,还得努力。

还能说什么呢,学到了,真是学到了。

吐槽

本周的某一天,我回到家,打开iTerm准备大干一场,突然,一道灵光闪过,我CTMD,iTerm换图标了,上面那个白条是什么鬼,真是逼死强逼症的节奏哎。直到现在,好几天过去了,还是不习惯!

某天晚上十一点,看了将军的直播,我一口气花完了攒了好久的3700尘,合了一套法术猎,结果被治疗术吊打,被各种德吊打,被电影萨打到哭,甚至打不赢沙包战你信?在这里,说一句:炉石传说真**好玩!

今天快到中午的时候,和小伙伴健完身去那边买网线,问了好多家杂货店和五金店,基本上都没有,然后一老大爷给我找了个三米长的竟然要收我十五块,忍住了没买。后来买了十米十二块,价格稍微能够接收。关键是拿回家一试,房间里根本没接网,去起居室接又不可能。白瞎了我的十二块哎,无线网卡走一波,了事。

其它

如果说还要有其它就要算追了很久的美剧《地球百子第五季》完结啦,想看第六季明年再说咯。第五季追下来整体无感,感觉和前几季比起来剧情是真的无聊。今天看了第十三集,贝拉米他们重新上了飞船,休眠了125年,蒙迪留下的视频,感动!超级期待第六季地球百子与外星人的故事啦。

其它的其它,大概还有学习。每天给自己留下足够的时间,去好好的回顾和学习新的知识,趁自己还学得动。

分享到 评论

开端

时间过得真快,搬砖快一个月了。

第一周

现在对搬砖的要求真高,培训后才能上岗。按照惯例,进了工地就要开始培训了,谁知有工友要下周才到,所以我们这些先一批就得等着了,第一周工头又不安排工作,只有无所事事了。那五天的上班时间啊,幸好带了本《论如何在搬砖过程中学习挖掘技术》,一边学习搬砖技巧,一边偷偷干私活。总的来说,工作环境还是不错的,就是给我们的工具有点不顺手,哎,就这样呢,还要什么自行车呢!

这里要说一下食堂,虽然菜品是少了点,但味道还是不错的,比我在蓝翔好吃多了,就是这个价格…放在我住那边的工棚小店,这个价两荤一素再来瓶冰啤,岂不是美滋滋。哎,说多了都泪啊。

第二、三周

终于开始进行培训了。我们这些粗人,就仗着体力好,干得久,才能勉强得到这份工作。谁知第二周培训的内容竟然与我们的工作不是那么相关,金融知识,股票、债券、基金、期货搞得头都大了,最后做了个测试,发现自己是板砖型。妈哟,这辈子和砖怕是接下来缘分了啊。

培训的时候上面要求我们分成小组拍电影。是的,你没听错,是拍电影!妈哟,我们除了搬砖特长,哪还会啥子文艺哦,长得还丑,演技又捉急,真想找个地缝钻下去。

没办法啊,上面发话了,不但要拍,还要搞评比,那也得硬着头皮拍了啊。平时又没时间,搬砖时间又长,好不容易的周六,洗白了。

再说说我理了个大圆头,好像招谁惹谁了。那个搞培训的人说最不爱打理的就是我。WTF,我剪了个大圆头就认定我不爱打理了吗,那要是我留一头长发,再烫个卷卷头,岂不是你要说我是最帅的那个😂。

就因为我的这个大光头和不经意间透露出来自己会玩吃鸡,我TM也成了个头。那自然是要写剧本,当导演了啊。幸好以本人当前的造型,恐怕只能演打手。所以自然是不能亲自参演,幸好组里有演技派,要是有最正经奖,我们就获奖了。

第三周,没什么好说的,技能培训嘛。对于我们这种搬砖熟练手来说,食之无味,弃之不可惜,奈何上头说了算,还要考核,那是必须要去听了。工头布置了我些简单的任务,练练手还是不错的,所以这一周也就那样,还行。

如今

上岗了上岗了,满心欢喜啊。有个工友调走了,他的任务我就接手了呗。工头说了,先熟悉熟悉,随便干,追随自己的灵感。我呸,O98K,干就干啊。

是时候切换一下风格了。

磨炼新人最好的办法是把前人的代码给他看,让他绝望。我拿到那份有年代感的代码,还好把持住了,不然可能需要尿不湿。

我一眼望穿,这份代码深藏功与名啊。关于表格布局、evalhtml外写JS、注释、命名什么的不想再多说。借用罗老师的一句话:又不是不能用。

改啊,那就好好改咯。

想起了,最开始想到的是:

  1. 重写DOM结构,代替表格布局。
  2. 重写JS,除了那些没有头绪的黑箱。
  3. 基于配置的形式,一定程度解耦合。
  4. 基于86.375%ES6支持率,引入安全的ES6写法。

后来随着重构的深入,又有了新的想法:

  1. 引入AMD规范,前端模块化。
  2. 运行时构建DOM以及性能测试对比。
  3. 单元测试。

做完这些,第一步的改造计划就差不多了,用了一周的时间完成了这些工作。最大的收获大概是,DOM操作更加熟练了,VS Code的快捷键终于可以MacWindows无缝切换了。

接下来的项目是基于React的,还是老项目,做国际化的改造,以前没有做过类似的功能,还蛮期待的。

如果硬要打分的话:

加班程度:⭐️
新鲜度:⭐️⭐️⭐️
难度:⭐️⭐️
收获:⭐️⭐️⭐️⭐️

这里特别指出,最近利用上班的时间,看了很多书,真的收获很大的。每天翻书,手都翻痛了。

尾巴

又到了尾巴时间,一般灌点鸡汤什么的在这里再合适不过了。鉴于我们可是搬砖工程师,那就讲讲和搬砖相关的故事吧。

我的父亲,多年前从事过搬砖行业。现在虽然没搬砖了,可是也是相关行业。其实搬砖这个行业,真的很累,五十岁不到的人,明显看起来比一般人看起来更老。我父亲没什么文化,但多的是力气,所以他就靠这个把我和姐姐都供到大学毕业,然后啊,他还不稍微停下一点,又得考虑下一步了。

我想像父亲一样,能够独挡一面。

所以啊,有些时候负能量爆棚,总有些乱七八糟的想法,想想自己的家人,最后,既来之,则安之,也挺好的。

我们这种除了会点技术,还真是不会什么了。这是事实,但除此之外,做到更多只有靠你自己。

鸡汤灌输完毕,溜了溜了。

分享到 评论

尾巴

这是故事的结局,我把它叫做尾巴。

是尾巴但也有开头

尾巴起源于我一个不敢想但是蓄谋已久的想法。22岁,我大学毕业,来到了梦想中的城市,找了一份自认为还不错的工作,然后开始奋斗。这几乎是每个大学毕业生的剧本,我也不例外。22岁总会带来点什么,或是我们应该下意识改变些什么。而22岁的我,决定付诸行动,虽然已经蓄谋很久了。

见老朋友啊。

这就是尾巴,但尾巴也有开头。

旅程

毫不夸张的讲,这是一趟漫长的旅程。即使我生活的地点一直向南在变化,就算我们可以选择的交通工具既方便又快捷,虽说没有千里之隔,但就像是回趟家一样。漫长,但充满期待。

路途开始那天就下起了雨,虽说都快七月了,但是上海就像梅雨天一样,几乎每天都会下会儿小雨,或者是太阳雨。傍晚时分,刚坐上火车,雨又开始沥沥淅淅下起来了,我把脸贴在玻璃上,甚至可以感受到火车车轮与钢轨摩擦发出的吱吱声,随着火车越开越快,这种感觉就越发强烈,直到到了忍耐的极限。在火车上的六个小时不长,但却够拿来回忆很多年的故事呢!好在六个小时不长,不然陷入回忆这种事就要发生在我身上了。可又为何会这样,也许是因为除了回忆,什么都不剩下了。

晚上10点,顺利到达目的地,一走出火车站,潮湿的热空气像我袭来,就像在冬季里吸入冷空气一样,吸入这样的空气也会让人顿时提起神来,它仿佛在告诉,你活着。是啊,活着真好!

第二天,很早就起,赶上清晨的前几班公交,离目的地还有很远,换乘,再步行,差不多两小时才到。穿过菜市场,湿漉漉的街道和发出的鱼腥味让我想起了和妈妈为数不多买菜的情景。眼前是一个有点年头的小区,旁边有高架桥,不远处还在绿化施工,这虽然是一片住宅,的的确确和D描述的一样,吵死了!

我环顾四周,茫然写在脸上。我开始打电话,又等了几分钟,一个阿姨向我走来,我认出来了,她是来接我的,旁边还跟着一个小女孩。我赶忙上去打招呼,阿姨看见我也很开心,好久没见到这样的笑容挂在一个中年妇女脸上了,上一个还是半年前的寒假,那个人是我妈。

就这样,我上了楼,一口气爬了六层,到了她家。房子从外面看真不怎么样,但走进真觉得精致啊,客厅厨房都挺宽敞的,这点和我合租的房子真是天壤之别。阿姨问我吃早餐了没,我碍于情面不好说自己饥肠辘辘,上一顿还是在昨天下午吃的,就说自己吃了,阿姨也没多问。

我坐在客厅的沙发上,环顾四周,却没有发现记忆里的东西,心里不禁失落,四年的时间里,也许什么都在发生改变。我和阿姨坐下来聊天,她以为我是D的高中同学,我说不是呢,我是D最好的朋友也是D小学同学,在远在千里的家乡,小学三年级的时候,我们还做过半年多同桌呢!阿姨的震惊完全写在脸上,又有谁能想到,眼前的这个人,竟然是D的小学同学!说道这里,毕竟是同乡人,我们用家乡的方言开始交流。我给阿姨讲我和D的故事,记忆深刻的。这样的桥段在我的脑海里不知过了几遍,语言斟酌了多少次,却没想到,直到真的要说出去的时候,是如此的困难。

好在时间冲淡了这一切,我们都没有太动情。阿姨带我去看了D的房间,这间房子我还是很熟悉的,虽然房间的主人不在了,陈设也变了,但是透过那窗台,望过去就是外面齐平的高架桥。D曾告诉过我,当她无聊的时候,还可以数过往车辆,数到自己不无聊为止。

我问阿姨有没有老照片。

她拿出了一本相册,整整满满的一个相册都贴满了,有多年的老照片,有全家福,还有很多有关D的照片。阿姨在和我一起翻看这些照片,去给我讲有关D的故事。

至始至终我脸上都没有表现出悲伤,直到离开。我谢绝了留下来吃中午饭的好意,阿姨也陪着我下楼,在最后的时间里,我给阿姨说,如果D没离开,可能我们早就见面了。

阿姨叫我以后多来家做客,可是就像是四年前那样,我又有什么理由再来这座城市呢!经过那条菜市场街,我拐了好几道弯,终于走出了小区。一路上,我在想,真的走出来了吧,不然小萝莉都快3岁了!我很欣慰,前所未有的释然。

是尾巴但终究还是结局了

回到新的大本营,迫不及待的开始写这个结局。今天下了好久的雨,肯定积了好多水坑,我打开窗呼吸着还算清爽的空气,听到蛙鸣,一切都是那么安静。我想,是时候让故事告一段落了。

我的这22年来,对我影响最大的三个女性是妈妈,老姐和D。妈妈在我童年的那段时间教会了我太多,善恶美丑,做人准则;有一个姐姐真的很棒,总会收到各种各样的礼物,在最无法沟通的时候,同龄人的姐姐却可以懂我;D,我们在小学就已经相识,到了高中,如果不是有D,恐怕我已经荒废那段最宝贵的时光,然后浑浑噩噩过着日子。

我走不出D离开给我带来的阴影,看似只有在电视剧上才会发生的剧情,发生在了我头上,并且没有一个好的结局。

五年可以忘掉什么?那些看似很有用的高中知识点,我忘了;不常用的邮箱密码,也搞忘了;可是,D的离开,快五年了,我以为我忘记了,可是一旦记起,唯独耿耿于怀。

这一次,我依然没法忘记这一切,毕竟真实存在过,亲生经历过;正是因为忘不掉,才证明我们真正的活着啊,并且要好好活着。我没法忘掉这一切,但我看开了,这就是结局。

分享到 评论

Hello Goodbye & Hello

5月1日,阴天,雾霾挺严重的。下午,戴着耳机,出门;傍晚,下起了雨,躲进快餐店;点了宫保鸡丁和土豆豆角,开始狼吞虎咽,然后,等着雨伞送到;离学校最后的一公里路程,需要十分钟。直到现在,12时,雨还在下,伴随着风。

小长假的最后一天,也是五月的第一天。对啊,五月已经来了。

打开网易云音乐,点开日推,第一首歌就是《Hello Goodbye & Hello》,很早以前看过的番剧《追逐繁星的孩子》ED。此刻我正苦于构思一个标题,所以就用了这个歌名“你好,再见,再也不见”。

在为数众多的看过的动画中,《追逐繁星的孩子》故事讲得不算好,但那句原来是我太孤独直戳内心深处。我想,我何尝不是这样呢,虽然性格不内向,容易和人打成一片,但我还是习惯一个人呆,去健身,躲在网吧打游戏。可我也挺怕一个人的,会因为一个人吃饭吃得特别快,走路也走得特别快,久而久之,给别人留下了不可接近的印象。

五月带给我的印象里就是忙吧,无论是高中还是上了大学,所有的事情都会在五月变得忙碌起来。而这个五月,也就是现在,我却过得非常的悠闲,甚至有点百无聊赖。早早的做完毕业设计,我有很多时间去做很多做感兴趣的事。这样的日子,还会持续两个月。不知道是好是坏。

我的生日一般都在六月,这个时候我呆都在学校,所以这么多年来,我都没怎么过过生日。高中的时候,有时候学习特别忙,都忘记了哪天是五月初三,每次都是妈妈打电话提醒我,让我吃顿好的;上了大学,我更不想让同学们知道我过生日,所以那天我很早就出门,找个自习室好好的学习一天。如果说要有什么不同,那一定是17岁那年,端午节。

至于为什么不同,因为我收到了特别的礼物。为数不多的收到过的贺卡,学生时代追了个遍的小说,画得还算不错的画。

去年寒假回去叔叔家把遗留在那里的高中记忆都翻了个遍,很可惜的是,贺卡不见了;而那本单行本也码在书堆中早已泛黄,我拿走了那本书,把它带在身边,就像那幅画一样。

对于只会画条条框框的我,无法描述那幅画的内容,但站在一个观赏者的角度,还算可以把,仅此而已了。

说起那幅画,我曾经给很多人看过,他们问我画的什么有什么含义,我总是说,我怎么知道啊,就是别人送的礼物而已。其实背后的故事我是知道的,那是我最珍贵的宝物,那是我的记忆啊。

其实记忆才是是每个人最珍贵的宝物。

分享到 评论

前端路由拦截和http响应拦截

问题由来

最近在制作毕业设计的时候,遇到一个问题,那就是用户的访问控制。简单点来说,就是未登录用户只能访问某些特定的页面、API。最初我的想法是用户登录后返回一个凭证,用户以后的每次http请求都带上该凭证,进行验证,只有验证成功才能继续请求。然后在每个页面进行判断,如果用户是未登录或者凭证失效,则进行相应的提示和路由跳转。刚开始的时候,这个方法是完全可行的,但是在开发过程中,随着业务逻辑变得复杂、页面增多,重复代码太多,这样的方式也许并不合适。

如何解决

首先是后端,我使用了jsonwebtoken,用户登录成功都会生成一个具有一定时效的 token,这个token会发回到客户端,并且接下来每次发起http请求,都在http头的authorization字段带上这个token。我这里使用了axios这个http请求库,只需要在拿到token后:

1
axios.defaults.headers.common.authorization = `Bearer ${token}`;

就可以了。

由于在开发过程中涉及到跨域,这里我使用CORS来解决:通过设置一系列Access-Control-Allow-*响应头进行访问控制,上面提到了在请求头的authorization字段中设置token,因此发出的请求都不是简单请求,所以注意在每次发起http请求时,就会自动发起一个OPTIONS请求。

我服务器端用的是Express框架,我们需要写一个中间件来处理每一个请求。处理逻辑为:针对每个OPTIONS请求,直接放行;对于某些请求,如果在白名单中(例如登录、注册等不需要验证的路由),放行;对于其他请求,我们拿到其携带的token,并且进行验证,如果验证通过,放行,否则结束请求,返回未授权。具体的代码如下,这里我使用jsonwebtoken这个package,用于生成token和进行token验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
app.use((req, res, next) => {
console.log('methods' ,req.method);
if( req.method === 'OPTIONS' ) {
console.log('option请求直接通过');
next();
}else {
// 除去某些特定的API,其余的都做token的验证
let { path } = req;
if(path === '/api/users/auth'
|| path === '/api/users/auth_vc'
|| path === '/api/users/check_id_validation'
|| path === '/api/users/regist'
|| path === '/api/users/send_reset_email'
|| path === '/api/users/reset_password'
)
{
console.log('本次请求不需要验证权限');
next();
}else {
const token = req.headers.authorization ? req.headers.authorization.split(' ')[1] : '';
req.token = token;
jwt.verify(token, KEY, (err, decoded) => {
if(err) {
res.status(401).json({ status: 3, error: '用户认证失败', data: '' })
}else {
console.log('验证权限通过');
req.decoded = decoded;
next();
}
})
}
}
})

然后是前端,我想如果能像后端拦截每个请求一样,写一个逻辑拦截所有的相应,并进行处理,信号,axios自带拦截器,我们只需要写我们的逻辑就可以了。我的想法是,拦截每一个相应,如果其状态码是401,那么久提示token失效,并且进行路由跳转。
vue-cli构建的应用为例,在main.js中,下面是实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
axios.interceptors.response.use(data => data, (error) => {
if(error.response) {
switch(error.response.status) {
case 401: {
localStorage.removeItem('token');
router.replace({
path: '/auth',
query: {redirect: router.currentRoute.fullPath}
})
}
}
}
return Promise.reject(error);
})

值得说明的是,如果我们在某个访问的过程中,token失效,我们需要跳转到登录页面,但是想登录过后再跳转回来,所以这里在进行路由跳转的时候,我设置了一个参数, redirect,表示传入当前的路径,当我们登录成功后,在跳转回来即可。

最后是路由拦截,这里我使用了vue-router,其实vue-router的路由对象提供一个钩子函数beforeEach,其会在每一次路由跳转之前,执行这个函数,我们就在这里进行路由拦截。原理很简单,使用一个标志位标明每个路由是否需要用户权限,如果需要的话,我们检查保存在本地的凭证,一般存在localStorage中,如果不含凭证就直接跳转到登录页面。

好了,找到根路由文件,添加:

router.beforeEach((to, from , next) => {
  if(to.matched.some(res => res.meta.requireAuth)) {
    if(localStorage.getItem('token')) {
      next();
    }else {
      next({
        path: '/auth',
        query: { redirect: to.fullPath }
      })
    }
  }else {
    next();
  }
})

这里要注意的是,res.meta.requireAuth是你自己在声明路由的时候自定义的。

总结

差不多,这算是一个比较好的解决方案了。但是有这样一个情况:如果用户凭证有效期是1小时,那么如果我浏览网页超过一个小时了,凭证还是保存在本地的,当我们进行路由跳转的时候,并没有验证凭证是否失效,所以还是会进行路由跳转。这里不用担心,因为进入进入了一个路由后,一旦发起http请求,token失效,http相应拦截就会生效,进而跳转到登录页面。

加油!

分享到 评论

最近这段时间

不知不觉,大学里最长也是最后的一个寒假就快要过完了,而学生生涯也要画上一个句号了,真的好快啊!

还记得寒假带回来几本书,现在才开始翻看;本着要掌握的目标去学习Vue,然后现在才刚刚入门;信誓旦旦说要在家好好健身,虽说不规律,可总算是去做了,收效甚微;寒假总共“吃鸡”40小时,可总算成功吃鸡了。总之,最近(这个寒假)做了很多事,也下定了决心将要去做一些事。

那些做过的事

  • 学习Vue及其技术栈,为毕业设计做准备
  • 继续完善自己的Project
  • 钓鱼!钓鱼!!钓鱼!!!说三遍~
  • 有些事情,向前迈出一步
  • 不懈努力,成功“吃鸡”

“吃鸡”与“吃到鸡”

作为一名“吃鸡”萌新,标配夕阳红枪法,又是老年人视力,那肯定是行走的盒子精无疑啦。可是萌新也有大梦想,那就是吃一把鸡,为了这个目标,一直苦练枪法,终于吃鸡。既然如此,下一步目标是,打上2000分!就看时间允许不允许了😂

学习Vue

毕竟一年多React经验的自信,所以毕设直接选了使用Vue来实现的一个App,那么理所当然的就要在寒假“补课”啦,官方教程半小时过一遍,再花1小时细细过一遍,OK不OK?ojbk!看完教程连个脚手架都搭建不出来!既然如此,还是视频大法好啊,看了差不过2个小时时间的基础教程,再配合上github上的开源项目,差不多get了吧。现在才感叹,当初学React的时候,真是费了好大的劲啊,光是Redux都够你喝一壶的了,最后悟出一个道理:珍爱生命,远离React😂

钓鱼,第一等大事

我为什么那么喜欢钓鱼到现在还是一个未解之谜。我几岁的时候就开始钓鱼了,各种水域,各种鱼类都钓过,毫不夸张的说,我钓过的与鱼少说也是成千上万了吧。寒假一回来没有回老家就在农家乐钓过几次,太好钓了反而无聊。回老家的一个星期也钓了几次,总算过瘾了。以后夏天基本上没机会回家乡想想都可怕,只寄希望于春节少德可怜的假期能够撑起一个钓鱼爱好者的心啦~

我的项目

其实一直有在写一些简单的项目,脑子里想到的就要去试着实现,在学校一直在断断续续做一个关于想法的App,寒假无聊的时候也会一个点一个点去完善。但是倒霉的是,某个电脑管家竟然在清理垃圾的时候把这个proj删了,我还没提交到远程仓库呢,真是气死一个人,果断卸载!所以呢,找个时间得重新起航,也许到时候又会有新的点子呢~

有些事情,得迈出一步

其实这个故事是这样的:你一直暗恋一个女孩很久,在后来的某个时候,你向她表白,她接受了,可是后来由于各种原因虽不说天各一方但也没能走到一起。很多年过去了,你总会在某些特定的时候想起她,你还是忘不掉她。你决心不留遗憾,在某次很愉快的聊天的时候,话题突然一转,你问她:你有男朋友吗?她说:你猜~ 你回答:也许有,也许没有,一半一半吧。她沉默了好一会儿,才憋出几个字:有的哦,都出来上班那么久啦。外面的花花世界,不比得你学校。听到这个意料之中的答案,男孩心中说不出的感觉,对她说了最后一句:打扰了。其实男孩心中从最开始就知道,如果可以把人分类的话,他们从来都不是一类人,从最开始他们就走向了不同的十字路口。至于为什么时常回想起,他也不知道。他迈出了一步,解开了自己的心结。

那些将要做的事

被逼无奈,我要学车


今年回家过年,七大姑八大姨除了问你:找到工作了吗、有女朋友吗、成绩怎么样呢这样的问题以外,学没学车竟然也加入了进来,在他们看来,不会开车的人好像就不能生存以外,所以为了不被念叨,我决心要学车啦,就在接下来的三个月时间里搞定!

对,我要增重

在外人眼里,我172的身高配上快140的体重是再好不过了的,不过我还是要增重,直到长到145,当然,这不是简单的增重而是增肌。所以,是时候努力了。

补课,然后大补考

补一门大二未上的实验课,然后大补考挂掉的《形势政策》,然后毕业!

技术上,继续

除了继续在web开发领域继续摸索深耕以外,还有扩展自己的技术栈,接下来要把大数据、数据挖掘纳入我的技术栈。

其它

比如一定要吃早饭、好好睡觉这种是肯定要做的,无论什么时候。

本来挺喜欢玩《炉石传说》的,可是这个版本快攻横行,打不过术士又没尘加入他们,所以暂时要放弃啦。最近在看两部番剧《紫罗兰永恒花园》和《比宇宙更远的地方》。最近在读一本书叫做《24个 比利》。就这样。

分享到 评论

SQL参数化查询

SQL注入想必是每个人都听过,其原理和XSS攻击很相似,都是把用户的输入当做程序去执行。防御办法也很类似,就是对用户的输入进行转义,但是同样转义十分麻烦,因为SQL注入攻击的方式和变种实在太多,转义需要考虑到的情况也复杂多变;而另外一种方式就是使用参数化查询–Prepared Statements。

SQL注入

在先介绍参数化查询的时候我们先复习一下SQL注入,上面提到其原理是把用户的输入当做了SQL语句程序的一部分去执行,因为我们经常使用字符串拼接来构建SQL语句。

在这里开始演示一下(使用MySQL):

在我的数据库中我数据库中我建立了一个名为urls的表,其结构和数据如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mysql> desc urls;
+-------------+------------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+-------------------+----------------+
| id | int(11) unsigned | NO | PRI | NULL | auto_increment |
| url | varchar(255) | NO | | | |
| insert_time | timestamp | NO | | CURRENT_TIMESTAMP | |
| tid | bigint(20) | YES | | NULL | |
+-------------+------------------+------+-----+-------------------+----------------+
mysql> select * from urls;
+----+-----------------------+---------------------+------+
| id | url | insert_time | tid |
+----+-----------------------+---------------------+------+
| 1 | http://www.limoer.cc | 0000-00-00 00:00:00 | NULL |
| 2 | http://baidu.com/news | 0000-00-00 00:00:00 | NULL |
| 3 | http://do.io | 0000-00-00 00:00:00 | NULL |
| 5 | http://github.iod | 0000-00-00 00:00:00 | NULL |
+----+-----------------------+---------------------+------+

该表有4字段并且有4条记录,现在我们如果想要查询id=1的那条记录,应该这样写:select * from urls where id=1。执行该条语句,正确返回结果,现在我们修改一下这条语句,改成:select * from urls where id=1 and 1=1,执行这条语句,同样没问题,返回结果正常;我们接下来再把and 改成 or再执行,结果出乎我们的意料,我们把所有的记录都查询了出来,id=1的限定条件失效了。至于如何导致其失效,是因为or后面的条件1=1是恒等的,所以前面的限定条件已经不重要了,and也是如此,我们想要获取正确的结果,那么and后面的限定条件必须要正确才可以。

说到这里,其实我们就已经进行了一次SQL注入的攻击,并且窃取了数据库的所有记录(更严重的删库、窃取管理员密码也很easy)!

其实不光是上面演示到的使用and or来进行SQL注入,还有很多神奇的SQL语法让SQL注入有了可乘之机,例如我们常用的union等等。

解决办法

如果我们把上面情景放在实际开发过程中,我们可能现在有一个输入框,用户可以输入任意一个数据来查看某条记录,
服务端的SQL语句也许是这样的:select * from urls where id=${userInput}。如果某个淘气的用户不遵守约定输入了非数字,例如10 or 1=1,SQL语句拼接过后就成了这样:select * from urls where id=10 or 1=1,表中的信息一次被完全暴露!

针对上面的情况,我最想想到的不是转义输入也不是使用参数化查询,而是针对本问题,我们直接对其进行输入验证即可,既然其必须限定用户输入数字,那么在进行SQL拼接之前,对用户输入进行验证即可!

例如,在Node.js环境下,我们可以使用parseInt(userInput)就可以完成对用户输入进行强制性的验证。

第二种也就是最常用的解决办法就是转义,和防御XSS攻击一样,我们需要构建用于转义的函数,对用户的输入进行转义,还是上面的那个例子:

1
select * from urls where `id`= ${id};

如果用户输入1 or 1=1,那么毫无疑问将会导致一次非常严重的SQL注入攻击,现在假设我们已经写好了我们的转义函数escape,我们只需要在进行字符串拼接之前,做一次转义即可。 例如对于用户的输入1 or 1=1经过转义后变成了'1 or 1=1',经过SQL拼接过后则变成了:

1
select * from urls where `id`='1 or 1=1';

不出意外,我们得到了正确的结果。

关于转义函数escape如何实现,这里就不不再多说,很多数据库的驱动工具都带有相应的工具函数,我们在实际开发过程中一定要注意对用户的输入进行转义,来避免SQL注入攻击;当然,如果你使用参数化查询的话,就完全没有必要了。

参数化查询

最开始提到参数化查询的时候,我提到了Prepared Statements也就是预处理语句,其实我们可以把参数化查询理解为预处理,我们把完整的一次SQL查询分成两部分,第一步是预先查询,第二步使用参数得到结果。具体该怎么理解呢,还是接着上面的那个例子,现在我们使用参数化查询执行select * from urls where id=1。其分为两步,第一步执行select * from urls where id=?,注意这里的?,其实代表了未来将要传入的参数;第二步,传入用户的输入作为具体的id值,并且输出结果。这里要注意,因为执行完第一步的时候期待第二步传入的是一个用户的id(这里必须是数字),这时候用户传入的非法输入就不会生效,这也就从根本上杜绝了了SQL注入攻击。

好了,参数化查询(预处理)可以完全避免SQL注入,其还有其他的优点例如更加可读(相比于字符串拼接),多次查询性能会有提升(因为会对预处理语句进行缓存再利用)等。

说了这么多,那么如何使用参数化查询呢?很简单,使用一个支持该特性的数据库连接工具就可以了,比如我们下面要演示的Node环境下MySQL的参数化查询。

Demo

我们在Node环境下进行演示,首先通过npm install mysql2命令安装数据库连接工具,这里是mysql2,能够支持参数化查询。

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const mysql2 = require('mysql2');
const conn = mysql2.createConnection({
host: 'localhost',
user: 'admin',
password: '123',
database: 'news'
});
// 不使用任何防护手段(将导致SQL注入攻击)
const userInput = '1 or 1=1';
conn.query(
`select * from urls where id=${userInput}`,
(err, result) => {
console.log(result);
}
);
// 使用转义(这里默认进行了转义)
conn.query(
'select * from urls where `id`=?',
['1 or 1=1'],
(err, result) => {
console.log(result);
}
);
// 使用参数化查询
conn.execute(
'select * from urls where `id`=?',
['1 or 1=1'],
(err, result, fields) => {
console.log(result);
}
);

尾巴

关于SQL注入和参数化查询就介绍到这里,如果你觉得参数化查询两步走我说得并不明确,你可以使用抓包工具来加深理解;还有最后的Demo,其实query和execute的区别就是一个支持了参数化查询而另外一个不支持;如果你运行Demo,仔细看,区别就藏在里面(Tips:B & T);最后,请总是使用参数化查询!

分享到 评论

我的应聘经历(不断更新中...)

只有在写简历的时候才会明白,真后悔自己平凡的大学四年,没有拔尖的学习成绩、没有丰富的实践经历、也没有牛X的技术,对于大牛而言,自己就是简历收割机,而对于我而言…好吧,如果谁能看得上我,管吃管住就行!可是,时间没有倒带,不会从头再来/感慨。

概括

从8月开始到如今一个多月过去了,简历虽不是海投但还是投了有数十家,除去没有参加笔试的,剩下通过笔试拿到面试的就更少了,接下来我好好回顾一下,算是一个小小的总结吧,虽然到目前还没有找到工作…

某测(通信测试行业)

经历:

这是校招来学校宣讲的第一家企业,很小型的宣讲会,参会人数不多;在简单的介绍企业过后,就直接现场笔试。吐槽下笔试题,融合了C++/前端/智力测试的一张综合试卷,难度不大,我花15分钟做完了试卷上前端相关的试题就离开了,一个小时后就收到通知当天下午面试得通知。

面试(时间50分钟):

面试也安排的特别简单,二面一,连自我介绍都没有(害得我准备好久…)。问题主要有以下几个:

  1. 你了解通信测试行业吗?
  2. 你觉得本公司适合你吗? 这里的时候我直接问了他几个问题然后做出判断,我们都觉得不适合
  3. 你期待的工作方式? 构思以下结合公司实际谈了谈数据可视化
  4. 数据挖掘相关知识。 基本的分类、聚类算法,分词等。
  5. 给我的建议。 推荐我要有自己的想法,最好选择互联网公司,并且赞了我字写得比较好(谢谢!)。

某某网络(初创互联网公司)

经历:

来自于知乎大牛的推荐,一家自认为小而美的公司!投递简历差不多一个月才进行电话面试。面试时间也真是会挑,早上8点过就打来电话(幸好每天都早起!),大概谈了超过一个小时,到目前为止仍然在等结果。

面试:

面试官大概是在上班路上给我打的电话,电话那头有点吵。面试流程也比较常规,自我介绍,介绍项目,目前在做的事,有关于React及其技术栈。当然还包括面试官对公司的介绍,要求我谈对公司发展的看法;后面又聊了前端开发的潮流;有关于SSR、SPA等。最后告诉了我他们公司前端开发团队的现状(规模很小!),问我如何看待,特别是如何快速的融入和承担起相应的责任。

总结:

当了解了他们正在做的事情的时候,我觉得这就是我想要加入的公司。我喜欢小而美的公司!面试过程十分愉快,虽说是等通知但是都快一周了还是没有音讯,大概是挂了吧~

某家网(卖房的?)

经历:

就在中午临时决定去试一试,幸好赶上校车去了宣讲现场。宣讲过程中真的能够感受到这是一家非常了不起和大牛聚集的地方。宣讲完直接笔试,笔试后就等面试通知咯。晚上接到面试通知,第二天在某某咖啡馆参加了面试,最终是倒在终面前。

笔试:

难度四星,10题全算法,对于数据结构和算法没掌握好的同学就是煎熬,我花了一个半小时做完了自己会做的题目,然后还是错过了一家不错企业面试的机会/哭。

面试:

一面一上来就是自我介绍,随便问问。然后十题算法挨个回顾,并且面试官对每道题进行打分(自己得了好多零!),然后一面结束,等通知。

二面已经是下午了,前端方向就我一个人,所以聊了比较久,一个半小时。面试过程中主要聊了:

  1. Java和JavaScript的特性(被我引入了我喜欢JS而不喜欢Java的怪圈…)
  2. 做过最酷的项目(介绍了一下正在开发的视频编辑器)
  3. 从架构角度谈某个数据平台(简历上提到)的建立和开发过程
  4. 如何做情感分析(数据挖掘方面)
  5. 提问环节

吐槽:

在面完二面后又是等通知,十分钟后我去问通过了吗,然后HR小姐姐告诉了过了,等待三面,我当时的那颗心啊,真的高兴,以为自己就要进入这家感觉十分良好的企业了!结果过了几分钟,HR姐姐给我说我没过,然后这就尴尬了😓。总的来说,本次面试的体验还是不错的(主要是中午管饭了!)。

某有(b2b)

经历:

很早很早就投了简历,并且做完测评等着来软件园宣讲。真的到了那一天去现场一看,人真的多!短暂的企业介绍后,就开始了笔试(分前端、Java、基础三套试卷)。结果由于弄错试卷做了前端、基础两套。试卷难度不大,但都是十分容易出错的地方。晚上收到通知,第二天面试。面试过程非常愉快,上午面完下午HR就打来电话说通过了,然后我说考虑一下,最终开始放弃了到手的offer(说好的就去第一家能看上你的公司呢!),到现在好几天了,我有点后悔自己做的决定。

面试:

面试官应该是管理层,年龄40+,基本不问技术方面,谈谈项目,谈谈个人经历,再结合职业测评问问就完了。二面HR问了问家庭状况,是否考研,以及如何看待将要在工作中遇到的一些问题,后面又问道期待薪资(最大的败笔),然后就结束了。

总结:后悔 X N!!!

还有很多…但是…

不知不觉半个月又过去了,期间不间断的参加过很多公司的招聘,但始终没能更进一步。有些时候晚上睡不着觉,就在想,到底是哪里出了问题,没抓住机遇?实力不够?表现不好?… 我不知道。

可是,就在今天,我暂时不用去为自己的将来而担忧,能够有时间去做自己想要去做的事,能够静下心来提升自己。所以,我愉快的做了决定,好比平时做决定那样–洒脱?。

我打电话通知了家人,以往不想让我离家太远的母亲也很高兴,至少无论他们口头上怎么反对我去外地工作,可真当找到工作后,无论在哪里,只有一如既往的支持。

我认为我就是一个平庸(凡?)的人,我每天会花时间在打游戏娱乐上,我也会时不时睡睡懒觉,天气冷了我可能更多的会宅在宿舍。

尾巴里面提到我不会错过第二家看上我的公司,但是我也食言了,可是我真的不会再错过这一个机会了。我准备好来年在人生的下一站,开启我的程序猿人生了。

分享到 评论