0%


最近看了李笑来先生写的《区块链小白书》对其中的理解一个新事物正确的姿势在此做一个备忘。

1. 不要滥用类比

你将要尝试着学习并理解的,是一个前所未有的重大创新,其中有很多你一下子难以理解透彻的概念,很少有人能一下子全都弄明白……

在这样的时候,人们会不由自主地抄近路走捷径 —— 滥用类比:

“哦! 我明白了,这就好像是……”

比如,你经常会看到人们挣扎着理解了半天,突然冒出一句:“哦,我懂了,比特币就是电子黄金!” 类比是约等号(≈),而“这就是”是等号(=),约等号和等号之间的差别有时甚至超过十万八千里。 比特币与电子黄金之间的关系甚至干脆就谈不上是约等于…… 全然不是一个东西。

在理解全新事物的时候,滥用类比的危害非常大,因为你压根就找不到什么过往已经存在的东西真的和这个创新竟然一模一样 —— 否则,它也不可能被称为创新了,是不是?

这种不恰当的类比被滥用多次之后,就再也没办法形成正确的理解了 —— 因为理解一个创新需要理解多个前所未有的概念,每个都做了不恰当的类比之后,多次非常不恰当的约等于拼接起来之后,无论如何都没办法达到一个与正确理解相近的效果。

请务必注意,每次你的脑子里不由自主地冒出 “这就好像……” 这个念头的时候,你都要把它强压回去。

2. 重复重复再重复

遇到暂时无法理解的概念,不要担心、不要纠结、不要停顿,你要做的事情很简单:

  • 继续读下去;
  • 读完之后再重复读很多次……

这是学习任何新知识或者在任何新领域探索的 “必杀技”。这背后有一个重要的原理:

绝大多数难以理解的知识,是因为它内部有很多 “前置引用”。

所谓的前置引用,就是一个在后面才能深入理解的概念竟然在此之前已经被引用了,导致的结果是学习者总是处于懵懂的状态。学校里的知识却不是这样的,学校里的知识总是线性层层递进的,理解了前面,就能理解后面…… 关于 “前置引用”。

“硬着头皮读完,而后重复读很多次” 这个策略,就是可以轻松突破 “前置引用” 所设置的障碍。这个技巧,事实上可以用在任何领域。

3.借助群智的力量

快速掌握新知识,快速适应新领域,还有个重要的技巧,就是借助群智的力量。事实上,在学校里,你早就应该发现这个技巧了 —— 如果你能跟那些学霸经常聊天,经常玩耍,你就会发现总是在不经意之间,很多重点难点就那样轻而易举地被解决掉了……

这首先因为人是社交动物,然而更为重要的是,交流这个东西,随意的交流总是比刻意的交流更为有效 —— 因为随意的交流总是刻意解决那些连你自己都没意识到的问题…… 可偏偏,这些你自己意识不到的问题恰恰是最重要甚至最关键的问题。如果不借助这种群智的力量,很难想象还有什么办法可以解决这种隐秘的关键问题。

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。

背景

过去一年多的时间,整个产品是从0到1的,整个前端团队也几乎是从0到1(大多都是后端转的前端),被产品迭代的车路推动,滚滚向前,处于野蛮生长的阶段。最近产品大体进入了一个思考过去未来的阶段,相对较平缓。可以有喘息的时间干点想干的事情了。

你知道的,干一行爱一行,既然在前端了就想着咋个把它做的更好,因为以前做后端,后端的工程化的工具箱(CI、CD、监控…有一大堆实践)是很成熟的也较容易搭建起来,不过前端相对就很陌生了,据说也没那么容易。

记录

刚好关注了【前端早早聊】,发现里面有这部分的内容,盗了两张图,让我对前端工程化有了很宽的认识,做个记录,后续慢慢实践。

本文引用的图片,如有侵权请联系我删除。

最近看《圆桌派》聊的一个话题斜杠:理想还是欲望?一专还是多能?。想在这儿随便说说。

这个词其实前两年说的比较多,当时另一个说法是一个人的标签很多。为什么出现的频率高,也流行,更多的原因是在于那其实是大大多数的梦想。

里面窦先生说了一下,欲望和理想的区别:一定要结果的就是欲望,热爱过程的是理想。所以对于追求斜杠,你是出于欲望还是理想?从我个人来说,我对斜杠的追求我归为欲望,因为很显然我是需要结果的,不管是物质上的还是精神上的我都是有所求的。

我一直认为,斜杠青年:其实是一个很奢侈的一个愿望。

我比较俗啊,我对斜杠的定义是,每个斜杠都应该是一份事业且他们是相互独立(跨界)的,就像《圆桌派》里说的一样你虽然干了很多份事业但是其实他们都是有关联性或者有递进性的这其实不算是斜杠,因为你始终还是在那个圈里。

既然是事业那就肯定会有付出和回报当然咱们谈的不仅限于钱,最起码你要花时间和精力去做,且会收到反馈。人的时间和精力都是有限的,你把有限的时间和精力花在了多个不同的行业,且都得到反馈,这才算是斜杠。

比如你上午卖炒河粉,下午coding,晚上酒吧驻唱。这我觉得可以说是:餐饮/互联网/演艺,三个斜杠。

所以为什么说斜杠是很奢侈的,首先你的精力要跟上,其次你的时间能自己做主,然后你还得技术过硬。当然跟现实生活中一样奢侈品再贵,也总有些人是能消费的。所以不是说斜杠就没有,只是那是很小的一部分。

大家别把斜杠玩坏了,也别一味的飘飘然的追求斜杠,很多时候你自己要先静一静想一想,别听风就是雨的,不仅飞不高还摔得疼。

就算你有这个欲望,不得现有实力和条件吗,先让自己有这些条件然后再想吧。

延宕其实直白的说就是拖延的意思,有人就感觉了,装逼非要搞个不常见的,就是因为不常见所以你才会好奇啊,才会去查一下这个词时代表什么意思。良苦用心在于为了加深印象撒。

