lejoy

lejoy 查看完整档案

北京编辑  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

lejoy 提出了问题 · 2019-05-22

解决Chrome发送ajax请求时,status:blocked:devtools

Chrome浏览器发送ajax请求时,调试工具栏里status值:blocked:devtools。
请问是浏览器调试工具阻止了请求吗?什么情况下回导致devtools阻止请求?
谢谢!

关注 1 回答 1

lejoy 回答了问题 · 2019-04-20

请教几个关于单点登入(SSO)的几个疑问?

问题1:假如用户伪造一个令牌,请求系统1。 而系统1不去认证中心校验,怎么知道是否是合法的?
问题2:会话机制。登录后信息放到Cookie里,此后浏览器向同一个域名发请求时,会自动带上的,不需要在代码里实现。你可以打开浏览器调试,自己观察一下。

关注 2 回答 1

lejoy 评论了文章 · 2019-04-12

腾讯大厦与我有个约定(面试精华帖)

在一个雨蒙蒙的清晨,百般无聊的闲逛中,突然回忆起了我这一生中的第一次面试经历。虽然结果是以失败而告终,但此时此刻的回忆,带给我的并不是失败而是成长。

作为一名实习生,我深刻的感受到在校园与社会夹缝中生活的不易。也十分的幸运,我还有足够的青春与活力驱动着我去学习,让我的未来不再遥不可及;让我能在社会的这份土壤里扎根成长。

clipboard.png

这一次的面试地点是成都腾讯大厦,对于我这类常在农村走,从未上过街的学生党来讲,我真的被眼前的惊呆了(没见过世面)。门口的迎宾,高大帅气;前台的女士,仪态端庄;一旁的植物,生机勃勃;楼道的电梯,金碧辉煌;我站的地板,闪闪发光。我内心中油然而生了一份自豪感,如果以后我能在这儿上班。那简直是哇!塞!

一瞬间我就到达了指定楼层,这办公环境真的是哇塞!哇塞!超级nice!我艹,这前台小姐姐这么漂亮,我艹,这HR小姐姐好靓啊!比学校的妹子还乖!(我翻不到什么词汇来形容了)。

clipboard.png

很快我拿到了一份笔试题;

1.请描述下状态码304?(5分)

表示浏览器端有缓存,并且服务端未更新,不用向服务器端请求资源。

2.写出5种css隐藏元素的办法(10分)

1.opacity: 0;

2.visibility: hidden;

3.display: none;

4.position: absolute;
top: -9999px;
left: -9999px;

5.clip-path: polygon(0px 0px,0px 0px,0px 0px,0px 0px);

我只写出来了4种。第5种确实没遇到过,也没有想到过。

3.cookies与session有什么区别?(5分)

由于http请求是无状态的,需要cookie来做身份验证
1.cookies由服务端创建,发送给浏览器端,当用户发出请求后,带上cookie发送给服务端做验证。
2.来回传递过程中,占用带宽,消耗网络资源,并且容易被中间人获取或浏览器端用户篡改十分不安全
3.cookies大小只有4k

1.session主要存在于服务端,不会被发送到浏览器所以很安全
2.如果没有设置过期时间,在会话结束后session会自动消失
3.session主要用于服务端保存请求信息的机制

答得不够全面,所以请小伙伴们自行查阅资料

4.实现一个方法,找出一个数组中重复的元素(10分)

举例

arr = [1,2,3,4,1,1,2,4,4]

输出 [1,2,4]
Array.prototype.repeNum = function(){
    let new_arr = this.sort();  //先排序
    let res = [] ;
    for( let i = 0 ; i < new_arr.length ; i++){
        if(new_arr[i] == new_arr[i+1] &&    //判断是否重复,是否已经放入容器
        new_arr[i] !=new_arr[i-1]){
            res.push(new_arr[i]);
        }
    }
    return res
}

因为题目上说的要实现一个方法,所以我考虑到是给array原型加一个方法

5.将这段英文this is a pen首字母大写(10分)

