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语句也许是这样的:select * from urls where id=${userInput}。如果某个淘气的用户不遵守约定输入了非数字,例如10 or 1=1,SQL语句拼接过后就成了这样:select * from urls where id=10 or 1=1,表中的信息一次被完全暴露!
最开始提到参数化查询的时候,我提到了Prepared Statements也就是预处理语句,其实我们可以把参数化查询理解为预处理,我们把完整的一次SQL查询分成两部分,第一步是预先查询,第二步使用参数得到结果。具体该怎么理解呢,还是接着上面的那个例子,现在我们使用参数化查询执行select * from urls where id=1。其分为两步,第一步执行select * from urls where id=?,注意这里的?,其实代表了未来将要传入的参数;第二步,传入用户的输入作为具体的id值,并且输出结果。这里要注意,因为执行完第一步的时候期待第二步传入的是一个用户的id(这里必须是数字),这时候用户传入的非法输入就不会生效,这也就从根本上杜绝了了SQL注入攻击。
现在我们可以通过import style from './style.css'的形式引入自定义css,并且通过style.className的形式给元素设置类。这次倒好,直接build不成功了,我一气之下索性不搞了;为了继续捣鼓下去,我直接又把CSS写在组件中了,直到我要使用react-transition-group来做路由切换动画,不得不倒回来解决。这次比以往更加冷静,我仔细阅读了extract-text-webpack-plugin的readme过后,恍然大悟,原来我们可以在一个项目中使用多个ExtractTextPlugin实例来生成多个css文件!好了,这次还是通过两个规则处理css,并且构建两个css文件,一个是自定义的css,一个是antd css,问题迎刃而解,又可以开心的捣鼓了!
WebGL (Web Graphics Library) is a JavaScript API for rendering interactive 3D and 2D graphics within any compatible web browser without the use of plug-ins. WebGL does so by introducing an API that closely conforms to OpenGL ES 2.0 that can be used in HTML5 canvas elements.
可计算值是通过现有状态和其它可计算值派生出来的值。这很好理解,我们在使用React的时候,往往要通过state衍生出很多的值,例如如果state的一部分是一个数组,那么我们通过衍生得到的数组长度就是一个计算值,并且在Mobx中,一旦可观察的state或者其他computed value 发生改变,可计算值就会重新计算。其实,在实际的React项目中,我们在很多地方都使用到了计算值。
还是上面AppState的例子,现在我们给其增加一个计算值,
1 2 3 4 5 6 7 8 9 10
classAppState{ @observable list = ['limoer', 'lin']; @computed get count() { returnthis.list.length; } } let state = new AppState(); console.log(state.count); // > 2 state.list.push('lindo'); console.log(state.count); // > 3