正文

此篇内容源起最近要准备进行一次分享,筛选分享主题时,想到了拖延,首先我自身就有这个问题,然后我敞开怀抱感受了一下,身边很多人都或多或少存在拖延的问题。

目录

  • 拖延原因分析
  • 拖延的特征
  • 造成的危害
  • 怎么破

首先这篇不是一个从心理学角度写的东西,当然咱也没这个段位。这是一个不严谨但具有严重个人色彩的分享,只在于刨析自己从而能给朋友们提供一些思考和建议。

拖延原因分析

白话点说可能有下面四个原因:

  1. 对成功所需的能力缺乏自信
  2. 对要去完成某个任务有反感心理:认定做事的过程中会遭遇很多困难,结局也会很惨
  3. 目标和回报太遥远,感受不到对我有什么意义
  4. 无法自我约束,例如容易冲动和分心

加粗部分是我认为对我影响最突出的部分。

首先咱们得说导致拖延的因素有很多,具体你是哪一类,你可以买本《拖延心理学》对号入座。我暂时认为自己时拖延早期患者,所以列出的主要是自己审视有的。

目标和回报太遥远,感受不到对我有什么意义

先分析一下,目标和回报太遥远,感受不到对我有什么意义,这个点其实很有意思,你回过头看一下自己列的目标也好还是flag之类的…,大多数都会有一个比较共通的点,那就是列的太大太虚,然后也没有反馈的环节。

上图所示就是以前我列的目标,注意看打勾的标识完成的,红圈的表示未达成的。我来自我检讨一下啊,首先打圈的一看就不符合smart原则,当然也没法用PDCA那套。第二个原因是这几个都没有进行反馈设定,这就让你总感觉这个目标好像老离我挺远,慢慢的就觉得没意思了,也没用积极性了。

但是相反打勾的我都完成了,主要有两方面的原因。

  1. 这几个都是有明显的反馈环节的,比如团队分享,首先意义对我和对同事而言都是正向的。分享完之后也能收到同事给与的一些讨论和评价,这也是一个反馈的环节。这就让这件事变得有结束有结果有意义了,当然就有积极性。
  2. 这件事很具体,也比较小,跨越的周期不长,比较符合smart原则,事情就变得可达。
无法自我约束,例如容易冲动和分心

先根据 Tim Urban在TED的演讲,刨析一下拖延时的大脑活动情况,我觉得真是讲到我心里去了,具体大家可以搜一下演讲的名字叫<你有拖延症吗>。

如上图在有拖延症的大脑里会有一只Monkey(分心/诱惑),它经常会跳出来,告诉你其实你的时间还有很多,要不我们逛逛YouTobe、BiliBIli…,它会不断的骚扰你,最终你会沦陷让其掌握大脑。其实就是抵御不了诱惑,容易分心。那什么时候我们会突然警醒呢,就是有一个东西出现的时候,如下图,这个东西叫恐慌。它一来Monkey就被吓跑了,但是往往这个时候,已经来不及了,被动了。

拖延特征

我们说说怎么辨别,你是否存在拖延这个问题。

  1. 看它是不是让你烦恼不已

    内在结果:必须承受某些内在情绪的折磨,从恼怒、后悔到强烈的自我谴责和绝望

    外在结果:影响家庭、工作、社交….

  2. 在一开始,你往往信心满满

    在完成目标的一开始,往往信心满满 ,但是最后其实都不能很好的的完成或者说完成不了,往往整个过程如下图。

  3. 自我

    自我价值感 =能力(具有独立性,反对受控制) =表现(通过拖延,“我”说了算),不愿意遵守那些不是我们自己所制定的规则并顺应别人的需要 。

  4. 追求完美

    咋一看还挺牛x,原来拖延还有这么美丽的特征,但是注意我们这儿说的是适应不良型的完美主义,“完美主义”者往往对自己期待过高,不够现实,当无法实现这样的要求是,就不知所措。失望之余,通过拖延让自己从中退却。适应不良型的完美主义,对自己的要求跟对自己的表现的期待之间存在一种矛盾。

拖延的伤害

怎么破

说了那么多,最终咱们得找到解法,当然前提是你有拖延困扰并且你愿意付诸行动改变这个毛病。

以下是我亲身实践且认为效果良好的方子,现在我也还在这么做,这是个持久战别想着10天半个月就有多大的改变,也别相信什么21天就能养成xx习惯,普通人就踏踏实实干就行了。

破法1:你得接受
  • ​ 接受自己能力有限这个事实得人不太会为此过于烦恼 。
  • ​ 接受遵守那些不是我们自己所制定的规则并顺应别人的需要。
破法2:和原因对上号
  • 看看这方面的书以及专业的一些心理视频或者找心理方面的人士咨询,找到自身造成的拖延的原因,才能对症下药,人是个体,个体就有差异千万别总去套别人那套方法论,要找到适合自己的。
破法3:明确的目标与可行性的计划

找到一个目标,然后将它分解成几个小的步骤,跨出小小的第一步,学习怎样记录时间,以及如何优化周围环境使之向有利于成功的方向推进。

  • 目标smart且够小,可达。既非常小,又可以给你带来进步感和成就感。

  • 执行过程中引入监督、奖惩机制

  • 整个执行目标的过程按照PDCA不断循环

  • 训练强大的执行力

    执行能力的基本要素:注意力控制、 认知弹性、 目标设定、 信息处理

    1.启动任务(起始,产生行动的想法)。

    2.维持注意力(持续跟进,专注于一个事项)。

    3.抑制冲动(在行动前有所思考,而不是马上反应)。

    4.转换注意力(从一个事项到另一个事项,转变关注的焦点,有弹性地加以回应)。

    5.流程记忆(记得计划、指令和以前学到的知识,在学习新知识和应对新环境的时候可以记起和运用到旧的知识)。

    6.情绪控制(调整和管理情绪)。

    7.组织材料(获取所需的材料,并依序编排)。

    8.自我监测(具备自我评价的相应语言能力,在必要的时候能够通过自我交谈闯过难关)。

    9.时间管理(时间意识,以及对待时间的务实态度)。

    10.计划(按优先次序考虑问题,找出达成目标的各个步骤,提前为以后的需要和相关进程做好准备)