法一:
function bigLetter(str){
let newArr = str.split(" ").map((v,i)=>{
  return v.slice(0,1).toUpperCase() + v.slice(1)
})
return newArr.join(" ")
}

法二:
function bigLetter(str){
bigStr = str.toLowerCase().replace(/\b\w+\b/g, function(word){
  return word.substring(0,1).toUpperCase()+word.substring(1);
});
return bigStr; 
}

由于这道面试题,曾经遇见过,所以给出了两种方法。能秀的时候绝对不马虎

clipboard.png

6.请写出你常用的10个linux命令并说明作用(20分)

7.请写出你常用的5个git命令并说明作用(15分)

最后两题因为时间比较久远了,有点忘却了。但记得考察的是什么

8.关于Promise的题(10分)

我印象中有,然后输出什么
Promise.then()
Promise.resolve(1)
Promise.catch()

9.react向子组件传状态(15分)

constructor(){
this.state = {
    name:'xxx'
}
}
<Person data={this.state.name} />

下面是Person组件
<div data={this.props.data} />

还有一个空我记不得了,反正一空5分

然后交给了HR,过了一会儿
HR:今天先回去,后面会在3天内告诉你笔试结果。
我:多少分才算过呢?
HR:60分

我一丝不舍的被送到了门口,唉,好想在这儿多待一会儿,哪怕是让我在这儿干站到我都愿意阿!
唉!回去了

clipboard.png

临近5:30时分,我接到了电话,说我笔试通过了,请问明天下午2点有没时间来面试?
对于我们这类无业青年来说,除了时间,我一无所有。

第二天

相同的时间相同的地方,我却走错了地方,原来成都腾讯大厦有AB两栋。马叔叔,你真有钱

clipboard.png

又是那高大帅气的迎宾;仪态端庄的前台;生机勃勃的植物;金碧辉煌的电梯;闪闪发光的地板,这个地板简直比我脸还干净。
又是那好看到爆的前台小姐姐,又是那漂亮到爆的hr。在如此炎热的8月,我一口就喝下了前台小姐姐送来的水,但是我的内心还是十分的紧张,丝毫没有缓解的迹象。我的腿情不自禁地抖起来,我的手不停使唤地去阻止腿的抖动,然后他们一起抖了起来,

clipboard.png

随后,HR与面试官一同走了进来,我内心暗想这是什么情况?难道HR面和技术面同时进行?HR拨通了一个电话,对方应该是另一个部门的负责人,然后HR说明到有两个部门都需要前端实习生,所以面试同时进行。我暗自高兴那我的胜算更大啦!我的紧张情绪终于得到了一丝缓解。

面试正式开始(由于题目的答案,并不固定所以我就不作答了,而且我个人认为当时也回答的相当不好,所以被pass掉了)
面试官:
1.先做个自我介绍吧!

2.看你项目你用过react,那你来说说react与vuejs的区别

3.你能说说react的虚拟DOM吗?

4.你这个项目中你负责开发了哪些模块?能说说你主要的开发流程吗?

5.项目中有没有用过Eslint

6.来讲讲http?

7.http请求头有哪些属性

8.说说GET与POST的区别

9.知道浏览器缓存吗?

10.图片懒加载能手写一下吗?

11.函数节流与防抖

12.讲讲怎么用Promise

13.linux如何修改文件权限

14.有了解过webpack吗?能说说吗?

15.loader与plugin的区别?

最后一个问题,你有什么想问我的吗?

我在网上看到加速乐是成都团队开发的,加速乐主要有什么用?用了什么技术栈

面试官:这个产品我可能讲的话,会讲很久。所以你还有没有什么其他想问的?

我:请问面试官你贵姓?
(虽然带了工牌,我还是没能看清楚)
面试官:XX

面试官:你稍等一下

一会儿HR告诉我,你先回去,后面我们会给你答复。

快到门口的时候,我回头问,是不是凉凉了?

HR:技术部门还在商量,暂时还不清楚。