破法4:学会怎样判断时间**

时间四象限

学会利用零碎时间

预防意外干扰,抵制诱惑

不要太分散精力

找出你的最佳时间

享受你的“自由”时间

  • 主观时间和客观时间,做到平滑过渡。很多人就是忽略客观时间所以才老是导致拖延,时间不是跟着你的意志走的。
  • 列出“非计划”时间,除开必须做的事情,剩下多少时间可以用于实现你的目标,给他排出来。
  • 积极的时间约束(番茄工作法…),主要是提高专注力,人不可能24小时都是专注的,就算你说你可以那请你看看猝死的例子…
破法5:积极一点

记住一点:不断地否定自己或者消极对待是要消耗很多能量地。

领导告诉了我一句话:如果你今年没觉得去年的自己是个SB那你就没有在成长,所以别动不动就沮丧、消极。

所以又对应上前面说的,要从一个个小成就不断地激励自己。

破法6:利用你的身体减轻拖延

锻炼,很多人一提到锻炼就会马上接一个词“身体”,其实锻炼不仅仅是锻炼身体其实还是一种脑力的、心理的活动,锻炼是一种释放,通常锻炼你是不会受其他东西影响的,比如你不能玩手机不能看电视等等…这就迫使你专注起来,并且大脑会开始想事情,有点类似冥想的意思。

你的大脑是比较放空的,你可以进行整理、归纳、思考等一系列活动,同时锻炼完事之后又特别爽,释放了身体和心理上的一些无用的东西。

今天内心膨胀的以为自己是个人才,所以随心所欲的看了门课。以下记录了我觉得对我有意义的点。

根据业务布局和业务的洞察来理解和分析业务的变局时什么,再次基础上呢再来看搭建什么样的阵型,组织阵型来匹配业务,为了这样的一个人才搭建,需要准备怎样对人才进行赋能,这个赋能是系统性的赋能,不是对单个个体,甚至不是对团队,而是一个系统性的赋能。最后沉淀褚一套人才管理的机制,用这样的一套人才管理机制不断推动人才。

人才

业务布局=人才体积

人才体积:人才在多大的业务空间中去发挥作用,所以业务布局决定了人才体积

组织阵型=密度

人才分布的密度和人才分布的层次

人才赋能=人才质量

对组织化导向的人才赋能,我组织想对我整个的人才产生怎样的一个牵引力。核心是我是要提高我得人才适应未来业务成长需求,适应未来变局的整体的能力的拉伸。

密度=质量/体积

所以单独对人才进行培训和赋能是不够的,而是要对人才的密度进行一个拉升,即提升人才质量的同时,要让业务体积处于合适的范围内。

人才称重:人才在组织中的重量,发挥的作用。

人才称重的三种方式:

  1. 通过人才赋能提升人才质量
  2. 通过业务布局减少人才体积(冗余)
  3. 通过组织机构的调整来优化人才在不同组织单元中的密度,激活组织的有效性。

四大模型

主要说说人才管理机制模型:

汰换、激励、约束、牵引

汰换:这是一个必然的过程,当你想懈怠的时候觉得无趣的时候,问问自己你对于公司的价值是什么

牵引:企业文化价值的输入、企业向心力的培养等

业务变局

业务结构与人才结构

解释,在什么情况下先发展业务还是先发展人才。

依赖的手段则是进行业务摸底人才摸底(核心团队)

组织变阵

说明什么地方配置更加优秀的人才,合理的调整人才结构和组织结构

人才赋能

迎接未来面对变局的能力

人才管理机制

通过上述内容,沉淀出一套符合自己公司的人才管理机制

小结

从这个课我知道了人才管理不是我之前那么单纯的理解,很容易被这个词午到,人才管理其实不仅仅说的是人才管理,还包括业务布局、组织变阵、人才赋能、机制建立等因素。

所以我理解一下下,人才的定义是不是:专业技能过硬,有战略眼光且能适应业务未来的变局,且有组织向心力?

为什么要谈个人发展?

这个话题其实我很怕的….,因为我发育迟读书少,所以一直都懵懵懂懂+凄凄惨惨戚戚,自认为放荡不羁其实就是无知逗逼。我是从17年开始才意识到有个概念叫“以后的路咋走”,文气点就是个人发展。因为17年开始面临买房、小孩儿上学等一系列问题,深深感到自己的无力,表象就是缺钱,内里就是焦虑。那段时间常常展开双臂抬头望问天“咋整?我该咋整?”,夜深人静常常哭湿了我的小黄人枕巾。就想着不能这样,得变,得抗。

这两年其实我一直在摸索适合自己地发展路径,虽然现在个人发展长远地战略还不是非常明确,但是至少我认识到了个人发展地重要性,并且找到了最近3-5年自己地发展路径。

当然这篇不是来说我的,是结合之前老大的分享以及平时自己的学习来试着说明一下,个人发展的必要性。

**我们先聊聊几个点,看是否能达成共识。达不成共识可能这篇文章对你来说就没什么意义 **

工作压力大,没时间

不用我说大家都知道,个人发展是需要时间来铺垫的,同时个人发展肯定跟工作会有联系,这种联系根据个人的处境可强可弱。另外一个共识点是,工作肯定会压缩我们的可自由支配的时间。所以很多时候我们会得出一个结论,工作压力大,没时间。作为程序员我承认确实会存在这样的情况,究其原因:公司的业务压力大,需要堆人堆时间来跟上时代的节奏。另外一点则是个人的精力有限,就像电池一样,在工作上就把电耗尽了,就算会有一些休息时间,也已经没电了。但是我们可以这么想想:现在的工作强度是否有利于个人发展?得到报酬能否多到让我暂时放弃个人发展的程度?工作压力是否真的有我们想象得那么大,时间是否真的就没了?

所以核心的问题是,我们对个人发展这件事情有多重视?愿意投资多少时间和精力?

我的观点是:如果光感受到工作压力大让你没有时间,但又无法获得一些正反馈,那这不是你有没有时间得问题,而是先考虑这份工作是不是应该继续做下去的问题。如果有正反馈,我们再想想是否现在处境就算我想要的的”个人发展”。

怎么来判断,我通常是这样做的:

  1. 列出来公司的晋升制度,薪酬制度。
  2. 尽可能的根据各种反馈,试着评估一下公司的发展前景或者产品线的发展前景。
  3. 列出来所在职位的工作内容(在不晋升的情况下),以及如果晋升了的工作内容(从与领导交流,加上观察基本上能预估出80%左右)。
  4. 列出来如果因为某些因素,导致被动的离开公司,自己会怎样?

不出意外你列完之后,会说一句“卧槽xxxx”,这样就对了,好好考虑一下个人发展的重要性吧。

有点扯远了,其实我是想说,自己愿意的话,不会没有时间。

工作生活要平衡

我不想这么辛苦,我期望生活和工作平衡

很多人都期望活少钱多还开心,朋友圈那些天天晒美食,旅行,老婆孩子热炕头的生活就是理想人生。每个行业都有其辛苦的部分,这才是现实。有的要付出体力之苦,有的要付出健康的代价,有的要付出脑力之苦。既然选择了薪酬相对高一些的IT行业,持续学习新技术,新知识就是你必须面对的。你是想要今天的生活和工作平衡,还是中年油腻后的生计艰难?

假如你不是富二代,官二代,还是更现实,更长期地看待工作和生活平衡的事情。如果你从事的工作是你热爱的工作,不存在平衡问题,从中获得的成就感就是你生活的一部分。如果你从事的工作是你谋生的手段,想持续获得这个收入,就遵循这个工作的本质规律。

以上是老大的原话我觉得已经说的很透彻了,我认为要想追求工作生活的平衡是不可能的,当然我不是说工作和生活就必须得纠缠在一起才好,我是觉得平衡这词应该是心理上的划分而不是物理上的划分。

个人发展战略

然后我们再来说怎么找到属于自己的个人发展战略,内容总结来自圈外商学院的个人发展战略主体纲要,因为平台不让看了,我就直接不要脸的引用有识之士的了。大家如果觉得有用请去链接点赞,就当我对其微薄的回报了。

一、一个模型,帮你找到真正热爱的工作

  • 冰山模型;美国著名心理学家麦克利兰

    • 显性30%;

      • 知识(专业,书籍),慌乱
      • 技能(编程,技术),焦虑
      • 能力(思考能力,学习能力),挫败低效
    • 隐性70%;

      • 价值观(判断事物标准),矛盾纠结
      • 性格特质(行为偏好),心累
      • 动机(成就动机,权力动机),没热情
    • 四个步骤找到适合的工作

      • 找专业;找自己喜欢的专业和爱好的相关岗位
      • 搜索岗位;在招聘网上,搜索岗位的要求
      • 分析需求;用冰山模型,分析这份岗位需要的知识,技能和能力
      • 对比自己;用冰山模型匹配自己的价值观,性格特质和动机,确定适不适合。

二、四大要素,决定你的市场价值

  • 用冰山模型说明该投入到哪里,才能提升自己的市场价值

    • 投入知识;容易获取,但如果不能运用来解决问题,几乎没有竞争力。
    • 投入技能;有门槛,但市场价值取决于稀缺程度,所有技能都会走向供需平衡,高收入不可持续,需要不断持续学习新技能。
    • 投入能力;能力可迁移,积累到一定高度,行业不对称,也能发挥作用。
    • 投入自我发现;难以改变和发现,但如有清晰的认识,找到相匹配的工作也能提升价值。
  • 为什么大多数人都选择投入到知识和技能,不断碎片化学习,练习并不稀缺的技能。

    • 因为知识和技能容易习得
    • 惰性让自身受限于岗位
    • 没明白工作本质是解决问题
  • 汇总;我们的时间,永远应该花在正确的事情上,而不是容易的事情上。

三、四类迹象,发现你的隐藏能力

    • 虽然成功的道路有千万条,但成功人士基本都在遵循了一个原则,就是将自己的自身天赋发挥到了极致。
    • 天赋就是隐藏的能力,让一个人可以在同样起点的情况下,更加加速成长。
  • 天赋探索方法;“SIGN”

    • 自我效能(Self-efficacy);对某类事情非常有信心,觉得自己肯定能做好。
    • 本能(Instinct);迫不及待想要尝试的事情
    • 成长(Growth);发现自己明显比别人进步的快一些
    • 满足(Needs);做完后及时很累,也会觉得满足
  • 如何在日常中发现自己的SIGN特质

    • 围绕SIGN特质问自己

      • 自我效能;认为自己能教别人什么?别人向你请教什么?跟别人聊天倾向聊什么?聊什么话题会让你感到自信?做什么事情不会感到焦虑和担心?
      • 本能;做什么事的时候很少拖延?长时间休息后,你最想念工作的哪个方面?你宁愿放弃休息时间也要做的事情是什么?
      • 成长;什么事情会让你沉浸其中忘记时间?不容易感到疲累和厌烦?
      • 满足;过去工作和生活中,有什么让你获得巨大的成就感和满足感?
    • 围绕SIGN特质问他人

      • 你觉得我身上有什么不同于别人的特质?

      • 你最欣赏或者佩服我的方面是什么?

      • 在你看来,我做什么的时候最兴奋?

      • 我做过什么让你印象深刻的事情么?

      • 在以下方面,你觉得我那些更加擅长?

        • 思维方式;条理清晰,逻辑严密,脑洞很大,专注专业
        • 沟通协调;化解冲突,争取资源,知人善用
        • 计划执行;执行力强,强求完美,目标导向