我又依依不舍的,哪怕是让我多站会儿我也愿意啊。

在回家的路上,我没有骑摩拜单车,而是选择一个人在偌大的城市街头游走。我不断地思索刚刚面试过程重中有哪些回答不好的地方。我一直在等待那个5点多会打过来的电话,结果6点了,我的手机安静的像个睡着的婴儿。我还怀着一丝侥幸猜想,可能还在加班哦。

直到夜晚的降临,我也的懂得了这份弦外知音。这次的失利,虽然对我的打击很大但是再大也浇不灭我执着追梦热爱前端的热情,也阻挡不了我更加努力的步伐。

clipboard.png

收拾好我失落的情绪,到楼下点了份最喜欢吃的鱼香肉丝炒饭,为这次面试旅程画上一个句号。

几个月过去了

现在的我,回想当时,我不禁的发笑。人总是在不断成长,就算跌倒了,拍拍身上的尘土,还是会向前奔跑。

感谢记忆,我将永远记住你带给我的一切,你留在我❤间无论是忧伤还是快乐,现在或将来对我来说已是甜蜜,为此我要永远怀念你,感谢你❤

clipboard.png

查看原文

lejoy 赞了文章 · 2018-08-01

记一次删除Git记录中的大文件的过程

最近在开发一个新应用,有一天在gitlab上clone代码的时候发现我的应用竟然有170+M,明明是一个全新的应用,代码都没有几行呢,为什么会有这么大呢?

后来经过了解Git的原理,解决了这个问题,把相关内容记录下来。分享一下。

Why

我的一个新应用竟然要170+M,这是打死我我也不会信的,于是就开始分析为什么会这么大。

step 1. 把代码拉到本地

git clone git@github.com:hollischuang/Architecture-Evolution.git

只是用这个地址举例,实际并不是这个项目。

step 2. 查看哪个文件占用的空间比较大

$cd Architecture-Evolution
$du -d 1 -h
 174M   ./.git
 264K   ./test
 96K    .

于是,发现是.git目录自己就占用了174M,了解Git的人都知道,.git目录是git自己生成的,记录了git仓库的相关信息的。看到这里其实并不难知道原因。

Git 维护着一个微型的文件系统,其中的文件也被称作数据对象。所有的数据对象均存储于项目下面的 .git/objects中。

经过我的验证,确实是.git/objects这个文件夹中的文件占了磁盘上174M的空间。

也就是说,只要我有一次将一个大文件误提交了,那么即使我后面把它删除了,但是,实际上在.git中,这个文件还是存在的,虽然我们可能再也不需要他了,但是他还在那里默默的存在着。。。

Git与大部分版本控制系统的差别是很大的,比如Subversion、CVS、Perforce、Mercurial 等等,使用的是“增量文件系统” (Delta Storage systems), 就是说它们存储每次提交(commit)之间的差异。Git正好与之相反,它会把你的每次提交的文件的全部内容(snapshot)都会记录下来。这会是在使用Git时的一个很重要的理念。

也就是说,如果我又一次把一个大文件务提交到git仓库中了,那么,下次提交时,即使你只改动了某个文件的一行内容,Git 也会生成一个全新的对象来存储新的文件内容。


因为以上两个特性,我回想起我的一次手残行为:
刚刚创建一个应用之后,我快速的写完代码,编译,运行,发现没啥问题之后,我准备先把他发布掉,于是我开始创建git仓库,并尝试把代码提交上去,这时我并没有创建.gitignore文件,我直接git add . git commit -m 'init' git push一气呵成的执行了熟悉的操作。

相信聪明的人已经发现了,逗比啊,我在编译代码之后,会有很多jar被我down到target目录下。我直接git add.把target下面的jar包,war包等这些也直接提交了。。。虽然后面我意识到,并且删除了这些文件,然后再次提交,但是由于刚我们说过的原因,这些文件依然占用着我的空间。。。

更多关于git的原理内容参见:Git 内部原理

How