四、三种方法,将知识内化成能力

  • 惰性知识;不能及时有效调用,占用大脑内存的知识

  • 如何把知识内化成能力,让自己的能力快速提升的三个方法

    • 1.掌握20%的核心;二八原则,一个领域的20%的核心内容,能够解决80%的问题

      • 如结构化思维20%的三个特征;主题鲜明,归类分明,逻辑递进。
      • 擅长找师傅,找领域内专业人士,了解领域的核心20%
    • 2.知识和问题相互靠

      • 让知识和问题链接起来,知识向问题靠,问题向知识靠。

      • 知识(想应用)问题;看到一个知识就去思考这个知识可以用来解决什么问题?

        • 如;马斯洛的五层次需求,可以用来分析奢侈品为什么这么贵?
      • 问题(找解释)知识,遇到问题,抛弃第一反应,去想想有什么方法论模型可以用

        • 看书遇到有趣的理论,先记下思考3个可以用该模型解决的问题。下次不要下意识反应,学会去翻一下以前的笔记,把问题补充到笔记里。
    • 3.做系统化训练

      • 刻意练习;一个月中,显示每天练习三段式,再提炼主题,然后积累结构
      • 我们的习惯,是高估几天的变化,而低估几个月的变化。
  • 汇总;如何具体到行动中;

  • 1.找专业人士了解领域的核心20%,先去学习20%

  • 2.在学习的过程中,思考各个知识点的应用场景,并记录下来,遇到问题再回去找

  • 3.能力提升是一个系统性过程,所以需要坚持至少1个月。

五、三大系统,让学习不靠意志力

  • 为什么我们如此难坚持

    • 意志力是有限的,并不是学习这件事情类到你,而是“坚持”
    • 移动互联网时代,诱惑越来越多
    • 威尔海姆。霍夫曼主持的一项研究表明;人们醒着的时候,把大约1/4的时间用来抵制欲望。
  • 意志力不够用,就用行为改变来学习。

    • 决定事情时起作用的大脑内部的两个系统;理性和感性。
  • 如何让我们坚持做一件事的三个关键因素;

    • 理性上;知道要学习(树立明确的目标)

      • 明确的目标是坚持学习的第一步
    • 感性上;愿意去学习(利用情绪冲动)

      • 截止日期的紧迫感
      • 比较产生的焦虑感
      • 鼓励带来的成就感
    • 情景上;制造适合学习的场景(创造学习环境)

      • 人是社会动物,我们会观察周围人的行为来调整自己的行为。
      • 如果可以利用环境,就不要用你的意志力来抵制欲望

六、三个建议,让你不做“定制化人才”

  • 1.调整主体,给自己定好发展方向
  • 2.提升能力,让自己成为横向可迁移的人才
  • 3.提升认知高度,让自己成为纵向可拓展的人才

源引感谢:

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。

最近看了《抉择》,虽说本身是一本企业管理的书,但是对人自身也是特别有指导意义的…

背景

由于某些客户现场以及我们公司自身的要求,产品上线之前都会有一轮的安全扫描,用AppScan等这类工具扫一扫,最近就处理了几个安全扫描的问题,虽说处理的比较原始但是还是需要记录一下,你晓得哇,因为比较折磨人。

工作原理

什么交XSS、SQL注入网上一大堆我就不出丑了哈,要解决这块问题那就先得搞清楚AppScan这类软件的工作原理。

AppScan 工作原理小结如下:

  • 通过爬行配置的整个 Web 应用,了解其结构找到接口等信息
  • 根据分析的结果,发送修改后的Request 进行攻击尝试(扫描规则库模拟XSS、SQL注入等操作)
  • 最后分析 Respone ,验证是否符合预期是否存在安全漏洞

所以由此看出处理XSS、SQL注入等问题只能在第二个和第三个环节出手。

处理姿势

处理这类问题我所知道的通常就3种姿势:

  1. 拦截

    触发了这类校验直接拦截掉并提示不让其做任何操作,简单粗暴但是不人性化。经常让人很懵逼。

  2. 替换

    把可触发这类校验的关键字全部替换为其它字符或者转换为字符串等。这种容易破坏原有的表达。

  3. 加密

    这是种欺骗扫描软件的方式,直接前后端约定加密方式,对所有的输入进行统一加密,后端再统一解密,这样扫描软件识别不了任何关键字。我同事就这样干过,虽然说性能上会有一点问题但是好在不用动任何代码。嗯,这种只能说骚操作。

实操

最后和架构师定的方式是通过filter+正则这种最原始最简单的方式来做,我们这是toB的运维系统所以让大家失望了没上高大上的安全策略。

输入流

需要先搞清楚为什么需要处理输入流,因为 reqeust.getInputStream 方法只能读取一次。我们可以大概捋一下是咋回事。

我们需要输入流所以需要调用reqest.getInputStream(),getInputStream返回值为ServletInputStream,所以我们先看看ServletInputStream。

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
public abstract class ServletInputStream extends InputStream {
protected ServletInputStream() {
}

public int readLine(byte[] b, int off, int len) throws IOException {
if (len <= 0) {
return 0;
} else {
int count = 0;

int c;
while((c = this.read()) != -1) {
b[off++] = (byte)c;
++count;
if (c == 10 || count == len) {
break;
}
}

return count > 0 ? count : -1;
}
}

public abstract boolean isFinished();

public abstract boolean isReady();

public abstract void setReadListener(ReadListener var1);
}

然后知道是继承自InputStream,所以我们先看InputStream,注意read和reset方法。

read方法告诉我们会从输入流一直读取下一个字节、如果以达到末尾侧返回-1。

reset告诉我们可以重置读取的位置。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
public abstract class InputStream implements Closeable {

// MAX_SKIP_BUFFER_SIZE is used to determine the maximum buffer size to
// use when skipping.
private static final int MAX_SKIP_BUFFER_SIZE = 2048;

/**
* Reads the next byte of data from the input stream. The value byte is
* returned as an <code>int</code> in the range <code>0</code> to
* <code>255</code>. If no byte is available because the end of the stream
* has been reached, the value <code>-1</code> is returned. This method
* blocks until input data is available, the end of the stream is detected,
* or an exception is thrown.
*
* <p> A subclass must provide an implementation of this method.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* stream is reached.
* @exception IOException if an I/O error occurs.
*/
public abstract int read() throws IOException;

/**
* Repositions this stream to the position at the time the
* <code>mark</code> method was last called on this input stream.
*
* <p> The general contract of <code>reset</code> is:
*
* <ul>
* <li> If the method <code>markSupported</code> returns
* <code>true</code>, then:
*
* <ul><li> If the method <code>mark</code> has not been called since
* the stream was created, or the number of bytes read from the stream
* since <code>mark</code> was last called is larger than the argument
* to <code>mark</code> at that last call, then an
* <code>IOException</code> might be thrown.
*
* <li> If such an <code>IOException</code> is not thrown, then the
* stream is reset to a state such that all the bytes read since the
* most recent call to <code>mark</code> (or since the start of the
* file, if <code>mark</code> has not been called) will be resupplied
* to subsequent callers of the <code>read</code> method, followed by
* any bytes that otherwise would have been the next input data as of
* the time of the call to <code>reset</code>. </ul>
*
* <li> If the method <code>markSupported</code> returns
* <code>false</code>, then:
*
* <ul><li> The call to <code>reset</code> may throw an
* <code>IOException</code>.
*
* <li> If an <code>IOException</code> is not thrown, then the stream
* is reset to a fixed state that depends on the particular type of the
* input stream and how it was created. The bytes that will be supplied
* to subsequent callers of the <code>read</code> method depend on the
* particular type of the input stream. </ul></ul>
*
* <p>The method <code>reset</code> for class <code>InputStream</code>
* does nothing except throw an <code>IOException</code>.
*
* @exception IOException if this stream has not been marked or if the
* mark has been invalidated.
* @see java.io.InputStream#mark(int)
* @see java.io.IOException
*/
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}

所以从上面可以得知ServletInputStream是没有重写r关键的reset方法,所以行为是与InputStream保持一致的即输入流读取一遍之后就没了后续就一直返回-1。

所以解决办法就是找到重写reset的方法的类,即就找到我们常用的ByteArrayInputStream也是继承自InputStream,但是其重写了reset等方法。

我们看下源码:

注意read里面的pos变量,它是标识现在读取的流的位置,所以如果我们想多次读取输入流,需要调用上面说的reset方法重置pos为0。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public
class ByteArrayInputStream extends InputStream {
/**
* The currently marked position in the stream.
* ByteArrayInputStream objects are marked at position zero by
* default when constructed. They may be marked at another
* position within the buffer by the <code>mark()</code> method.
* The current buffer position is set to this point by the
* <code>reset()</code> method.
* <p>
* If no mark has been set, then the value of mark is the offset
* passed to the constructor (or 0 if the offset was not supplied).
*
* @since JDK1.1
*/
protected int mark = 0;

/**
* The index of the next character to read from the input stream buffer.
* This value should always be nonnegative
* and not larger than the value of <code>count</code>.
* The next byte to be read from the input stream buffer
* will be <code>buf[pos]</code>.
*/
protected int pos;
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned.
* <p>
* This <code>read</code> method
* cannot block.
*
* @return the next byte of data, or <code>-1</code> if the end of the
* stream has been reached.
*/
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}

/**
* Resets the buffer to the marked position. The marked position
* is 0 unless another position was marked or an offset was specified
* in the constructor.
*/
public synchronized void reset() {
pos = mark;
}

这些搞清楚之后就是看怎么能在到咱们的filter的时候得到的request是可以读取多次同时又不影响其它地方的读取(比如controller),刚好severlet.api提供了一个叫HttpServletRequestWrapper的东西,刚好提供一种包装(专业名词:装饰器模式)的手法让我们可以包装request请求对象使其可扩展其它能力。包装高富帅哪里都吃得开。

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* @author Gamehu
* @date 2019/5/9 18:32
* @description sql注入问题,前置处理输入流,避免输入流获取一次以后失效导致系统异常
*/
public class xxxHttpServletRequestWrapper extends HttpServletRequestWrapper {
private static final Logger LOGGER = LoggerFactory.getLogger(SqlInjectHttpServletRequestWrapper.class);
/**
* 存储请求输入流
*/
private byte[] body;


public SqlInjectHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
try {
body = inputStreamToByte(request.getInputStream());
} catch (IOException e) {
throw RiilExceptionUtils.bizException(e, BaseWebErrorCode.SecurityConstant.ERROR, BaseWebErrorMsg.SecurityConstant.ERROR_MSG);
}
}

/**
* 流转 字节数组
*
* @param is
* @return
* @throws IOException
*/
private byte[] inputStreamToByte(InputStream is) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int ch;
while ((ch = is.read(buffer)) != -1) {
byteStream.write(buffer, 0, ch);
}
byte[] data = byteStream.toByteArray();
byteStream.close();
return data;
}

@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(getInputStream()));
}

/**
* 重写方法用于多次获取流,防止读取用于校验过后,后面服务无法获取参数的情况
*
* @return
*/
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {

@Override
public boolean isFinished() {
return false;
}

@Override
public boolean isReady() {
return false;
}

@Override
public void setReadListener(ReadListener readListener) {
LOGGER.info("setReadListener");
}

@Override
public int read() {
return bais.read();
}
};


}

OK,到这儿输入流总算搞定了,nice,然后开始Filter上场了。

Filter

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