问题已经定位到了,接下来就是要解决问题了。如果对git的原理及命令了解的比较多的话,这个问题还是比较好解决的,由于当时博主并不十分了解git的原理,所以做了一些知识储备之后才开始动手的。(Git 之术与道 — 对象、为什么你的 Git 仓库变得如此臃肿

Step 1 查看哪些历史提交过文件占用空间较大

使用以下命令可以查看占用空间最多的五个文件:

git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"
rev-list命令用来列出Git仓库中的提交,我们用它来列出所有提交中涉及的文件名及其ID。 该命令可以指定只显示某个引用(或分支)的上下游的提交。

--objects:列出该提交涉及的所有文件ID。

--all:所有分支的提交,相当于指定了位于/refs下的所有引用。

verify-pack命令用于显示已打包的内容。

step 2. 重写commit,删除大文件

使用以下命令,删除历史提交过的大文件:

git filter-branch --force --index-filter 'git rm -rf --cached --ignore-unmatch big-file.jar' --prune-empty --tag-name-filter cat -- --all

上面脚本中的big-file.jar请换成你第一步查出的大文件名,或者这里直接写一个目录。

filter-branch命令可以用来重写Git仓库中的提交

--index-filter参数用来指定一条Bash命令,然后Git会检出(checkout)所有的提交, 执行该命令,然后重新提交。

–all参数表示我们需要重写所有分支(或引用)。

在重写提交的过程中,会有以下日志输出:

Rewrite 6cdbb293d453ced07e6a07e0aa6e580e6a5538f4 (266/266)
# Ref 'refs/heads/master' was rewritten

如果显示 xxxxx unchanged, 说明repo里没有找到该文件, 请检查路径和文件名是否正确,重复上面的脚本,把所有你想删除的文件都删掉。

step 3. 推送修改后的repo

以强制覆盖的方式推送你的repo, 命令如下:

git push origin master --force

step 4. 清理和回收空间

虽然上面我们已经删除了文件, 但是我们的repo里面仍然保留了这些objects, 等待垃圾回收(GC), 所以我们要用命令彻底清除它, 并收回空间,命令如下:

rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now

至此,我们已经彻底的删除了我们不想要的文件。

原文链接

查看原文

赞 36 收藏 26 评论 1

lejoy 回答了问题 · 2018-07-23

菜鸟来问一个django面试时的问题

1、网页加载慢的问题:
1️⃣通过17ce、站长工具等第三方检测工具,测试访问该网页,得到具体解析、建连、第一字节、响应时间,看看哪个环节慢;
2️⃣如果用了nginx,那么在nginx日志里打印"$upstream_response_time" "$request_time"这两个时间,基本就可以定位出到底是不是程序响应慢了;
3️⃣在相应代码里,一些可能比较耗费时间的代码前后打印时间戳,从而知道到底哪里的问题;
2、学习的问题:
对于一个没有工作经验的人来说,公司更多的是考验他的学习能力,思维能力,以及相关基础知识的掌握情况。当然,如果还能凭自己自学完成一个完整的项目,就更好了。

关注 5 回答 4

lejoy 评论了文章 · 2018-07-18

普通网站防暴力破解的新设计

前端防暴力破解的一个设计

Demo 地址

https://github.com/GitHub-Laz...

描述

传统的防范暴力破解的方法是在前端登录页面增加验证码, 虽然能有一定程度效果, 但是用户也跟着遭罪, 验证码越复杂, 用户登录的失败率越高

于是最近我想了一个新的设计, 前端在登录时采用解密的方式获取密钥, 把密钥与表单以前发往后端, 用密钥来代替验证码

具体细节如下

设计

  • 用户在登录页面输完用户名密码, 点击登录
  • js 向后端请求密文
  • 后端生成一个随机字符串和一个指定范围内的随机数
  • 正向拼接 随机字符串 和 随机字符串随机数的加密 得到密文rstr+MD5(rstr+rint)
  • 反向拼接 得到 密钥 MD5(rint+rstr)
    randomString = Utils.getUUID();
    randomNumber = Utils.randomInt(range);
    privateText =  randomString + Utils.md5(randomString+randomNumber);
    privateKey= Utils.md5(randomNumber+randomString);
  • 将密文传给前端
  • 前端通过循环破解随机数
    let randomString = result.substring(0, 32)
    let valueString = result.substring(32)
    let answerString
    for (let i = 0; i < range; i++) {
        let s = crypto.createHash("md5").update(randomString + i).digest('hex')
        if (s == valueString) {
            answerString = crypto.createHash("md5").update(i + randomString).digest('hex')
            break
        }
    }
  • 把得到的密钥和表单一起传个后端
  • 后端验证密钥的真假

测试

经过测试10000次内md5加密前端用时不超过300ms, 用户察觉不到, 但是暴力破解的难道确增加了几千倍, 这意味这本来一个小时能破解的网站, 现在可能要一年才能破解

优势

  • 整个流程对后端带来的压力几乎为0
  • 用户无需输入验证码
  • 前端延时极小(对人来说)
  • 对暴力破解影响极大
  • 只需添加部分代码, 无需更改现有的代码
  • 条件可控, 随机数的范围完全由后端决定
欢迎关注我的博客公众号
图片描述
查看原文

lejoy 评论了文章 · 2018-07-18

普通网站防暴力破解的新设计

前端防暴力破解的一个设计

Demo 地址

https://github.com/GitHub-Laz...

描述

传统的防范暴力破解的方法是在前端登录页面增加验证码, 虽然能有一定程度效果, 但是用户也跟着遭罪, 验证码越复杂, 用户登录的失败率越高

于是最近我想了一个新的设计, 前端在登录时采用解密的方式获取密钥, 把密钥与表单以前发往后端, 用密钥来代替验证码

具体细节如下

设计

  • 用户在登录页面输完用户名密码, 点击登录
  • js 向后端请求密文
  • 后端生成一个随机字符串和一个指定范围内的随机数
  • 正向拼接 随机字符串 和 随机字符串随机数的加密 得到密文rstr+MD5(rstr+rint)
  • 反向拼接 得到 密钥 MD5(rint+rstr)
    randomString = Utils.getUUID();
    randomNumber = Utils.randomInt(range);
    privateText =  randomString + Utils.md5(randomString+randomNumber);
    privateKey= Utils.md5(randomNumber+randomString);
  • 将密文传给前端
  • 前端通过循环破解随机数
    let randomString = result.substring(0, 32)
    let valueString = result.substring(32)
    let answerString
    for (let i = 0; i < range; i++) {
        let s = crypto.createHash("md5").update(randomString + i).digest('hex')
        if (s == valueString) {
            answerString = crypto.createHash("md5").update(i + randomString).digest('hex')
            break
        }
    }
  • 把得到的密钥和表单一起传个后端
  • 后端验证密钥的真假

测试

经过测试10000次内md5加密前端用时不超过300ms, 用户察觉不到, 但是暴力破解的难道确增加了几千倍, 这意味这本来一个小时能破解的网站, 现在可能要一年才能破解

优势

  • 整个流程对后端带来的压力几乎为0
  • 用户无需输入验证码
  • 前端延时极小(对人来说)
  • 对暴力破解影响极大
  • 只需添加部分代码, 无需更改现有的代码
  • 条件可控, 随机数的范围完全由后端决定
欢迎关注我的博客公众号
图片描述
查看原文

lejoy 评论了文章 · 2018-07-18

普通网站防暴力破解的新设计

前端防暴力破解的一个设计

Demo 地址

https://github.com/GitHub-Laz...

描述

传统的防范暴力破解的方法是在前端登录页面增加验证码, 虽然能有一定程度效果, 但是用户也跟着遭罪, 验证码越复杂, 用户登录的失败率越高

于是最近我想了一个新的设计, 前端在登录时采用解密的方式获取密钥, 把密钥与表单以前发往后端, 用密钥来代替验证码

具体细节如下

设计

  • 用户在登录页面输完用户名密码, 点击登录
  • js 向后端请求密文
  • 后端生成一个随机字符串和一个指定范围内的随机数
  • 正向拼接 随机字符串 和 随机字符串随机数的加密 得到密文rstr+MD5(rstr+rint)
  • 反向拼接 得到 密钥 MD5(rint+rstr)
    randomString = Utils.getUUID();
    randomNumber = Utils.randomInt(range);
    privateText =  randomString + Utils.md5(randomString+randomNumber);
    privateKey= Utils.md5(randomNumber+randomString);
  • 将密文传给前端
  • 前端通过循环破解随机数
    let randomString = result.substring(0, 32)
    let valueString = result.substring(32)
    let answerString
    for (let i = 0; i < range; i++) {
        let s = crypto.createHash("md5").update(randomString + i).digest('hex')
        if (s == valueString) {
            answerString = crypto.createHash("md5").update(i + randomString).digest('hex')
            break
        }
    }
  • 把得到的密钥和表单一起传个后端
  • 后端验证密钥的真假

测试

经过测试10000次内md5加密前端用时不超过300ms, 用户察觉不到, 但是暴力破解的难道确增加了几千倍, 这意味这本来一个小时能破解的网站, 现在可能要一年才能破解

优势

  • 整个流程对后端带来的压力几乎为0
  • 用户无需输入验证码
  • 前端延时极小(对人来说)
  • 对暴力破解影响极大
  • 只需添加部分代码, 无需更改现有的代码
  • 条件可控, 随机数的范围完全由后端决定
欢迎关注我的博客公众号
图片描述
查看原文

lejoy 评论了文章 · 2018-07-17

普通网站防暴力破解的新设计

前端防暴力破解的一个设计

Demo 地址

https://github.com/GitHub-Laz...

描述

传统的防范暴力破解的方法是在前端登录页面增加验证码, 虽然能有一定程度效果, 但是用户也跟着遭罪, 验证码越复杂, 用户登录的失败率越高

于是最近我想了一个新的设计, 前端在登录时采用解密的方式获取密钥, 把密钥与表单以前发往后端, 用密钥来代替验证码

具体细节如下

设计

  • 用户在登录页面输完用户名密码, 点击登录
  • js 向后端请求密文
  • 后端生成一个随机字符串和一个指定范围内的随机数
  • 正向拼接 随机字符串 和 随机字符串随机数的加密 得到密文rstr+MD5(rstr+rint)
  • 反向拼接 得到 密钥 MD5(rint+rstr)
    randomString = Utils.getUUID();
    randomNumber = Utils.randomInt(range);
    privateText =  randomString + Utils.md5(randomString+randomNumber);
    privateKey= Utils.md5(randomNumber+randomString);
  • 将密文传给前端
  • 前端通过循环破解随机数
    let randomString = result.substring(0, 32)
    let valueString = result.substring(32)
    let answerString
    for (let i = 0; i < range; i++) {
        let s = crypto.createHash("md5").update(randomString + i).digest('hex')
        if (s == valueString) {
            answerString = crypto.createHash("md5").update(i + randomString).digest('hex')
            break
        }
    }
  • 把得到的密钥和表单一起传个后端
  • 后端验证密钥的真假

测试

经过测试10000次内md5加密前端用时不超过300ms, 用户察觉不到, 但是暴力破解的难道确增加了几千倍, 这意味这本来一个小时能破解的网站, 现在可能要一年才能破解

优势

  • 整个流程对后端带来的压力几乎为0
  • 用户无需输入验证码
  • 前端延时极小(对人来说)
  • 对暴力破解影响极大
  • 只需添加部分代码, 无需更改现有的代码
  • 条件可控, 随机数的范围完全由后端决定
欢迎关注我的博客公众号
图片描述
查看原文

认证与成就

  • 获得 133 次点赞
  • 获得 20 枚徽章 获得 1 枚金徽章, 获得 5 枚银徽章, 获得 14 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2017-04-14
个人主页被 2k 人浏览