/**
* @author Gamehu
* @date 2018/12/20 15:18
* @description XSS、SQL注入校验
*/
@WebFilter(urlPatterns = "/*", filterName = "xxFilter")
public class xxFilter implements Filter {


@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
...
//安全扫描问题(sql注入、xss)处理,对参数进行校验
securityScanParamsValidate(filterChain, response, request);
}


/**
* 安全扫描问题(sql注入、xss)处理,对参数进行校验
*
* @param filterChain
* @param response
* @param request
* @throws IOException
* @throws ServletException
*/
private void securityScanParamsValidate(final FilterChain filterChain, final HttpServletResponse response, final HttpServletRequest request) throws IOException, ServletException {
final String paramsAndValues = SecurityScanUtil.extractPostRequestBody(request);
if (StringUtils.isEmpty(paramsAndValues)) {
filterChain.doFilter(request, response);
} else {
//根据参数是否能转换为json,执行不同的校验
parseParamAndValidate(filterChain, response, request, paramsAndValues);
}

}

private void parseParamAndValidate(final FilterChain filterChain, final HttpServletResponse response, final HttpServletRequest request, final String paramsAndValues) throws IOException, ServletException {
try {
final JSONObject paramsObj = JSONObject.parseObject(paramsAndValues);
if (paramsObj.size() == 0) {
filterChain.doFilter(request, response);
} else {
//对参数进行拆分校验,只校验每个参数值
jsonParamValidate(filterChain, response, request, paramsAndValues);
}

} catch (JSONException ex) {
LOGGER.error("isJSONValid,不是有效的JSON字符串,{}", ex.getMessage());
//参数不是合法地json格式则进行整句校验(不进行任何拆分)
notJsonParamValidate(filterChain, response, request, paramsAndValues);
}
}

/**
* 非json格式参数安全问题校验
*
* @param filterChain
* @param response
* @param request
* @param paramsAndValues
* @throws IOException
* @throws ServletException
*/
private void notJsonParamValidate(final FilterChain filterChain, final HttpServletResponse response, final HttpServletRequest request, final String paramsAndValues) throws IOException, ServletException {
final String uri = request.getRequestURI();
// sql注入校验
if (SecurityScanUtil.execSqlInjectValidate(uri, NO_KEY, paramsAndValues)) {
response.sendRedirect(SQL_INJECT_ERROR);
} else if (XssUtil.xssMatcher(uri, NO_KEY, paramsAndValues)) {
//xss校验
response.sendRedirect(XSS_ERROR);
} else {
filterChain.doFilter(request, response);
}
}

/**
* json格式参数安全问题校验(sql注入、xss)
*
* @param filterChain
* @param response
* @param request
* @param paramsAndValues
* @throws IOException
* @throws ServletException
*/
private void jsonParamValidate(final FilterChain filterChain, final HttpServletResponse response, final HttpServletRequest request, final String paramsAndValues) throws IOException, ServletException {
//防sql注入校验
if (SecurityScanUtil.sqlInjectValidate(request.getRequestURI(), paramsAndValues)) {
response.sendRedirect(SQL_INJECT_ERROR);
} else if (SecurityScanUtil.xssValidate(request.getRequestURI(), paramsAndValues)) {
//xss校验
response.sendRedirect(XSS_ERROR);
} else {
filterChain.doFilter(request, response);
}
}

@Override
public void destroy() {
LOGGER.info("destroy");
}


}
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
*
* @author Gamehu
* @description Xss和Sql注入检查 工具类
* @date 2019/5/10 9:54
*/
public class SecurityScanUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityScanUtil.class);
private static final String GRAPHQL = "graphql";

private SecurityScanUtil() {
}

/**
* 单个参数的sql注入校验
*
* @param paramName
* @param value
* @return
*/
public static String sqlInjectionValidate(final HttpServletRequest request, final String paramName, final String value) {
if (StringUtils.isEmpty(value)) {
return null;
}
/*
* 防sql注入,如果存在抛出校验异常
*/
if (SqlInjectUtil.haveSqlInject(request.getRequestURI(), paramName, value)) {
return "sqlError";
}

return value;
}


/**
* 读取输入流中参数
*
* @param request
* @return
*/

public static String extractPostRequestBody(final HttpServletRequest request) {

final Scanner s;
try {
s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
} catch (IOException e) {
throw RiilExceptionUtils.bizException(e, BaseWebErrorCode.SecurityConstant.INPUTSTREAM_ERROR, BaseWebErrorMsg.SecurityConstant.INPUTSTREAM_ERROR_MSG);
}
return s.hasNext() ? s.next() : "";

}


/**
* 效验sql注入问题
* <h3>SQL注入的几种方式:</h3>
* <pre>
* 1) 使用 ' or 语句,将查询条件扩大,实现破坏性查询(操作)
* 2) 使用 ; 将SQL分成两部分,在后面一部分实现破坏性操作
* 3) 使用注释,将后面的条件取消掉,将查询条件扩大,注意MySQL有三种注释的方法,都需要处理
*
* 为了简化处理,这里只考虑字符串类型参数注入情况(整型等其它类型在应用内部类型转换会失败,所以基本可以忽略)
* </pre>
*
* @return
* @throws IOException
*/
public static boolean sqlInjectValidate(final String uri, final String paramsAndValues) {
//获取参数列表以及参数值
final JSONObject paramsObj = JSONObject.parseObject(paramsAndValues);
final Set<String> keys = paramsObj.keySet();
return keys.stream().anyMatch(key -> haveSqlInjectCondition(uri, paramsObj, key));
}

/**
* 判断是否存在sql注入的表达式
*
* @param uri
* @param paramsObj
* @param key
* @return
*/
private static Boolean haveSqlInjectCondition(final String uri, final JSONObject paramsObj, final String key) {
//graphql 不进行校验
if (key.equalsIgnoreCase(GRAPHQL)) {
return false;
}
final String value = convertParamToString(paramsObj, key);
return SqlInjectUtil.haveSqlInject(uri, key, value);
}

/**
* 效验XSS问题
*
* @param uri
* @param paramsAndValues
* @return
*/
public static boolean xssValidate(final String uri, final String paramsAndValues) {
//获取参数列表以及参数值
final JSONObject paramsObj = JSONObject.parseObject(paramsAndValues);
final Set<String> keys = paramsObj.keySet();
return keys.stream().anyMatch(key -> haveXssCondition(uri, paramsObj, key));
}

/**
* 判断是否存在xss的表达式
*
* @param uri
* @param paramsObj
* @param key
* @return
*/
private static boolean haveXssCondition(final String uri, final JSONObject paramsObj, final String key) {
final String value = convertParamToString(paramsObj, key);
//判断是否存在xss攻击问题
return XssUtil.haveXss(value, key, uri);
}

/**
* 处理参数为字符串
*
* @param paramsObj
* @param key
* @return
*/
private static String convertParamToString(final JSONObject paramsObj, final String key) {
final Object obj = paramsObj.get(key);

String value = null;

if (obj instanceof JSONObject) {
value = ((JSONObject) obj).toJSONString();
}

if (obj instanceof JSONArray) {
value = ((JSONArray) obj).toJSONString();
}

if (obj instanceof String) {
value = (String) obj;
}
return value;
}

}
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

/**
* @author Gamehu
* @date 2019/9/26 12:12
* @description XSS校验的工具类
*/
public class XssUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(XssUtil.class);
private static final String GRAPHQL = "graphql";
private static Pattern[] patterns = new Pattern[]{
// Script fragments
Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
// src='...'
Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// lonely script tags
Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// eval(...)
Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// expression(...)
Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// javascript:...
Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),
// vbscript:...
Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),
// onload(...)=...
Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)
};


/**
* 判断是否存在xss攻击
*
* @param value
* @param key
* @param uri
* @return true表示存在,false表示不存在
*/
public static Boolean haveXss(final String value, final String key, final String uri) {
if (key.equalsIgnoreCase(GRAPHQL)) {
return false;
}
return xssMatcher(value, key, uri);
}

public static boolean xssMatcher(final String value, final String key, final String uri) {
if (StringUtils.isNotBlank(value)) {
Matcher matcher;
for (Pattern pattern : patterns) {
matcher = pattern.matcher(value);
// 匹配
if (matcher.find()) {
LOGGER.error("存在xss风险,URI:{},参数:{},参数值:{}", uri, key, value);
return true;
}
}

}
return false;
}

}
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

/**
* @author Gamehu
* @date 2019/9/26 12:12
* @description SQL注入校验的工具类
*/
public class SqlInjectUtil {
/**
* SQL语法检查正则:只检查一个关键字可能存在误判情况,这里要求必须符合两个关键字(有先后顺序)才算匹配
* 第一组关键字
*/
final static String sqlInjectGroup = "select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|drop|execute";

/**
* 构造SQL语法检查正则
* (?i)忽略字母的大小写,\s.*空白+字符
*/
final static Pattern sqlSyntaxPattern = Pattern.compile("(?i)(.*)\\b(" + sqlInjectGroup + " )\\b\\s.*", Pattern.CASE_INSENSITIVE);


/**
* 读取输入流中参数
*
* @param request
* @return
*/

public static String extractPostRequestBody(final HttpServletRequest request) {

final Scanner s;
try {
s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
} catch (IOException e) {
throw RiilExceptionUtils.bizException(e, BaseWebErrorCode.SecurityConstant.INPUTSTREAM_ERROR, BaseWebErrorMsg.SecurityConstant.INPUTSTREAM_ERROR_MSG);
}
return s.hasNext() ? s.next() : "";

}

/**
* 执行SQL注入校验
*
* @param uri
* @param key
* @param oldValue
* @return
*/
public static boolean haveSqlInject(final String uri, final String key, final String oldValue) {
if (StringUtils.isNotBlank(oldValue)) {
//统一转为小写
final String newValue = oldValue.toLowerCase();
final String logStr = "存在sql注入风险,URL:{},参数:{},参数值:{}";
// 检查是否包含SQL注入敏感字符
if (sqlSyntaxPattern.matcher(newValue).find()) {
LOGGER.error(logStr, uri, key, newValue);
return true;
}
}
return false;
}

}

因为我们用了graphql,有些地方还用了dsl,所以正则是魔鬼,我写崩溃了差点,当然如果有更好的方法请告诉我,万分感谢。

长出一口气…..

本文引用的内容,如有侵权请联系我删除,给您带来的不便我很抱歉。

高难度沟通发生的三个场景

矛盾、争取、推进

近段时间刚好,做的分享和听的分享较多。刚好缘分就是那么奇妙,在一个网课平台刚好看到了这个网课《如何提高Presentation的展现能力》,在此做个记录。

图1所阐述的观点,是我个人觉得做得最契合的。确实我一直认为,Presentation别弄太多文字类或者花哨的东西,PPT应该是辅助我们说明白一个事情,所以主次需要分清。

图2所说几个点

  • 底稿我觉得如果是很正式或者很重要的Presentation是个很好的减少风险的点。

  • 另外关于互动,这点是很重要的,不管是眼神还是肢体还是语言,他能让讲解人和听众建立联系,如果没有互动,那就感觉像是下命令了,你们只管听我只管讲,不能有异议这样的场景特别糟糕。

  • 时间管理特别重要,我特别厌烦那种拖沓的,慢条斯理的Presentation,让氛围很疲惫,这种效果很差,这点我也需要改进,虽然我很注意时间控制,但是也没有做到掐表的程度,但是我认为有些情况是可以掐表,比如做分享。

图3是我最没有底气的点,Presentation事后的修正和反思做得比较少,特别是修正,要想整个Presentation比较有质量,确实这块是不可或缺的,尽量不因此留下遗憾。

Presentation:我觉得可解释为:具有分享、议题、同步等性质的会议。

图片摘自: