-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
750 lines (360 loc) · 171 KB
/
search.xml
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>webpack 编译原理 及其优化方案</title>
<link href="/2020/04/25/webpack/"/>
<url>/2020/04/25/webpack/</url>
<content type="html"><![CDATA[<h2>webpack是什么?</h2><p>webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。</p><p> 当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。<br> <a id="more"></a></p><p> webpack有四个核心概念:</p><ul><li>入口(entry)</li></ul><p>入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。</p><p>每个依赖项随即被处理,最后输出到称之为 bundles 的文件中</p><ul><li>输出(output)</li></ul><p>output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程.</p><ul><li>loader</li></ul><p>loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。</p><ul><li>插件(plugins)</li></ul><p>插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。</p><h2>webpack 模式(mode)</h2><p>提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。<br><b>用法:</b></p><p>在配置中使用mode字段配置<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">module.exports = {</span><br><span class="line"> mode: 'production'</span><br><span class="line">};</span><br></pre></td></tr></table></figure></p><p>mode为production 生产环境是 webpack会开启内置优化。</p><ol><li>会将 process.env.NODE_ENV 的值设为 production</li><li>启用 <ul><li>FlagDependencyUsagePlugin(标记没有用到的依赖,这个插件无法通过webpack获取,我只能通过强行导入webpack/lib下的class文件来导入)</li><li>FlagIncludedChunksPlugin(chunks就是所有引用模块的id)</li><li>ModuleConcatenationPlugin(作用域提升)</li><li>NoEmitOnErrorsPlugin(防止程序报错,就算有错误也继续编译)</li><li>OccurrenceOrderPlugin(按照chunk引用次数来安排出现顺序,因为这让经常引用的模块和chunk拥有更小的id)</li><li>SideEffectsFlagPlugin(用于处理tree shaking的,tree shaking,sideEffect这个插件的作用就是,如果当前的模块没有引用,而且package.json中的sideEffects为false,那么打包的时候就可以将此包剔除)</li><li>UglifyJsPlugin(混淆&压缩).</li></ul></li></ol><p>mode为 development 时 开发环境的默认plugin配置。</p><ol><li>会将 process.env.NODE_ENV 的值设为 development</li><li>启用 NamedModulesPlugin(模块命名)和NamedChunksPlugin(chunks命名)</li></ol><h2>loader 和 plugin的区别 </h2> <p>对于loader,它就是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程</p><p>plugin是一个扩展器,它丰富了wepack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛的任务。</p><ul><li>如何手写一个loader</li></ul><p>代码如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">module.exports = function (src) {</span><br><span class="line"> if (src) {</span><br><span class="line"> console.log('--- reverse-loader input:', src)</span><br><span class="line"> src = src.split('').reverse().join('')</span><br><span class="line"> console.log('--- reverse-loader output:', src)</span><br><span class="line"> }</span><br><span class="line"> return src;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><ul><li>如何手写一个plugin</li></ul><p>代码如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">class MyPlugin {</span><br><span class="line"> // 构造方法</span><br><span class="line"> constructor (options) {</span><br><span class="line"> console.log('MyPlugin constructor:', options)</span><br><span class="line"> }</span><br><span class="line"> // 应用函数</span><br><span class="line"> apply (compiler) {</span><br><span class="line"> // 绑定钩子事件</span><br><span class="line"> compiler.plugin('compilation', compilation => {</span><br><span class="line"> console.log('MyPlugin')</span><br><span class="line"> ))</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">module.exports = MyPlugin</span><br></pre></td></tr></table></figure></p><p>webpack 启动后,在读取配置的过程中会先执行 new MyPlugin(options) 初始化一个 MyPlugin 获得其实例。<br>在初始化 compiler 对象后,再调用 myPlugin.apply(compiler) 给插件实例传入 compiler 对象。<br>插件实例在获取到 compiler 对象后,就可以通过 compiler.plugin(事件名称, 回调函数) 监听到 Webpack 广播出来的事件。<br>并且可以通过 compiler 对象去操作 webpack。</p><p><b>Compiler对象解析</b></p><p>Compiler 对象包含了 Webpack 环境所有的的配置信息,包含 options,loaders,plugins 这些信息,这个对象在 Webpack 启动时候被实例化,它是全局唯一的,可以简单地把它理解为 Webpack 实例;</p><p><b>Compilation对象解析</b></p><p>Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。当 Webpack 以开发模式运行时,每当检测到一个文件变化,一次新的 Compilation 将被创建。Compilation 对象也提供了很多事件回调供插件做扩展。通过 Compilation 也能读取到 Compiler 对象。</p><p><b>Compiler 和 Compilation 的区别在于:</b></p><p>Compiler 代表了整个 Webpack 从启动到关闭的生命周期,而 Compilation 只是代表了一次新的编译。</p><p><b>事件流</b></p><ul><li>webpack 通过Tapable来组织这条复杂的生产线。</li><li>webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。</li><li>webpack 的事件流机制应用了观察者模式,和 Node.js 中的 EventEmitter 非常相似。</li></ul><p><b>webpack优化方案</b></p><ol><li>优化解析时间 - 开启多进程打包</li></ol><ul><li>thread-loader(webpack4 官方推荐)</li></ul><ol start="2"><li>externals 非常用的可用cdn方式替换</li><li>splitChunks 适宜的大小模块 DllPlugin</li><li>减少访问请求数量 loader的合理配置 如 url loader</li><li>webpack自身的优化</li></ol><ul><li>tree-shaking</li><li>mode 模式的相关优化</li></ul><ol start="6"><li>合理利用缓存(缩短连续构建时间,增加初始构建时间) cache-loader的合理配置</li><li>优化搜索时间- 缩小文件搜索范围 减小不必要的编译工作 loader的include合理配置</li><li>noParse<br>如果一些第三方模块没有AMD/CommonJS规范版本,可以使用 noParse 来标识这个模块,这样 Webpack 会引入这些模块,但是不进行转化和解析,从而提升 Webpack 的构建性能 ,例如:jquery 、lodash。</li><li>抽离公共代码</li></ol><h2>Tapable </h2><p>tapable 这个小型 library 是 webpack 的一个核心工具,但也可用于其他地方,以提供类似的插件接口。webpack 中许多对象扩展自 Tapable 类。这个类暴露 tap, tapAsync 和 tapPromise 方法,可以使用这些方法,注入自定义的构建步骤,这些步骤将在整个编译过程中不同时机触发。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> webpack </category>
</categories>
<tags>
<tag> webpack </tag>
</tags>
</entry>
<entry>
<title>Promise 对象理解</title>
<link href="/2020/04/18/Promise/"/>
<url>/2020/04/18/Promise/</url>
<content type="html"><![CDATA[<p>Promise 是异步编程的一种解决方案,一起了解Promise 对象吧。<br><a id="more"></a></p><ol><li>promise 是什么<br> Promise 是异步编程的一种解决方案</li><li>异步是什么<br> JS异步是指在进行某些需要耗时不会立即返回结果的操作时,不会阻塞后面的操作,一旦该耗时的操作完成时,则会通知需要调用其结果的函数来做后续处理。这是一种异步非阻塞的操作,也就是说任务的排列顺序和执行任务是不一致的。</li><li>为什么要有Promise,他解决了什么问题<br> 比传统的异步解决方案——回调函数和事件——更合理和更强大,回调函数会出现“回调地狱”等问题,在代码的可读性、可维护性、易读性都有很大的问题。<br> 回调地狱: 回调函数内部多层嵌套回调函数。</li><li>promise特点<br>(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。<br>(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。</li><li>promise的优缺点<br> 优点:<ul><li>可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。</li><li>Promise对象提供统一的接口,使得控制异步操作更加容易。<br>缺点:</li><li>无法取消Promise,一旦新建它就会立即执行,无法中途取消。</li><li>如果不设置回调函数,Promise内部抛出的错误,不会反应到外部</li><li>当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)</li></ul></li><li><p>promise 使用方法<br>ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。<br>下面代码创造了一个Promise实例。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const promise = new Promise(function(resolve, reject) {</span><br><span class="line"> if (/* 异步操作成功 */){</span><br><span class="line"> resolve(value);</span><br><span class="line"> } else {</span><br><span class="line"> reject(error);</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line">Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。</span><br></pre></td></tr></table></figure></li><li><p>promise相关方法</p><ul><li><p>promise.all</p><p>方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。</p></li><li><p>promise.race</p><p>方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。</p></li></ul></li><li><p>如何js实现Promise相关方法</p></li></ol><p>promise.all<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">static all(promiseArr) {</span><br><span class="line"> let index = 0</span><br><span class="line"> let result = []</span><br><span class="line"> return new MyPromise((resolve, reject) => {</span><br><span class="line"> promiseArr.forEach((p, i) => {</span><br><span class="line"> //Promise.resolve(p)用于处理传入值不为Promise的情况</span><br><span class="line"> MyPromise.resolve(p).then(</span><br><span class="line"> val => {</span><br><span class="line"> index++</span><br><span class="line"> result[i] = val</span><br><span class="line"> if (index === promiseArr.length) {</span><br><span class="line"> resolve(result)</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> err => {</span><br><span class="line"> reject(err)</span><br><span class="line"> }</span><br><span class="line"> )</span><br><span class="line"> })</span><br><span class="line"> })</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>promise.race<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">//静态的race方法</span><br><span class="line">static race(promiseArr) {</span><br><span class="line"> return new MyPromise((resolve, reject) => {</span><br><span class="line"> //同时执行Promise,如果有一个Promise的状态发生改变,就变更新MyPromise的状态</span><br><span class="line"> for (let p of promiseArr) {</span><br><span class="line"> MyPromise.resolve(p).then( //Promise.resolve(p)用于处理传入值不为Promise的情况</span><br><span class="line"> value => {</span><br><span class="line"> resolve(value) //注意这个resolve是上边new MyPromise的</span><br><span class="line"> },</span><br><span class="line"> err => {</span><br><span class="line"> reject(err)</span><br><span class="line"> }</span><br><span class="line"> )</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><ol><li>Promise相关面试题目</li></ol><p>题目一<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">const promise = new Promise((resolve, reject) => {</span><br><span class="line"> console.log(1);</span><br><span class="line"> resolve();</span><br><span class="line"> console.log(2);</span><br><span class="line">})</span><br><span class="line">promise.then(() => {</span><br><span class="line"> console.log(3);</span><br><span class="line">})</span><br><span class="line">console.log(4);</span><br></pre></td></tr></table></figure></p><p>答案是: 1 2 4 3<br>首先Promise新建后立即执行,所以会先输出1,2,而Promise.then()内部的代码在当次事件循环的结尾立即执行,所以会先输出4,最后输出3.</p><p>题目二<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">const promise = new Promise((resolve, reject) => {</span><br><span class="line"> resolve('success1');</span><br><span class="line"> reject('error');</span><br><span class="line"> resolve('success2');</span><br><span class="line">});</span><br><span class="line">promise.then((res) => {</span><br><span class="line"> console.log('then:', res);</span><br><span class="line">}).catch((err) => {</span><br><span class="line"> console.log('catch:', err);</span><br><span class="line">})</span><br></pre></td></tr></table></figure></p><p>答案:then:success1</p><p>promise状态一经改变,不会再被改变其他的会被忽略。then函数会把上一个promise的值传递过来所以结果是:then:success1。</p><p>题目三<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Promise.resolve(1)</span><br><span class="line"> .then(2)</span><br><span class="line"> .then(Promise.resolve(3))</span><br><span class="line"> .then(console.log)</span><br></pre></td></tr></table></figure></p><p>答案:1<br>Promise.resolve方法的参数如果是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为resolved,Promise.resolve方法的参数,会同时传给回调函数。<br>then方法接受的参数是函数,而如果传递的并非是一个函数,它实际上会将其解释为then(null),这就会导致前一个Promise的结果会传递下面。</p><p>题目四<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">const first = () => (new Promise((resolve, reject) => {</span><br><span class="line"> console.log(3);</span><br><span class="line"> let p = new Promise((resolve, reject) => {</span><br><span class="line"> console.log(7);</span><br><span class="line"> setTimeout(() => {</span><br><span class="line"> console.log(5);</span><br><span class="line"> resolve(6);</span><br><span class="line"> }, 0)</span><br><span class="line"> resolve(1);</span><br><span class="line"> });</span><br><span class="line"> resolve(2);</span><br><span class="line"> p.then((arg) => {</span><br><span class="line"> console.log(arg);</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line">}));</span><br><span class="line"></span><br><span class="line">first().then((arg) => {</span><br><span class="line"> console.log(arg);</span><br><span class="line">});</span><br><span class="line">console.log(4);</span><br></pre></td></tr></table></figure></p><p>答案:<br>3 7 4 1 2 5</p><p>结合js event loop 机制,同步任务在执行过程中遇到异步任务会将其放入异步任务队列,在同步任务队列执行完毕之后再执行异步任务,异步任务执行完毕后再返回同步任务队列执行。异步任务分为宏仁务和微任务,微任务总是在宏仁务之前执行。</p><p>微任务: promise.then promise.catch promise.finally MutaionObserver process.nextTick(nodejs)<br>宏仁务: setTimeOut setInterval I/O setImmediate requestAnimationFrame</p><p>promise 定义时是同步执行,promise状态修改完毕之后不会再被修改。所以结果为3 7 4 1 2 5 没有6;</p>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
<tag> vue </tag>
</tags>
</entry>
<entry>
<title>vue 双向绑定相关知识</title>
<link href="/2020/04/18/vue-observer/"/>
<url>/2020/04/18/vue-observer/</url>
<content type="html"><![CDATA[<p>了解vue双向绑定原理<br><a id="more"></a></p><ol><li><p>为什么vue要实现双向绑定?</p><p> VUE 是一个 MVVM 模式的一套用于构建用户界面的渐进式框架。<br> Model-View-ViewModel 就是将其中的 View 的状态和行为抽象化,让我们可以将UI和业务逻辑分开。</p><p> MVVM模式是通过以下三个核心组件组成,每个都有它自己独特的角色:</p><ul><li>Model - 包含了业务和验证逻辑的数据模型</li><li>View - 定义屏幕中View的结构,布局和外观</li><li><p>ViewModel - 扮演“View”和“Model”之间的使者,帮忙处理 View 的全部业务逻辑</p><p>为了实现VM的作用引入了双向绑定机制。</p></li></ul></li><li><p>双向绑定的优点</p></li></ol><ul><li>低耦合。 视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的”View”上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。</li><li>可重用性。 你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。</li><li>独立开发。 开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计</li></ul><ol start="3"><li><p>双向绑定的实现原理<br> vue的双向绑定是使用了Object.defineProperty对数据进行劫持,并对数据属性进行get/set重写。并结合发布/订阅者模式,通过observer监听器来监听数据属性,如果属性发生变化就通知订阅者watcher,查看是否需要更新,因为订阅者是有很多个,所以需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理。还有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。</p><ul><li>Object.defineProperty的缺点</li></ul><ol><li>Object.defineProperty的第一个缺陷,无法监听数组变化。</li><li>Object.defineProperty的第二个缺陷,只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历,如果属性值也是对象那么需要深度遍历,显然能劫持一个完整的对象是更好的选择。</li></ol><ul><li><p>数组对象监听方式处理方法</p><p><img src="/images/vue/arrayObserver.jpg" alt=""></p><p>vue处理方式是Vue在array.js中重写了methodsToPatch中七个方法,并将重写后的原型暴露出去。还通过执行ob.dep.notify()将当前数组的变更通知给其订阅者,这样当使用重写后方法改变数组后,数组订阅者会将这边变化更新到页面中。</p><p><img src="/images/vue/arrayObserver1.jpg" alt=""> </p><p>重写完数组的上述7种方法外,还需要将这些重写的方法应用到数组上,因此在Observer构造函数中,可以看到在监听数据时会判断数据类型是否为数组。当为数组时,如果浏览器支持<strong>proto</strong>,则直接将当前数据的原型<strong>proto</strong>指向重写后的数组方法对象arrayMethods,如果浏览器不支持<strong>proto</strong>,则直接将arrayMethods上重写的方法直接定义到当前数据对象上;当数据类型为非数组时,继续递归执行数据的监听。</p></li></ul></li><li><p>指令编译原理</p><p> template会被编译成AST语法树,AST会经过generate得到render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点</p><ul><li>parse 过程,将 template 利用正则转化成 AST 抽象语法树。</li><li>optimize 过程,标记静态节点,后 diff 过程跳过静态节点,提升性能。</li><li>generate 过程,生成 render 字符串</li></ul></li><li><p>3.0版本双向绑定的变化</p><p>作者声明在3.0版本使用 proxy 属性进行数据代理部分,proxy的优点在于</p><ul><li>Proxy直接可以劫持整个对象,并返回一个新对象,不管是操作便利程度还是底层功能上都远强于Object.defineProperty。</li><li>Proxy可以直接监听数组的变化</li><li>Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等等是Object.defineProperty不具备的。</li></ul></li></ol>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
<tag> vue </tag>
</tags>
</entry>
<entry>
<title>js 继承方式</title>
<link href="/2020/04/17/extend/"/>
<url>/2020/04/17/extend/</url>
<content type="html"><![CDATA[<p>为什么要有继承?</p><p>js是面向对象的语言,在创建过程中受到了java面向对象思想的影响,因为js语言中所有数据类型对象都是object,为了使对象跟对象之间有所关联所以设计了继承模式。继承可以大大减少代码量,并且可以让代码具有更强的可读性和可维护性。<br><a id="more"></a><br>继承相关的基础知识</p><ul><li><p>prototype</p></li><li><p>__proto__</p></li><li>原型、实例、构造函数的概念</li></ul><p>通过下列代码来实现基础的继承方式,先创建一个父类(供子类继承)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">function Father(name) {</span><br><span class="line"> this.name = name;</span><br><span class="line"> this.shout = funciton() {</span><br><span class="line"> alert('my name is '+ name + ', i am shouting~!');</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> Father.prototype.eat = function(food) {</span><br><span class="line"> alert('my name is '+ name + ', i am eating' + food)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>ES5继承的方式</p><ol><li>构造函数继承</li></ol><p>原理: 复制父类的实例属性给子类</p><p>实现方式:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">function Child() {</span><br><span class="line"> Father.call(this, arguments);</span><br><span class="line">}</span><br><span class="line">const childObj = new Child();</span><br></pre></td></tr></table></figure></p><p>优点:</p><ul><li>解决了子类构造函数向父类构造函数中传递参数</li><li>可以实现多继承(call或者apply多个父类)</li></ul><p>缺点:</p><ul><li>方法都在构造函数中定义,无法复用</li><li>不能继承原型属性/方法,只能继承父类的实例属性和方法</li></ul><ol start="2"><li>原型链继承</li></ol><p>原理: 父类的实例作为子类的原型</p><p>实现方式:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">function Child() {</span><br><span class="line">}</span><br><span class="line">Child.prototype = new Father();</span><br><span class="line">Child.prototype.name = 'child'</span><br><span class="line">const childObj = new Child();</span><br></pre></td></tr></table></figure></p><p>优点:简单易于实现,父类的新增的实例与属性子类都能访问<br>缺点:</p><ul><li>可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面</li><li>无法实现多继承</li><li>创建子类实例时,不能向父类构造函数中传参数</li></ul><ol start="3"><li>组合继承</li></ol><p>原理: 调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用</p><p>实现方式:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">function Child(name) {</span><br><span class="line"> Father.call(this);</span><br><span class="line"> this.name = name || 'child'</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">Child.prototype = new Father();</span><br><span class="line">Child.prototype.constructor = Child;</span><br></pre></td></tr></table></figure></p><p>优点:</p><ul><li>函数可以复用</li><li>不存在引用属性问题</li><li>可以继承属性和方法,并且可以继承原型的属性和方法</li></ul><p>缺点:</p><ul><li>调用了两次父类构造函数(耗内存)</li></ul><ol start="4"><li>寄生组合继承</li></ol><p>原理: 通过寄生的方式来修复组合式继承的不足,完美的实现继承也是es中最常用的方式</p><p>实现方式:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">function Child(name) {</span><br><span class="line"> Father.call(this);</span><br><span class="line"> this.name = name || 'child'</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function extend(suberClass, superClass) {</span><br><span class="line"> var object = function (o) {</span><br><span class="line"> var F = function () { };</span><br><span class="line"> F.prototype = o;</span><br><span class="line"> return new F();</span><br><span class="line"> };</span><br><span class="line"></span><br><span class="line"> suberClass.prototype = object(superClass.prototype);</span><br><span class="line"> suberClass.prototype.constructor = suberClass; //强制constructor指向suberClass</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">extend(Child, Father)</span><br><span class="line">const childObj = new Child();</span><br></pre></td></tr></table></figure></p><p>寄生组合继承是ES5 最常用的继承方式,也是最优的继承方式。</p>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
</tags>
</entry>
<entry>
<title>防抖(debounce)与节流(throttle)</title>
<link href="/2020/03/21/throttle_debounce/"/>
<url>/2020/03/21/throttle_debounce/</url>
<content type="html"><![CDATA[<p>防抖与节流都是现今web应用的常用技术,他的使用场景主要在我们对一些触发频率较高的事件进行监听的场景下。是能够节省资源优化性能的常用方式。</p><a id="more"></a><ol><li>防抖(debounce)</li></ol><ul><li>原理:一个连续操作中的处理,只触发一次,从而实现防抖动。</li><li>代码:</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">function debounce(fn, delay) {</span><br><span class="line"> var timer;</span><br><span class="line"> return function () {</span><br><span class="line"> var context = this;</span><br><span class="line"> var args = arguments;</span><br><span class="line"> clearTimeout(timer)</span><br><span class="line"> timer = setTimeout(function () {</span><br><span class="line"> fn.apply(context, args)</span><br><span class="line"> }, delay)</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><ol><li>节流(throttle)</li></ol><ul><li>原理:一个连续操作中的处理,按照阀值时间间隔进行触发,从而实现节流。</li><li>代码:</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">function throttle(fn, delay) {</span><br><span class="line"> let timer = null,</span><br><span class="line"> remaining = 0,</span><br><span class="line"> previous = new Date();</span><br><span class="line"></span><br><span class="line"> return function () {</span><br><span class="line"> let now = new Date(),</span><br><span class="line"> remaining = now - previous,</span><br><span class="line"> args = arguments,</span><br><span class="line"> context = this;</span><br><span class="line"></span><br><span class="line"> if (remaining >= delay) {</span><br><span class="line"> if (timer) {</span><br><span class="line"> clearTimeout(timer);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> fn.apply(context, args);</span><br><span class="line"> previous = now;</span><br><span class="line"> } else {</span><br><span class="line"> if (!timer) {</span><br><span class="line"> timer = setTimeout(function () {</span><br><span class="line"> fn.apply(context, args);</span><br><span class="line"> previous = new Date();</span><br><span class="line"> }, delay - remaining);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> };</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>一个连续操作中的处理,只触发一次,从而实现防抖动。</p><ol><li>防抖和节流的应用场景</li></ol><p>防抖: input 搜索联想 、 window.resize()</p><p>节流: 鼠标不断点击触发(游戏中的点击移动)、监听滚动事件</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
</tags>
</entry>
<entry>
<title>如何更换hexo主题</title>
<link href="/2020/03/04/hexo-themes/"/>
<url>/2020/03/04/hexo-themes/</url>
<content type="html"><![CDATA[<p>hexo 官网的主题非常多样,选择一个你喜欢的、能够突出你个性的主题也很重要哦,让我们试试更换hexo的主题吧~!<br><a id="more"></a></p><p>hexo 官网主题部分网址:<br><a href="https://hexo.io/themes/" target="_blank" rel="noopener">https://hexo.io/themes/</a><br>我之前的主题是 next ,想要尝试下更换为 Aero-Dual,主题如下图:</p><p><img src="/images/hexo/hexo-themes.png" alt=""></p><p>点击主题名称,进入它的github项目主页<br><a href="https://github.com/levblanc/hexo-theme-aero-dual" target="_blank" rel="noopener">https://github.com/levblanc/hexo-theme-aero-dual</a><br>查看它的readme.md<br>安装该主题步骤如下:</p><ol><li>clone主题到themes文件夹下,命令如下</li></ol><p><code>$ git clone https://github.com/levblanc/hexo-theme-aero-dual.git themes/aero-dual</code></p><ol start="2"><li><p>在你的config.yml 文件中改变你的theme配置为 aero-dual<br>theme: aero-dual</p></li><li><p>执行命令hexo clean 清楚原来主题文件,再执行hexo g重新生成相关文件。就完成主题的更改了。</p></li></ol><p>更改成新主题后,在每一个更新的文档中 需要添加 tag、以及 category。如下</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">tags: </span><br><span class="line"> - hexo </span><br><span class="line"> - theme </span><br><span class="line">categories: hexo</span><br></pre></td></tr></table></figure><p>如果执行完相关命令出现白页现象,请重新检查第二步是否配置正确。<br>你也来尝试更换你喜欢的主题吧~~!</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> hexo </category>
</categories>
<tags>
<tag> hexo </tag>
<tag> theme </tag>
</tags>
</entry>
<entry>
<title>md 数据格式</title>
<link href="/2020/03/03/markdown/"/>
<url>/2020/03/03/markdown/</url>
<content type="html"><![CDATA[<p>在写博客的过程中,需要用到很多常用的md语法。以下列举出一些常用的md语法。<br><a id="more"></a></p><h4 id="1-正文"><a href="#1-正文" class="headerlink" title="1 正文"></a>1 正文</h4><pre><code>markdown 是支持html以及css样式代码的,也可以按照普通文档去写,markdown文档的换行也和HTML是类似的,你敲一个换行符他会当做什么都没发生,想要换行你可以使用HTML的标签或者是两段文字中间一行。</code></pre><h4 id="2-标题"><a href="#2-标题" class="headerlink" title="2 标题"></a>2 标题</h4><p>使用n个#加一个空格表示n级标题。<br>语法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 一级标题</span><br><span class="line">## 二级标题</span><br><span class="line">### 三级标题</span><br><span class="line">#### 四级标题</span><br></pre></td></tr></table></figure><h4 id="3-列表"><a href="#3-列表" class="headerlink" title="3 列表"></a>3 列表</h4><ul><li><p>无序列表<br>使用<em>加一个空格表示,还可以使用 + - 表示,和 </em> 是一样的。建议在文档中使用自己喜欢的一种,而且在一组列表中不要混用多种标签,这样在不同的解释器中可能会被解释成不同的列表组。<br>语法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">* 1 </span><br><span class="line">* 2</span><br><span class="line">- 3</span><br><span class="line">- 4</span><br><span class="line">+ 5</span><br><span class="line">+ 6</span><br></pre></td></tr></table></figure></li><li><p>有序列表<br>使用正常的数字加一个.和空格表示。有序列表的序号有些解释器会根据第一行列表的数字顺序来递增的,还有一种会默认从1开始递增<br>语法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. 1</span><br><span class="line">2. 2</span><br><span class="line">3. 3</span><br></pre></td></tr></table></figure></li></ul><h4 id="4-区块引用"><a href="#4-区块引用" class="headerlink" title="4 区块引用"></a>4 区块引用</h4><p>区块引用使用>表示,为了代码的美观性,我们也在后面加一个空格表示。<br>语法:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">> 这是一个区块引用</span><br><span class="line">> 这是另一个区块引用</span><br><span class="line">>> 这是一个二级嵌套引用</span><br><span class="line">>>> 这是一个三级嵌套引用</span><br></pre></td></tr></table></figure><h4 id="5-分割线"><a href="#5-分割线" class="headerlink" title="5 分割线"></a>5 分割线</h4><p>三个或者三个以上的 - 或者 * 都可以。</p><h4 id="6-图片"><a href="#6-图片" class="headerlink" title="6 图片"></a>6 图片</h4><p>语法:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">![图片alt](图片地址 ''图片title'')</span><br></pre></td></tr></table></figure></p><p>图片alt就是显示在图片下面的文字,相当于对图片内容的解释。<br>图片title是图片的标题,当鼠标移到图片上时显示的内容。title可加可不加</p><h4 id="7-表格"><a href="#7-表格" class="headerlink" title="7 表格"></a>7 表格</h4><p>语法:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">表头|表头|表头</span><br><span class="line">---|:--:|---:</span><br><span class="line">内容|内容|内容</span><br><span class="line">内容|内容|内容</span><br></pre></td></tr></table></figure></p><h4 id="8-代码块-语法:"><a href="#8-代码块-语法:" class="headerlink" title="8 代码块
语法:"></a>8 代码块
语法:</h4><p>单行代码:代码之间分别用一个反引号包起来<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">`代码内容`</span><br></pre></td></tr></table></figure></p><p>代码块:代码之间分别用三个反引号包起来,且两边的反引号单独占一行<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">\```代码块```\</span><br></pre></td></tr></table></figure></p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> markdown </category>
</categories>
<tags>
<tag> markdown </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第十一章总结</title>
<link href="/2020/02/26/http11/"/>
<url>/2020/02/26/http11/</url>
<content type="html"><![CDATA[<p>互联网上的攻击大都将web站点作为目标。本章讲解具体有哪些攻击web站点的手段,以及攻击会造成怎样的影响。<br><a id="more"></a></p><h1 id="web的攻击技术(第十一章)"><a href="#web的攻击技术(第十一章)" class="headerlink" title="web的攻击技术(第十一章)"></a>web的攻击技术(第十一章)</h1><p><br></p><h3 id="11-1-针对web的攻击技术"><a href="#11-1-针对web的攻击技术" class="headerlink" title="11.1 针对web的攻击技术"></a>11.1 针对web的攻击技术</h3><p><img src="/images/http/http-11-1.png" alt=""></p><h4 id="11-1-1-http不具备必要的安全功能"><a href="#11-1-1-http不具备必要的安全功能" class="headerlink" title="11.1.1 http不具备必要的安全功能"></a>11.1.1 http不具备必要的安全功能</h4><p>与最初的设计相比,现今几乎所有的 Web 网站都会使用会话(session)管理、加密处理等安全性方面的功能,而 HTTP 协议并不具备这些功能。<br>整体上看,HTTP 就是一个通用的单纯协议机制,因此它具备较多优势,但是在安全性方面呈劣势。<br>开发者需自行设计并开发认证及会话管理功能来满足 Web 应用的安全,但是自行设计会出现各种形形色色的实现,安全等级并不完备。</p><h4 id="11-1-2-在客户端即可篡改请求"><a href="#11-1-2-在客户端即可篡改请求" class="headerlink" title="11.1.2 在客户端即可篡改请求"></a>11.1.2 在客户端即可篡改请求</h4><p>在 Web 应用中,从浏览器那接收到的 HTTP 请求的全部内容,都可以在客户端自由的变更、篡改。所以 Web 应用可能会接收到与预期数据不相同的内容。<br>在 HTTP 请求报文内加载攻击代码,就能发起对 Web 应用的攻击。<br><img src="/images/http/http-11-2.png" alt=""></p><h4 id="11-1-3-针对web应用的攻击模式"><a href="#11-1-3-针对web应用的攻击模式" class="headerlink" title="11.1.3 针对web应用的攻击模式"></a>11.1.3 针对web应用的攻击模式</h4><p>对 Web 应用的攻击模式有以下两种。</p><ol><li>主动攻击</li><li>被动攻击</li></ol><ul><li>以服务器为目标的主动攻击<br>主动攻击(active attack)是指攻击者通过直接访问 Web 应用,把攻击代码传入的攻击模式。由于该模式是直接针对服务器上的资源进行攻击,因此攻击者需要能够访问到那些资源。<br>主动攻击模式里具有代表性的攻击是 SQL 注入攻击和 OS 命令注入攻击。<br><img src="/images/http/http-11-3.png" alt=""></li><li>以服务器为目标的被动攻击<br>被动攻击(passive attack)是指利用圈套策略执行攻击代码的攻击模式。在被动攻击过程中,攻击者不直接对目标 Web 应用访问发起攻击。<br>被动攻击通常的攻击模式入如下:</li></ul><ol><li>攻击者诱使用户触发已设置好的陷阱,而陷阱会启动发送已嵌入攻击代码的 HTTP 请求。</li><li>当用户不知不觉中招后,用户的浏览器或邮件客户端就会触发这个请求。</li><li>中招后的用户更浏览器会把含有攻击代码的 HTTP 请求发送给作为攻击目标的 Web 应用,运行攻击代码。</li><li>执行完攻击代码,存在安全漏洞的 Web 应用会称为攻击者的跳板,可能导致用户所持有的 Cookie 等个人信息被窃取。<br>被动攻击模式中具有代表性的攻击是跨站脚本攻击和跨站点请求伪造。<br><img src="/images/http/http-11-4.png" alt=""></li></ol><p>利用被动攻击,可发起对原本从互联网上无法直接访问的企业内网等网络的攻击。<br><img src="/images/http/http-11-5.png" alt=""></p><h3 id="11-2-因输出值转义不完全引发的安全漏洞"><a href="#11-2-因输出值转义不完全引发的安全漏洞" class="headerlink" title="11.2 因输出值转义不完全引发的安全漏洞"></a>11.2 因输出值转义不完全引发的安全漏洞</h3><p>实施 Web 应用的安全对策可大致分为以下两部分:</p><ul><li>客户端的验证</li><li>Web 应用端(服务器端)的验证</li><li>输入值验证</li><li>输出值转义<br><img src="/images/http/http-11-6.png" alt=""></li></ul><p>多数情况下采用 JavaScript 在客户端验证数据。保留客户端验证数据只是为了尽早的辨识输入错误,起到提供 UI 的作用。<br>输入值验证通常是指检查是否是符合系统业务逻辑的数值或检查字符编码等预防对策。<br>针对输出做值转义处理是一项至关重要的安全策略。当输出值转义不完全时,会因触发攻击者传入的攻击代码,而给输出对象带来损害。</p><h4 id="11-2-1-跨站脚本攻击"><a href="#11-2-1-跨站脚本攻击" class="headerlink" title="11.2.1 跨站脚本攻击"></a>11.2.1 跨站脚本攻击</h4><p>跨站脚本攻击(Cross-Site Scripting,XSS)是指通过存在安全漏洞的 Web 网站注册用户的浏览器内运行非法的 HTML 标签或者 JavaScript 进行的一种攻击。<br>跨站脚本攻击有可能造成以下影响。</p><ul><li>利用虚假输入表单骗取用户个人信息</li><li>利用脚本窃取用户的 Cookie 值,被害者在不知情的情况下,帮助攻击者发送恶意请求</li><li>显示伪造的文章或图片<br>XSS 是攻击者利用预先设置的陷阱触发的被动攻击。<br>跨站脚本攻击属于被动攻击模式,因此攻击者会事先布置 好用于攻击的陷阱。<h4 id="11-2-2-sql注入攻击"><a href="#11-2-2-sql注入攻击" class="headerlink" title="11.2.2 sql注入攻击"></a>11.2.2 sql注入攻击</h4>会执行非法 SQL 的 SQL 注入攻击。<br>SQL 注入(SQL Injection) 是指针对 Web 应用使用的数据库,通过运行非法的 SQL 而产生的攻击。可能会导致个人信息及机密信息的泄漏。<br>SQL 注入攻击可能会造成以下等影响。</li><li>非法查看或篡改数据库内的数据</li><li>规避认证</li><li>执行和数据库服务器业务关联的程序<br>SQL 注入是攻击者将 SQL 语句改变成开发者意想不到的形式以达到破坏结构的攻击。<h4 id="11-2-3-os命令注入攻击"><a href="#11-2-3-os命令注入攻击" class="headerlink" title="11.2.3 os命令注入攻击"></a>11.2.3 os命令注入攻击</h4>OS 命令注入攻击(OS Command Injection)是指通过 Web 应用,执行非法的操作系统命令达到攻击的目的。只要在能调用 Shell 函数的地方就有存在被攻击的风险。<br>通过 OS 注入攻击可执行 OS 上安装着的各种程序。<h4 id="1-2-4-http首部注入攻击"><a href="#1-2-4-http首部注入攻击" class="headerlink" title="1.2.4 http首部注入攻击"></a>1.2.4 http首部注入攻击</h4>HTTP 首部注入攻击(HTTP Header Injection)是指攻击者通过在响应首部字段内插入换行,添加任意响应首部或主体的一种攻击。属于被动攻击模式。<br>向首部主体内添加内容的攻击称为 HTTP 响应截断攻击(HTTP Response Splitting Attack)。<br>HTTP 首部注入攻击可能会造成以下一些影响。</li><li>设置任何 Cookie 信息</li><li>重定向至任意 URL</li><li>显示任意的主体(HTTP 响应截断攻击)<br>滥用 HTTP/1.1 中汇集多响应返回功能,会导致缓存服务器对任意内容进行缓存操作。这种攻击称为缓存污染。<h4 id="11-2-5邮件首部注入攻击"><a href="#11-2-5邮件首部注入攻击" class="headerlink" title="11.2.5邮件首部注入攻击"></a>11.2.5邮件首部注入攻击</h4>邮件首部注入(Mail Header Injection)是指 Web 应用中的邮件发送功能,攻击者通过向邮件首部 TO 或 Subject 内任意添加非法内容发起的攻击。利用存在安全漏洞的 Web 网站,可对任意邮件地址发送广告邮件或病毒邮件。<h4 id="11-2-6目录遍历攻击"><a href="#11-2-6目录遍历攻击" class="headerlink" title="11.2.6目录遍历攻击"></a>11.2.6目录遍历攻击</h4>目录遍历(Directory Traversal)攻击是指对本无意公开的文件目录,通过非法截断其目录路径后,达成访问的目的的一种攻击。这种攻击有时也称为路径遍历(Path Traversal)攻击。<h4 id="11-2-7远程文件包含漏洞"><a href="#11-2-7远程文件包含漏洞" class="headerlink" title="11.2.7远程文件包含漏洞"></a>11.2.7远程文件包含漏洞</h4>远程文件包含漏洞(Remote File Inclusion)是指当部分脚本内容需要从其他文件读入时,攻击者利用指定外部服务器的 URL 充当依赖文件,让脚本读取之后,就可运行任意脚本的一种攻击。<h3 id="11-3-因设置或设计上的缺陷引发的安全漏洞"><a href="#11-3-因设置或设计上的缺陷引发的安全漏洞" class="headerlink" title="11.3 因设置或设计上的缺陷引发的安全漏洞"></a>11.3 因设置或设计上的缺陷引发的安全漏洞</h3><h4 id="11-3-1-强制浏览"><a href="#11-3-1-强制浏览" class="headerlink" title="11.3.1 强制浏览"></a>11.3.1 强制浏览</h4>强制浏览(Forced Browsing)安全漏洞是指,从安置在 Web 服务器的公开目录下的文件中,浏览那些原本非自愿公开的文件。<br>强制浏览可能会造成以下一些影响。</li><li>泄漏顾客的个人信息等重要情报</li><li>泄漏原本需要具有访问权限的用户才可以查阅的内容</li><li>泄漏未连到外界的文件<h4 id="11-3-2不正确的错误信息处理"><a href="#11-3-2不正确的错误信息处理" class="headerlink" title="11.3.2不正确的错误信息处理"></a>11.3.2不正确的错误信息处理</h4>不正确的错误消息处理(Error Handling Vulnerability)的安全漏洞是指,Web 应用的错误信息包含对攻击者有用的信息。与 Web 应用有关的主要错误信息如下所示。</li><li>Web 应用抛出的错误信息</li><li>数据库等系统抛出的错误信息<br>系统抛出的错误主要集中在以下几个方面。</li><li>PHP 或 ASP 等脚本错误</li><li>数据库或中间件的错误</li><li>Web 服务器的错误<br>各系统应对详细的错误消息进行抑制设定,或使用自定义用户消息,以避免某些错误消息给攻击者以启发。<h4 id="11-3-3开放重定向"><a href="#11-3-3开放重定向" class="headerlink" title="11.3.3开放重定向"></a>11.3.3开放重定向</h4>开放重定向(Open Redirect)是一种对指定的任意 URL 作重定向跳转的功能。<br>可信度高的 Web 网站如果开放重定向功能,则很有可能被攻击者选中并用来作为钓鱼攻击的跳板。<h3 id="11-4-因会话管理疏忽引发的安全漏洞"><a href="#11-4-因会话管理疏忽引发的安全漏洞" class="headerlink" title="11.4 因会话管理疏忽引发的安全漏洞"></a>11.4 因会话管理疏忽引发的安全漏洞</h3>会话管理就是用来管理用户状态的必备功能,但是如果在会话管理上有所疏忽,就会导致用户的认证状态被窃取等后果。<h4 id="11-4-1-会话劫持"><a href="#11-4-1-会话劫持" class="headerlink" title="11.4.1 会话劫持"></a>11.4.1 会话劫持</h4>会话劫持(Session Hijack)是指攻击者通过某种手段拿到了用户的会话 ID,并非法使用此会话 ID 伪装成用户,达到攻击的目的。<br><img src="/images/http/http-11-7.png" alt=""></li></ul><p>具备认证功能的 Web 应用,使用会话 ID 的会话管理机制,作为认证管理状态的主流方式。会话 ID 中记录客户端的 Cookie 等消息,服务器会将会话 ID 与认证状态进行一对一匹配管理。<br>攻击者可能会获得会话 ID 的几种途径如下所示。</p><ul><li>通过非正规的生成方法推测会话 ID</li><li>通过窃听或 XSS 攻击盗取会话 ID</li><li>通过会话固定攻击(Session Fixation)强行获取会话 ID<h4 id="11-4-2-会话固定攻击"><a href="#11-4-2-会话固定攻击" class="headerlink" title="11.4.2 会话固定攻击"></a>11.4.2 会话固定攻击</h4>对以窃取目标会话 ID 为主动攻击收到的会话劫持而言,会话固定攻击(Session Fixation)攻击会强制用户使用攻击者指定的会话 ID,属于被动攻击。<h4 id="11-4-3-跨站点请求伪造"><a href="#11-4-3-跨站点请求伪造" class="headerlink" title="11.4.3 跨站点请求伪造"></a>11.4.3 跨站点请求伪造</h4>跨站点请求伪造(Cross-Site Request Forgeries,CSRF)攻击是指攻击者通过设置好的陷阱,强制对已完成认证的用户进行非预期的个人信息或设定信息等某些状态更新,属于被动攻击。<br>跨站点请求伪造有可能会造成以下等影响。</li><li>利用已通过认证的用户权限更新设定信息等</li><li>利用已通过认证的用户权限购买商品</li><li>利用已通过认证的用户权限在留言板上发表评论<h3 id="11-5-其他安全漏洞"><a href="#11-5-其他安全漏洞" class="headerlink" title="11.5 其他安全漏洞"></a>11.5 其他安全漏洞</h3><h4 id="11-5-1-密码破解"><a href="#11-5-1-密码破解" class="headerlink" title="11.5.1 密码破解"></a>11.5.1 密码破解</h4>密码破解(Password Cracking)即算出密码,突破认证。<br>密码破解有以下两种手段。</li><li>通过网络的密码试错</li><li>对已加密密码的破解(指攻击者入侵系统,已获得加密或散列处理的密码数据的情况)<br>除去突破认证的攻击手段,还有 SQL 注入攻击逃避认证,跨站脚本攻击窃取密码信息等方法。<br>通过网络进行密码试错<br>对 Web 应用提供的认证功能,通过网络尝试候选密码进行的一种攻击。主要有以下两种方式。</li><li>穷举法<br>穷举法(Brute-force Attack,又称暴力破解法)是指对所有密钥集合构成的密钥空间(Keyspace)进行穷举。用所有可行的候选密码对目标的密码系统试错,用以图片验证的一种攻击。</li><li>字典攻击<br>字典攻击是指利用事先收集好的候选密码(经过各种组合方式后存入字典),枚举字典中的密码,尝试通过认证的一种攻击手段。<br><img src="/images/http/http-11-8.png" alt=""><br>对已加密密码的破解<br><img src="/images/http/http-11-9.png" alt=""><br>从加密过的数据中导出明文通常有以下几种方法</li><li><p>通过穷举法字典攻击进行类推<br>针对密码使用散列函数进行加密处理的情况,采用和穷举法或字典攻击相同的手法,尝试调用相同的散列函数加密候选密码,然后把计算出的散列值与目标散列值进行匹配,类推出密码。<br><img src="/images/http/http-11-10.png" alt=""></p></li><li><p>彩虹表<br>彩虹表(Rainbow Table)是由明文密码及与之对应的散列值构成的一张数据库表,是一种通过事先制作庞大的彩虹表,可在穷举法·字典攻击等实际破解过程中缩短消耗时间的技巧。从彩虹表内搜索散列值就可以推导出对应的明文密码。<br><img src="/images/http/http-11-11.png" alt=""></p></li><li><p>拿到密钥<br>使用共享密钥加密方式对密码数据进行加密处理的情况下,如果通过某种手段拿到加密使用的密钥,也就可以对密码数据解密了。</p></li><li>加密算法的漏洞<br>考虑到加密算法本身可能存在的漏洞,利用该漏洞尝试解密也是一种可行的方法。<h4 id="11-5-2-点击劫持"><a href="#11-5-2-点击劫持" class="headerlink" title="11.5.2 点击劫持"></a>11.5.2 点击劫持</h4>点击劫持(Clickjacking)是指利用透明的按钮或链接做成陷阱,覆盖在 Web 页面之上。然后诱使用户在不知情的情况下,点击那个链接访问内容的一种攻击手段。这种行为又称界面伪装 (UI Redressing)。<br><img src="/images/http/http-11-12.png" alt=""></li></ul><h4 id="11-5-3-Dos攻击"><a href="#11-5-3-Dos攻击" class="headerlink" title="11.5.3 Dos攻击"></a>11.5.3 Dos攻击</h4><p>DoS 攻击(Denial of Service attack)是一种让运行中的服务呈停止状态的攻击。有时也叫做服务停止攻击或拒绝服务攻击。DoS 攻击的对象不仅限于 Web 网站,还包括网络设备及服务器等。<br>主要有以下两种方式实现 DoS 攻击。</p><ul><li>集中利用访问请求造成资源过载,资源用尽的同时,实际上服务也就呈现停止状态</li><li>通过攻击安全漏洞是服务停止<br><img src="/images/http/http-11-13.png" alt=""></li></ul><p>多台计算机发起的 DoS 攻击称为 DDoS 攻击(Distuibuted Denial of Service attack)。DDoS 攻击通常利用那些感染病毒的计算机作为攻击者的攻击跳板</p><h4 id="11-5-4-后门程序"><a href="#11-5-4-后门程序" class="headerlink" title="11.5.4 后门程序"></a>11.5.4 后门程序</h4><p>后门程序(Backdoor)是指开发设置的隐藏入口,可不按正常步骤使用受限功能,利用后门程序就能够使用原本受限制的功能。<br>通常的后门程序可分为以下 3 种类型。</p><ul><li>开发阶段作为debug调用的后门程序</li><li>开发者为了自身利益植入的后门程序</li><li>攻击者通过某种方法设置的后门程序</li></ul><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第十章总结</title>
<link href="/2020/02/24/http10/"/>
<url>/2020/02/24/http10/</url>
<content type="html"><![CDATA[<p>在web刚出现时,我们只能浏览那些页面样式简单的内容。如今,web使用各种各样的技术,来呈现丰富多彩的内容。<br><a id="more"></a></p><h1 id="构建web内容的技术(第十章)"><a href="#构建web内容的技术(第十章)" class="headerlink" title="构建web内容的技术(第十章)"></a>构建web内容的技术(第十章)</h1><p><br></p><h3 id="10-1-HTML"><a href="#10-1-HTML" class="headerlink" title="10.1 HTML"></a>10.1 HTML</h3><h4 id="10-1-1-web页面几乎全由html构建"><a href="#10-1-1-web页面几乎全由html构建" class="headerlink" title="10.1.1 web页面几乎全由html构建"></a>10.1.1 web页面几乎全由html构建</h4><p>html(hypertext Markup Language)超文本标记语言。</p><h4 id="10-1-2-html版本"><a href="#10-1-2-html版本" class="headerlink" title="10.1.2 html版本"></a>10.1.2 html版本</h4><p>html5 是目前最新版本</p><h4 id="10-1-3-设计应用"><a href="#10-1-3-设计应用" class="headerlink" title="10.1.3 设计应用"></a>10.1.3 设计应用</h4><p>css (cascading style sheets)层叠样式表。css控制浏览器页面外观。</p><h3 id="10-2-动态html"><a href="#10-2-动态html" class="headerlink" title="10.2 动态html"></a>10.2 动态html</h3><h4 id="10-2-1-让web页面动起来的动态html"><a href="#10-2-1-让web页面动起来的动态html" class="headerlink" title="10.2.1 让web页面动起来的动态html"></a>10.2.1 让web页面动起来的动态html</h4><p>动态html指客户端脚本语言讲静态的html内容变成动态的技术的总称,通过调用客户端脚本语言javascript,实现对web页面的动态改造。</p><h4 id="10-2-2-更易控制html的dom"><a href="#10-2-2-更易控制html的dom" class="headerlink" title="10.2.2 更易控制html的dom"></a>10.2.2 更易控制html的dom</h4><p>DOM 是用以操作html文档和xml文档的api。使用dom将html内的元素当作对象操作。</p><h3 id="10-3-web应用"><a href="#10-3-web应用" class="headerlink" title="10.3 web应用"></a>10.3 web应用</h3><h4 id="10-3-1-通过web提供功能的web应用"><a href="#10-3-1-通过web提供功能的web应用" class="headerlink" title="10.3.1 通过web提供功能的web应用"></a>10.3.1 通过web提供功能的web应用</h4><p>web应用是指通过web功能提供的应用程序。</p><h4 id="10-3-2-与web服务器及程序协作的CGI"><a href="#10-3-2-与web服务器及程序协作的CGI" class="headerlink" title="10.3.2 与web服务器及程序协作的CGI"></a>10.3.2 与web服务器及程序协作的CGI</h4><p>CGI (Common Gateway Interface)通用网关接口。是指web服务器在接收到客户端发送过来的请求后转发给程序的一组机制。</p><h4 id="10-3-3-因java而普及的servlet"><a href="#10-3-3-因java而普及的servlet" class="headerlink" title="10.3.3 因java而普及的servlet"></a>10.3.3 因java而普及的servlet</h4><p>servlet是一种能在服务器上创建动态内容的程序。是用java语言实现的一个借口,属于面向企业级java的一部分。Servlet运行环境叫做web容器或servlet容器。Servlet运行在与web服务器相同的进程中,因此受到的负载较小。</p><h3 id="10-4-数据发布的格式及语言"><a href="#10-4-数据发布的格式及语言" class="headerlink" title="10.4 数据发布的格式及语言"></a>10.4 数据发布的格式及语言</h3><h4 id="10-4-1-可拓展标记语言"><a href="#10-4-1-可拓展标记语言" class="headerlink" title="10.4.1 可拓展标记语言"></a>10.4.1 可拓展标记语言</h4><p>XML (eXtensible Markup Language,可扩展标记语言)是一种可按应用目标进行扩展的通用标记语言。旨在通过使用 XML,是互联网数据共享变得更加容易。<br>XML 和 HTML 一样,使用标签构成树形结构,并且可自定义扩展标签。<br>从 XML 文档中读取数据比起 HTML 更为简单。由于 XML 的结构基本上都是用标签分割而成的树形结构,因此通过语法分析器(Parser)的解析功能解析 XML 结构并取出数据元素,可更容易的对数据进行读取。</p><h4 id="10-4-2-发布更新信息的RSS-Atom"><a href="#10-4-2-发布更新信息的RSS-Atom" class="headerlink" title="10.4.2 发布更新信息的RSS/Atom"></a>10.4.2 发布更新信息的RSS/Atom</h4><p>RSS(简易信息聚合,也叫聚合内容)和 Atom 都是发布新闻或博客日志等更新信息文档的格式的总称。两者都用到了 XML。<br>RSS 有以下版本:</p><ul><li>RSS 0.9(RDF Site Summary): 最初的 RSS 版本。</li><li>RSS 0.91(Rich Site Summary): 在 RSS0.9的基础上扩展元素。非 RDF 规格,使用 XML 方式编写。</li><li>RSS 1.0(RDF Site Summary): RSS规格正处于混乱状态。</li><li>RSS 2.0(Really Simple Syndication): 非 RSS 1.0 路线。增加支持 RSS0.91 的兼容性。</li><li>Atom 具有以下两种标准。</li><li>Atom 供稿格式(Atom Syndication Format):为发布内容而制定的网站消息来源格式。</li><li>Atom 出版协定(Atom Publishing Protocol): 为 Web 上内容的新增或修改而制定的协议。<h4 id="10-4-3-javascript-衍生的轻量级易用JSON"><a href="#10-4-3-javascript-衍生的轻量级易用JSON" class="headerlink" title="10.4.3 javascript 衍生的轻量级易用JSON"></a>10.4.3 javascript 衍生的轻量级易用JSON</h4>JSON(JavaScript Object Notation)是一种以 JavaScript 的对象表示法为基础的轻量级数据标记语言。<br>能够处理的数据类型有 false/null/true/对象/数组/数字/字符串 这 7 种类型。<br>示例:<blockquote><p>{“name”: “Web Application Security”, “num”: “TR001”}</p></blockquote></li></ul><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第九章总结</title>
<link href="/2020/01/09/http9/"/>
<url>/2020/01/09/http9/</url>
<content type="html"><![CDATA[<p>随着时代发展,功能使用上捉襟见肘的疲态已经凸显,主要讲解基于http新增的功能的协议。<br><a id="more"></a></p><h1 id="基于http的功能追加协议-第九章"><a href="#基于http的功能追加协议-第九章" class="headerlink" title="基于http的功能追加协议(第九章)"></a>基于http的功能追加协议(第九章)</h1><p><br></p><h3 id="9-1-基于http的协议"><a href="#9-1-基于http的协议" class="headerlink" title="9.1 基于http的协议"></a>9.1 基于http的协议</h3><p>随着web应用的发展,http协议的限制和自身性能变得有限。由于http协议使用范围广泛并遍布全球。因此无法抛弃,所以需要在原有基础上添加新的功能。</p><h3 id="9-2-消除http瓶颈的spd"><a href="#9-2-消除http瓶颈的spd" class="headerlink" title="9.2 消除http瓶颈的spd"></a>9.2 消除http瓶颈的spd</h3><p>google 2010年发布SPDY,开发目标旨在解决http 的性能瓶颈,缩短web页面的加载时间。</p><h4 id="9-2-1-http的瓶颈"><a href="#9-2-1-http的瓶颈" class="headerlink" title="9.2.1 http的瓶颈"></a>9.2.1 http的瓶颈</h4><p>使用http协议探知服务器上是否有内容更新,就必须频繁的从客户端道服务端进行确认。如果服务器上没有内容更新,那么就会产生徒劳的通信。<br>若想在现有Web实现所需的功能,以下这些http标准就会成为瓶颈。</p><ul><li>一条连接上只可发送一个请求。</li><li>请求只能从客户端开始。客户端不可以接收除响应以外的指令。</li><li>请求/响应首部未经压缩就发送。首部信息越多延迟越大。</li><li>发送冗长的首部。每次互相发送相同的首部造成的浪费较多。</li><li>可任意选择数据压缩格式。非强制压缩发送。</li></ul><p><img src="/images/http/http-9-1.png" alt=""></p><h4 id="Ajax-的解决方法"><a href="#Ajax-的解决方法" class="headerlink" title="Ajax 的解决方法"></a>Ajax 的解决方法</h4><p>Ajax(Asynchronous JavaScript and XML,异步 JavaScript 与 XML 技术) 是一种有效利用 JavaScript 和 DOM(Document Object Model,文档对象模型)的操作。以达到局部 Web 页面替换加载的异步通信手段。<br>Ajax 的核心技术是名为 XMLHttpRequest 的 API,通过 JavaScript 脚本语言的调用就能和服务器进行 HTTP 通信。借用这种手段,就能从已加载完毕的 Web 页面上发起请求,只更新局部页面。<br>利用 Ajax 实时的从服务器获取内容,有可能会导致大量请求产生。另外 Ajax 仍未解决 HTTP 协议本身存在的问题。<br><img src="/images/http/http-9-2.png" alt=""></p><h4 id="Comet-的解决方法"><a href="#Comet-的解决方法" class="headerlink" title="Comet 的解决方法"></a>Comet 的解决方法</h4><p>一旦服务器有内容更新,Comet 不会让请求等待,而是直接给客户端返回响应。这是一种通过延迟应答,模拟实现服务器端向客户端推送(Server Push)的功能。<br>通常,服务器端接收到请求,在处理完毕后就会立即返回响应,但为了实现推送功能,Comet 会先将响应置于挂起状态,当服务器端有内容更新时,再返回该响应。因此,服务器端一旦有更新,就可以立即反馈给客户端。<br>通过 Comet 内容上可以做到实时更新,但为了维持连接会消耗更多的资源。另外,Comet 也仍未解决 HTTP 协议本身存在的问题。<br><img src="/images/http/http-9-3.png" alt=""></p><h4 id="SPDY-的目标"><a href="#SPDY-的目标" class="headerlink" title="SPDY 的目标"></a>SPDY 的目标</h4><p>处于持续开发状态中的 SPDY 协议,正是为了在协议级别消除 HTTP 所遭遇的瓶颈。</p><h4 id="9-2-2-SPDY的设计与功能"><a href="#9-2-2-SPDY的设计与功能" class="headerlink" title="9.2.2 SPDY的设计与功能"></a>9.2.2 SPDY的设计与功能</h4><p>SPDY 并没有完全改写 HTTP 协议,而是在 TCP/IP 的应用层与运输层之间通过新加会话层的形式运作。考虑到安全性问题,SPDY 规定通信中使用 SSL。<br>SPDY 以会话层的形式加入,控制对数据的流动。但还是采用 HTTP 建立连接通信。<br><img src="/images/http/http-9-4.png" alt=""></p><p>使用 SPDY 后,HTTP 协议额外获得以下功能。</p><ul><li>多路复用流<br>通过单一的 TCP 连接,可以无限制处理多个 HTTP 请求。所有请求的处理都在一条 TCP 连接上完成。因此 TCP 的处理效率得到提高。</li><li>赋予请求优先级<br>SPDY 不仅可以无限制地并发处理请求,还可以给请求逐个分配优先级顺序。主要是为了在发送多个请求时,解决因带宽低而导致响应变慢的问题。</li><li>压缩 HTTP 首部<br>压缩 HTTP 请求和响应的首部。这样一来,通信产生的数据包数量和发送的字节数就更少了。</li><li>推送功能<br>支持服务器主动向客户端推送数据的功能。这样,服务器可直接发送数据,而不必等待客户端的请求。</li><li>服务器提示功能<br>服务器可以主动提示客户端请求所需的资源。<h4 id="9-2-3-SPDY消除Web瓶颈了么"><a href="#9-2-3-SPDY消除Web瓶颈了么" class="headerlink" title="9.2.3 SPDY消除Web瓶颈了么"></a>9.2.3 SPDY消除Web瓶颈了么</h4>SPDY是一种可有效消除http瓶颈的技术,但web本身的速度提升,并非仅仅是由http瓶颈造成的。应该从其他可细致钻研的地方入手。<h3 id="9-3-使用浏览器进行全双工通信的websocket"><a href="#9-3-使用浏览器进行全双工通信的websocket" class="headerlink" title="9.3 使用浏览器进行全双工通信的websocket"></a>9.3 使用浏览器进行全双工通信的websocket</h3>WebSocket 网络技术正是为解决 HTTP 瓶颈问题而实现的一套新协议及 API。</li></ul><h4 id="9-3-1-WebSocket的设计与功能"><a href="#9-3-1-WebSocket的设计与功能" class="headerlink" title="9.3.1 WebSocket的设计与功能"></a>9.3.1 WebSocket的设计与功能</h4><p>WebSocket,即 Web 浏览器与 Web 服务器之间全双工通信标准。其中,WebSocket 协议由 IETF 定为标准,WebSocket 由 W3C 定位标准。<br>仍在开发中的 WebSocket 技术主要是为了解决 Ajax 和 Comet 里 XMLHttpRequest 附带的缺陷所引起的问题。</p><h4 id="9-3-2-WebSocket协议"><a href="#9-3-2-WebSocket协议" class="headerlink" title="9.3.2 WebSocket协议"></a>9.3.2 WebSocket协议</h4><p>一旦 Web服务器与客户端之间建立起 WebSocket 协议的通信连接,之后所有的通信都依靠这个专用协议进行。通信过程中可互相发送 JSON、XML、HTML 或图片等任意格式的数据。<br>由于是建立在 HTTP 基础上的协议,因此连接的发起方仍是客户端,而一旦建立 WebSocket 通信连接,不论服务器还是客户端,任意一方都可直接向对方发送报文。<br>WebSocket 协议的主要特点如下:</p><ul><li>推送功能<br>支持由服务器向客户端推送数据的推送功能。这样,服务器可直发送数据,而不必等待客户端的请求。</li><li>减少通信量<br>只要建立起 WebSocket 连接,就希望一直保持连接状态。和 HTTP 相比,不但每次连接时的总开销减少,而且由于 WebSocket 的首部信息很小,通信量也相应减少了。<br>为了实现 WebSocket 通信,在 HTTP 连接建立之后,需要完成一次握手(Handshaking)的步骤。</li><li>握手·请求<br>为了实现 WebSocket 通信,需要用到 HTTP 的 Upgrade 首部字段,告知服务器通信协议发生改变,以达到握手的目的。</li></ul><blockquote><p>GET /chat HTTP/1.1<br>Host: server.example.com<br>Upgrade: websocket<br>Connection: Upgrade<br>Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==<br>Origin: <a href="http://example.com" target="_blank" rel="noopener">http://example.com</a><br>Sec-WebSocket-Protocol: chat, superchat<br>Sec-WebSocket-Version: 13</p></blockquote><p>Sec-WebSocket-Protocol 字段内记录着握手过程中必不可少的键值。<br>Sec-WebSocket-Version 字段内记录使用的子协议。</p><ul><li>握手·响应<br>对于之前的请求,返回状态码 101 Switching Protocols 的响应。<br>HTTP/1.1 101 Switching Protocols<br>Upgrade: websocket<br>Connection: Upgrade<br>Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=<br>Sec-WebSocket-Protocol: chat</li></ul><p>Sec-WebSocket-Accept 的字段值是由握手请求中的 Sec-WebSocket-Key 的字段值生成的。<br>成功握手并建立 WebSocket 连接之后,通信时不再使用 HTTP 的数据帧,而采用 WebSocket 独立的数据帧。<br><img src="/images/http/http-9-5.png" alt=""></p><h4 id="WebSocket-API"><a href="#WebSocket-API" class="headerlink" title="WebSocket API"></a>WebSocket API</h4><p>JavaScript 可调用 The WebSocket API 内提供的 WebSocket 程序接口。以实现 WebSocket 协议下全双工通信。<br>以下是调用 WebSocket API,每 50ms 发送 一次数据的实例。</p><blockquote><p>var socket = new WebSocket(‘ws://game.example.com:12010/updates’);<br>socket.onopen = function () {<br> setInterval(function() {<br> if (socket.bufferedAmount == 0)<br> socket.send(getUpdateData());<br> }, 50);<br>};</p></blockquote><h3 id="9-4-期盼已久的http-2-0"><a href="#9-4-期盼已久的http-2-0" class="headerlink" title="9.4 期盼已久的http/2.0"></a>9.4 期盼已久的http/2.0</h3><p>HTTP/2.0 的目标是改善用户在使用 Web 时的速度体验。<br>HTTP/2.0 的 7 项技术及讨论如下表格所示:<br><img src="/images/http/http-9-6.png" alt=""></p><h3 id="9-5-web服务器管理文件的WebDAV"><a href="#9-5-web服务器管理文件的WebDAV" class="headerlink" title="9.5 web服务器管理文件的WebDAV"></a>9.5 web服务器管理文件的WebDAV</h3><p>WebDAV(Web-based Distributed Authoring and Versioning,基于万维网的分布式创作和版本控制)是一个可对 Web 服务器上的内容直接进行复制、编辑等操作的分别式文件系统。作为扩展的 HTTP/1.1 协议。<br>除了创建、删除文件等基本功能,它还具备文件创建者管理、文件编辑过程中禁止其他用户内容覆盖的加锁功能,以及对文件内容修改的版本控制功能。<br><img src="/images/http/http-9-7.png" alt=""></p><h4 id="9-5-1拓展http-1-1的WebDAV"><a href="#9-5-1拓展http-1-1的WebDAV" class="headerlink" title="9.5.1拓展http/1.1的WebDAV"></a>9.5.1拓展http/1.1的WebDAV</h4><p>针对服务器上的资源,WebDAV 新增了一些概念,如下所示。<br><img src="/images/http/http-9-8.png" alt=""></p><ul><li>集合(Collection)<br>是一种统一管理多个资源的概念。以集合为单位可进行多种操作。也可以实现类似集合的集合这样的叠加。</li><li>资源(Resoucre)<br>把文件或集合称为资源。</li><li>属性(Property)<br>定义资源的属性。定义以 “名称=值” 的格式执行。</li><li>锁(Lock)<br>把文件设置成无法编辑状态。多人同时编辑时,可防止在同一时间进行内容写入。<br>9.5.2 WebDAV内新增的方法及状态码<br>WebDAV 为实现远程文件管理,向 HTTP/1.1 中追加了以下这些方法。</li><li>PROPFIND: 获取属性</li><li>PROPPATCH: 修改属性</li><li>MKCOL: 创建集合</li><li>COPY: 复制资源及属性</li><li>MOVE: 移动资源</li><li>LOCK: 资源加锁</li><li>UNLOCK: 资源解锁<br>为配合扩展的方法,状态码也随之扩展。</li><li>102 Processing: 可正常处理请求,但目前是处理中状态</li><li>207 Multi-Status: 存在多种状态</li><li>422 Unprocessible Entity: 格式正确,内容有误</li><li>423 Locked: 资源已被加锁</li><li>424 Failed Dependency: 处理与某请求关联的请求失败,因此不再维持依赖关系</li><li>507 Insufficient Storage: 保存空间不足</li></ul><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第八章总结</title>
<link href="/2019/12/13/http8/"/>
<url>/2019/12/13/http8/</url>
<content type="html"><![CDATA[<p>某些web页面需要对特定人员群体进行浏览限制,为达到此等目标,认证功能必不可少。<br><a id="more"></a></p><h1 id="确认访问用户身份的认证(第8章)"><a href="#确认访问用户身份的认证(第8章)" class="headerlink" title="确认访问用户身份的认证(第8章)"></a>确认访问用户身份的认证(第8章)</h1><p><br></p><h3 id="8-1-何为认证"><a href="#8-1-何为认证" class="headerlink" title="8.1 何为认证"></a>8.1 何为认证</h3><p>认证通常需要核对的信息指的是:</p><ul><li>密码:只有本人才会知道的字符串信息</li><li>动图令牌:仅限本人持有的设备内显示的一次性密码</li><li>数字证书:仅限本人(终端)持有的信息</li><li>生物认证:指纹和虹膜等本人的生理信息</li><li>IC 卡等:仅限本人持有的信息</li></ul><p>Http/1.0使用的认证方式</p><ul><li>BASIC 认证(基本认证)</li><li>DIGEST 认证(摘要认证)</li><li>SSL 客户端认证</li><li>FormBase 认证(基于表单认证)<h3 id="8-2-Basic-认证"><a href="#8-2-Basic-认证" class="headerlink" title="8.2 Basic 认证"></a>8.2 Basic 认证</h3></li></ul><p>Basic认证的步骤:</p><p><img src="/images/http/http-8-1.png" alt=""></p><ol><li>当请求的资源需要 BASIC 认证时,服务器会随状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段包含认证的方式(BASIC)及 Request-URI 安全域字符串(realm)。</li><li>接受到状态码 401 的客户端为了通过 BASIC 认证,需要将用户 ID 和密码经过 Base64 编码处理后发送给服务器。</li><li>接受到包含首部字段 Authorization 请求的服务器,会对认证信息的正确性进行验证。如验证通过,则返回一条包含 Request-URI 资源的响应。<br>BASIC 认证使用上不够便捷灵活,且达不到多数 Web 网站期望的安全性等级,因此并不常用。</li></ol><h3 id="8-3-Digest认证"><a href="#8-3-Digest认证" class="headerlink" title="8.3 Digest认证"></a>8.3 Digest认证</h3><p>DIGEST 认证同样使用质询/响应的方式(challenge/response),但不会像 BASIC 认证那样直接发送明文密码。<br>质询响应方式是指,一开始一方会先发送认证要求给另一方,接着使用从另一方接受到的质询码计算生成响应码,最后将响应码返回给对方进行认证的方式。<br><img src="/images/http/http-8-2.png" alt=""></p><p>因为发送给对方只是响应摘要及由质询码产生的计算结果,所以比起 BASIC 认证,密码泄漏的可能性就降低了。<br><img src="/images/http/http-8-3.png" alt=""></p><p>DIGEST 认证步骤</p><ol><li>请求需要认证的资源时,服务器会随状态码 401 Authorization Required,返回带 WWW-Authenticate 首部字段的响应。该字段内包含质问响应方式认证所需的临时质询码(随机数,nonce)。</li><li>首部字段 WWW-Authenticate 内必须包含 realm 和 nonce 这两个字段的信息。客户端就是依靠向服务器回送这两个值进行认证的。</li><li>接收到 401 状态码的客户端,返回的响应中包含 DIGEST 认证必须的首部字段 Authorization 信息。</li><li>接受到包含首部字段 Authorization 请求的服务器,会确认认证信息的正确性。认证通过后则返回包含 Request-URI 资源的响应。<br>DEGIST 认证提供了高于 BASIC 认证的安全等级,但是和 HTTPS 的客户端认证相比仍旧很弱,所以使用范围也有所受限</li></ol><h3 id="8-4-ssl-客户端认证"><a href="#8-4-ssl-客户端认证" class="headerlink" title="8.4 ssl 客户端认证"></a>8.4 ssl 客户端认证</h3><p>SSL 客户端认证是借由 HTTPS 的客户端证书完成认证的方式。凭借客户端证书认证,服务器可确认访问是否来已自登录的客户端。</p><h4 id="8-4-1-ssl客户端认证的认证步骤"><a href="#8-4-1-ssl客户端认证的认证步骤" class="headerlink" title="8.4.1 ssl客户端认证的认证步骤"></a>8.4.1 ssl客户端认证的认证步骤</h4><p>为达到 SSL 客户端认证的目的,需要事先将客户端证书发送给客户端,且客户端必须安装此证书</p><ol><li>接收到需要认证资源的请求,服务器会发送 Certificate Request 报文,要求客户端提供客户端证书。</li><li><p>用户选择将发送的客户端证书后,客户端会把客户端证书信息以 Client Certificate 报文方式发送给服务器。<br><img src="/images/http/http-8-4.png" alt=""></p></li><li><p>服务器验证客户端证书,验证通过后方可领取证书内客户端的公开密钥,然后开始 HTTPS 加密通信。</p></li></ol><h4 id="8-4-2-ssl客户端认证采用双因素认证"><a href="#8-4-2-ssl客户端认证采用双因素认证" class="headerlink" title="8.4.2 ssl客户端认证采用双因素认证"></a>8.4.2 ssl客户端认证采用双因素认证</h4><p>在多数情况下,SSL 客户端认证不会仅依靠证书完成认证,一般会和基于表单认证组合形成一种双因素认证来使用。<br>双因素认证是指,认证过程不仅需要密码这一个因素,还需要申请认证者提供其他持有信息,从而作为另一个因素,与其组合使用的认证方式。</p><h4 id="8-4-3-ssl客户端认证必要的费用"><a href="#8-4-3-ssl客户端认证必要的费用" class="headerlink" title="8.4.3 ssl客户端认证必要的费用"></a>8.4.3 ssl客户端认证必要的费用</h4><p>使用 SSL 客户端认证需要用到客户端证书,而客户端证书需要支付一定费用才能使用。</p><h3 id="8-5-基于表单认证"><a href="#8-5-基于表单认证" class="headerlink" title="8.5 基于表单认证"></a>8.5 基于表单认证</h3><p>基于表单的认证方法并不是在 HTTP 协议中定义的,客户端会向服务器上的 Web 应用程序发送登录信息(Credential),按登录信息的验证结果认证。</p><h4 id="8-5-1认证多半为基于表单认证"><a href="#8-5-1认证多半为基于表单认证" class="headerlink" title="8.5.1认证多半为基于表单认证"></a>8.5.1认证多半为基于表单认证</h4><p>对于 Web 网站的认证功能,能够满足其安全使用级别的标准规范并不存在,所以只好使用由 Web 应用程序各自实现基于表单的认证方式。<br><img src="/images/http/http-8-5.png" alt=""></p><h4 id="8-5-2-session管理及cookie应用"><a href="#8-5-2-session管理及cookie应用" class="headerlink" title="8.5.2 session管理及cookie应用"></a>8.5.2 session管理及cookie应用</h4><p>基于表单认证的标准规范尚未由定论,一般会使用 Cookie 来管理 Session。<br>基于表单认证本身是通过服务器端的 Web 应用,将客户端发送过来的用户 ID 和密码与之前登录过的信息做匹配来认证。<br>使用 Cookie 来管理 Session,来弥补 HTTP 协议中不存在的状态管理功能。<br><img src="/images/http/http-8-6.png" alt=""></p><ol><li>客户端把用户 ID 和密码等登录信息放入报文的实体部分,通常是以 POST 方法把请求发送给服务器。而这时,会使用 HTTS 通信来进行 HTML 表单表面的显示和用户输入数据的发送</li><li>服务器会发放用以识别用户的 Session ID。通过验证从客户端发送过来的登录信息进行身份验证,然后把用户的认证状态与 Session ID 绑定后记录在服务器端。</li><li>客户端接收到从服务器端发来的 Session ID 后,会将其作为 Cookie 保存在本地。下次向服务器发送请求时,浏览器会自动发送 Cookie,所以 Session ID 也随之发送到服务器。服务器可通过验证接受到的 Session ID 识别用户和其认证状态。</li></ol><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第七章总结</title>
<link href="/2019/11/01/http7/"/>
<url>/2019/11/01/http7/</url>
<content type="html"><![CDATA[<p>在http协议中有可能存在信息窃听或身份伪装等安全问题。使用https通信机制可以有效的防止这些问题。<br><a id="more"></a></p><h1 id="确保web安全的HTTPS-第七章"><a href="#确保web安全的HTTPS-第七章" class="headerlink" title="确保web安全的HTTPS(第七章)"></a>确保web安全的HTTPS(第七章)</h1><p><br></p><h3 id="7-1-http的缺点"><a href="#7-1-http的缺点" class="headerlink" title="7.1 http的缺点"></a>7.1 http的缺点</h3><p>主要有以下不足:</p><ul><li>通信使用明文(不加密),内容可能会被窃听</li><li>不验证通信方的身份,因此有可能遭遇伪装</li><li>无法证明报文的完整性,所以有可能已遭篡改</li></ul><h4 id="7-1-1-通信使用明文可能会被窃听"><a href="#7-1-1-通信使用明文可能会被窃听" class="headerlink" title="7.1.1 通信使用明文可能会被窃听"></a>7.1.1 通信使用明文可能会被窃听</h4><p>由于 HTTP 本身不具备加密的功能,所以也无法做到对通信整体(使用 HTTP 协议通信的请求和响应的内容)进行加密。即 HTTP 报文使用明文(指未经过加密的报文)方式发送 。</p><ul><li>TCP/IP 是可能被窃听的网络</li><li>按照 TCP/IP 协议族的工作机制,通信内容在所有的通信线路上都有可能遭到窥视。</li><li>加密处理防止被窃听</li><li>通信的加密</li><li>HTTP 协议中没有加密机制,但可以通过和 SSL(Secure Socket Layer,安全套接层) 或 TLS(Transport Layer Security,安全层传输协议) 的组合使用,加密 HTTP 通信的内容。</li><li>用 SSL 建立安全通信线路之后,就可以在这条通信线路 上进行 HTTP 通信。与 SSL 组合使用的 HTPP 被称为 HTTPS (HTTP Secure ,超文本传输安全协议)</li><li>内容的加密</li><li>将参与通信的内容本身加密,即把 HTTP 报文里所包含的内容进行加密处理</li><li>客户端需要对 HTTP 报文进行加密处理后再发送请求<h4 id="7-1-2-不验证同新方的身份就可能遭遇伪装"><a href="#7-1-2-不验证同新方的身份就可能遭遇伪装" class="headerlink" title="7.1.2 不验证同新方的身份就可能遭遇伪装"></a>7.1.2 不验证同新方的身份就可能遭遇伪装</h4>任何人都可以发送请求</li></ul><p><img src="/images/http/http-7-1.png" alt=""></p><p>不确认通信方,会存在以下各种隐患:</p><ul><li>无法确定请求发送至目标的 Web 服务器,是否是按照真实意图返回响应的服务器</li><li>无法确定响应返回到的客户端,是否是按真实意图接受响应的那个客户端</li><li>无法确定正在通信的双方是否具备访问权限</li><li>无法判定请求来自何方,出自谁手</li><li>即使是无意义的请求也会照单接受</li><li>查明对手的证书<br>使用 HTTP 协议无法确定通信方,使用 SSL 则可以。SSL 不仅提供加密处理,而且还使用了一种被称为证书的手段,可用于确定方<br>确认通信方(服务器或客户端)持有的证书,即可判断通信方的真实意图<br><img src="/images/http/http-7-2.png" alt=""></li></ul><p>客户端持有证书即可完成个人身份的确认,也可用于对 Web 网站的认证环节</p><p>在http协议通信时,由于不存在通信方的处理步骤,任何人都可以发送请求</p><h4 id="7-1-3-无法证明报文的完整性,可能已遭篡改"><a href="#7-1-3-无法证明报文的完整性,可能已遭篡改" class="headerlink" title="7.1.3 无法证明报文的完整性,可能已遭篡改"></a>7.1.3 无法证明报文的完整性,可能已遭篡改</h4><p>所谓完整性是指信息的准确度。若无法证明其完整性,通常也就意味着无法判断信息是否准确</p><ul><li>接受到的内容可能有误<br>由于 HTTP 协议无法证明通信报文的完整性,所有没有任何办法确认,发出的请求/响应和接受到的请求/响应时前后相同的<br><img src="/images/http/http-7-3.png" alt=""></li></ul><p>请求或响应在传输途中,遭攻击者拦截并篡改内容的改变称为中间人攻击(Main-in-the-Middle-attack,MITM)<br><img src="/images/http/http-7-4.png" alt=""></p><ul><li>如何防止篡改<br>使用 https,ssl提供认证和加密处理及摘要功能</li></ul><h3 id="7-2-http-加密-认证-完整性保护"><a href="#7-2-http-加密-认证-完整性保护" class="headerlink" title="7.2 http+加密+认证+完整性保护"></a>7.2 http+加密+认证+完整性保护</h3><h4 id="7-2-1-http加上加密处理和认证以及完整性保护后即是https"><a href="#7-2-1-http加上加密处理和认证以及完整性保护后即是https" class="headerlink" title="7.2.1 http加上加密处理和认证以及完整性保护后即是https"></a>7.2.1 http加上加密处理和认证以及完整性保护后即是https</h4><p><img src="/images/http/http-7-5.png" alt=""></p><h4 id="7-2-2-https是身披ssl外壳的http"><a href="#7-2-2-https是身披ssl外壳的http" class="headerlink" title="7.2.2 https是身披ssl外壳的http"></a>7.2.2 https是身披ssl外壳的http</h4><p>HTTPS 并非是应用层的一种协议。只是 HTTP 通信接口部分采用 SSL (Secure Socket Layer)和 TSL(Transport Layer Security) 协议代替而已<br><img src="/images/http/http-7-6.png" alt=""></p><h4 id="7-2-3-相互交换密钥的公开密钥加密技术"><a href="#7-2-3-相互交换密钥的公开密钥加密技术" class="headerlink" title="7.2.3 相互交换密钥的公开密钥加密技术"></a>7.2.3 相互交换密钥的公开密钥加密技术</h4><p>SSL 采用一种叫做公开密钥加密(Public-key cryptography)的加密处理方式<br>近代的加密方法中加密算法是公开的,而密钥却是保密的。通过这种方式得以保持加密方法的安全性<br>加密和解密都会用到密钥,没有密钥就无法对密码解密</p><ul><li>共享密钥加密的困境<br>加密和解密同用一个密钥的方式称为共享密钥加密(Common key crypto system),也被叫做对称密钥加密<br><img src="/images/http/http-7-7.png" alt=""></li></ul><p>以共享密钥加密时必须将密钥也发送给对方<br><img src="/images/http/http-7-8.png" alt=""></p><ul><li><p>使用两把密钥的公开密钥加密<br>公开密钥的加密方式很好的解决了共享密钥加密的困难<br>公开密钥加密使用一对非对称的密钥。一把叫做私有密钥(private key),一把叫做公开密钥(public key)<br>使用公开密钥加密时,发送密文的一方使用对方的公开密钥进行加密处理,对方收到被加密的信息后,再使用自己的私有密钥进行解密<br><img src="/images/http/http-7-9.png" alt=""></p></li><li><p>HTTPS 采用混合加密机制<br>HTTPS 采用共享密钥加密和公开密钥加密两者并用的混合加密机制<br>在交换密钥环节使用公开密钥加密方式,之后的建立通信交换报文阶段则使用共享密钥加密方式<br><img src="/images/http/http-7-10.png" alt=""></p></li></ul><h4 id="7-2-4-证明公开密钥正确性的证书"><a href="#7-2-4-证明公开密钥正确性的证书" class="headerlink" title="7.2.4 证明公开密钥正确性的证书"></a>7.2.4 证明公开密钥正确性的证书</h4><p>公开密钥加密方式无法证明公开密钥本身就是货真价实的公开密钥<br>使用数字证书认证机构和其相关机关颁发的公开密钥证书可解决上述问题</p><ul><li>可证明组织真实性的 EV SSL 证书</li><li>证书的一个作用是用来证明作为通信一方的服务器是否规范,另外一个作用是确认对方服务器背后运营的企业是否真实存在。拥有该特性的证书是 EV SSL(Extended Validation SSL Certificate) 证书</li><li>用以确认客户端的客户端证书</li><li>HTTPS 中还可以使用客户端证书。以客户端证书进行客户端认证,证明服务器正在通信的对方始终是预料之内的客户端,其作用跟服务器证书如出一辙</li><li>客户端证书只能用来证明客户端实际存在,而不能用来证明用户本人的真实有效性</li><li>认证机构信誉第一</li><li>SSL 机制中介入认证机构之所以可行,是因为建立其信用绝对可靠这一前提下的</li><li>由自认证机构颁发的证书称为自签名证书</li><li>独立构建的认证机构叫做自认证机构,由自认证机构颁发的 无用 证书也被戏称为自签名证书<br>浏览器访问该服务器时,会显示 无法确认连接安全性 或 该网站的安全证书存在问题 等警告信息<h4 id="7-2-5-https的安全通信机制"><a href="#7-2-5-https的安全通信机制" class="headerlink" title="7.2.5 https的安全通信机制"></a>7.2.5 https的安全通信机制</h4>HTTPS 通信步骤<br><img src="/images/http/http-7-11.png" alt=""></li></ul><ol><li>客户端通过发送 Client Hello 报文开始 SSL 通信</li><li>服务器可进行 SSL通信时,会以 Server Hello 报文作为响应</li><li>之后服务器发送 Certificate 报文,报文中包含公开密钥证书</li><li>最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的 SSL 握手协商部分结束</li><li>SSL 第一次握手结束之后,客户端以 Client Key Exchange 报文作为回应</li><li>接着客户端继续发送 Client Cipher Spec 报文</li><li>客户端发送 Finished 报文,该报文包含连接至今全部报文的整体校验值</li><li>服务器同样发送 Client Cipher Spec 报文</li><li>服务器同样发送 Finished 报文</li><li>服务器和客户端的 Finished 报文交换完毕之后,SSL 连接就算建立完成</li><li>应用层协议通信,即发送 HTTP 响应</li><li>最后客户端断开连接,断开连接时,发送 close_notify 报文</li></ol><p>在以上流程中,应用层发送数据时会附加一种叫做 MAC 的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第六章总结</title>
<link href="/2019/10/24/http6/"/>
<url>/2019/10/24/http6/</url>
<content type="html"><![CDATA[<p>http协议的请求和响应报文中必定包含http首部,只是我们平时在使用web的过程中感受不到它。<br><a id="more"></a></p><h1 id="HTTP首部(第六章)"><a href="#HTTP首部(第六章)" class="headerlink" title="HTTP首部(第六章)"></a>HTTP首部(第六章)</h1><p><br></p><h3 id="6-1-Http报文首部"><a href="#6-1-Http报文首部" class="headerlink" title="6.1 Http报文首部"></a>6.1 Http报文首部</h3><p>HTTP请求报文<br>在请求中,HTTP报文由方法、URI、HTTP版本、HTTP首部字段等部分构成。<br>HTTP响应报文<br>在响应中,HTTP报文由HTTP版本、状态码、HTTP首部字段3部分构成。</p><h3 id="6-2-Http首部字段"><a href="#6-2-Http首部字段" class="headerlink" title="6.2 Http首部字段"></a>6.2 Http首部字段</h3><p>使用首部字段是为了给浏览器和服务器提供报文主体大小、所使用的语言、认证信息等内容。<br>首部字段由首部字段名和字段值构成,中间用冒号“:”分隔。<br>首部字段名 : 字段值</p><p>4种HTTP首部字段类型</p><ul><li>通用首部字段<br>请求报文和响应报文两方都会使用的首部。</li><li>请求首部字段<br>从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。</li><li>响应首部字段<br>从服务器向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。</li><li>实体首部字段<br>针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体相关的信息。<h3 id="6-3-Http-1-1-通用首部字段"><a href="#6-3-Http-1-1-通用首部字段" class="headerlink" title="6.3 Http/1.1 通用首部字段"></a>6.3 Http/1.1 通用首部字段</h3><img src="/images/http/http-6-1.png" alt=""></li></ul><h3 id="6-4-请求首部字段"><a href="#6-4-请求首部字段" class="headerlink" title="6.4 请求首部字段"></a>6.4 请求首部字段</h3><p><img src="/images/http/http-6-2.png" alt=""></p><h3 id="6-5响应首部字段"><a href="#6-5响应首部字段" class="headerlink" title="6.5响应首部字段"></a>6.5响应首部字段</h3><p><img src="/images/http/http-6-3.png" alt=""></p><h3 id="6-6-实体首部字段"><a href="#6-6-实体首部字段" class="headerlink" title="6.6 实体首部字段"></a>6.6 实体首部字段</h3><p><img src="/images/http/http-6-4.png" alt=""></p><h3 id="6-7-为Cookie服务的首部字段"><a href="#6-7-为Cookie服务的首部字段" class="headerlink" title="6.7 为Cookie服务的首部字段"></a>6.7 为Cookie服务的首部字段</h3><p><img src="/images/http/http-6-5.png" alt=""></p><h3 id="6-8-其他首部字段"><a href="#6-8-其他首部字段" class="headerlink" title="6.8 其他首部字段"></a>6.8 其他首部字段</h3><p>HTTP首部字段是可以自行扩展的。所以在Web服务器和浏览器的应用上,会出现各种非标准的首部字段。</p><ul><li>X-Frame-Options<br>属于HTTP响应首部,用于控制网站内容在其他Web网站的Frame标签内的显示问题。其主要目的是为了防止点击劫持攻击。</li><li>X-XSS-Protection<br>属于HTTP响应首部,它是针对跨站脚本攻击的一种对策,用于控制浏览器XSS防护机制的开关。<br>0将XSS过滤设置成无效状态 1将XSS过滤设置成有效状态</li><li>DNT<br>属于HTTP请求首部,其中DNT是Do Not Track的简称,意为拒绝个人信息被收集,是表示拒绝被精准广告追踪的一种方法。<br>0同意被追踪1拒绝被追踪</li><li>P3P<br>属于HTTP相应首部,通过利用P3P技术,可以让Web网站上的个人隐私变成一种仅供程序可理解的形式,以达到保护用户隐私的目的。</li></ul><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第五章总结</title>
<link href="/2019/09/17/http5/"/>
<url>/2019/09/17/http5/</url>
<content type="html"><![CDATA[<p>一台 web服务器可搭建多个独立域名的web网站,也可作为通信路径上的中转服务器提升传输效率。<br><a id="more"></a></p><h1 id="与HTTP协作的-web服务器(第五章)"><a href="#与HTTP协作的-web服务器(第五章)" class="headerlink" title="与HTTP协作的 web服务器(第五章)"></a>与HTTP协作的 web服务器(第五章)</h1><p><br></p><h3 id="5-1-用单台虚拟主机实现多个域名"><a href="#5-1-用单台虚拟主机实现多个域名" class="headerlink" title="5.1 用单台虚拟主机实现多个域名"></a>5.1 用单台虚拟主机实现多个域名</h3><p>一台服务器可以托管多个域名。<br>在相同的IP地址下,虚拟主机可以寄存多个不同主机名和域名的网站,所以在发送HTTP请求时,必须在Host首部内指定完整的主机名和域名的URI。</p><h3 id="5-2-通信数据转发程序:代理、网关、隧道"><a href="#5-2-通信数据转发程序:代理、网关、隧道" class="headerlink" title="5.2 通信数据转发程序:代理、网关、隧道"></a>5.2 通信数据转发程序:代理、网关、隧道</h3><h4 id="5-2-1代理"><a href="#5-2-1代理" class="headerlink" title="5.2.1代理"></a>5.2.1代理</h4><p><img src="/images/http/http-5-1.png" alt=""><br>代理服务器的基本行为就是接受客户端的请求后转发给其他服务器,不会改变请求URI。</p><p>使用代理服务器的理由:利用缓存技术减少带宽的流量、组织内部针对特定网站的访问控制、以获取访问日志为主要目的等。<br>缓存代理:代理在转发响应资源时,会将响应资源副本保存在代理服务器上。当代理再次收到对相同资源的请求时,可以不从源服务器那里获取资源,而是将之前缓存的资源作为响应返回。<br>透明代理:转发请求或响应时,不会对报文进行处理和加工的代理类型被称为透明代理。反之,对报文进行修改的代理称为非透明代理。</p><h4 id="5-2-2网关"><a href="#5-2-2网关" class="headerlink" title="5.2.2网关"></a>5.2.2网关</h4><p>利用网关可以将HTTP请求转化为其他协议通信。<br>利用网关可以提高通信的安全性,因为可以在客户端和网关之间的通信上加密以确保连接的安全。</p><h4 id="5-2-3隧道"><a href="#5-2-3隧道" class="headerlink" title="5.2.3隧道"></a>5.2.3隧道</h4><p>隧道可按要求建立一条与其他服务器的通信,届时使用SSL等加密手段进行通信。隧道本身不会对HTTP进行解析。<br><img src="/images/http/http-5-2.png" alt=""></p><h3 id="5-3-保存资源的缓存"><a href="#5-3-保存资源的缓存" class="headerlink" title="5.3 保存资源的缓存"></a>5.3 保存资源的缓存</h3><p>缓存是指代理服务器或者客户端本地磁盘内保存的资源副本<br>利用缓存机制就可以减少对源服务器的访问,因此节省了通信流量和通信时间<br>缓存服务器是代理服务器的一种,并归类在缓存代理类型中,所以说当代理转发从服务器返回的响应的时候,代理服务器将会保存一份副本</p><p>转发响应后,复制资源后,保存在缓存服务器上<br>请求的资源如果已经被缓存则直接缓存服务器放回给客户端<br>缓存服务器会先向源服务器确认缓存资源的有效性<br>缓存服务器的优势就是在与利用缓存可以避免从源服务器上面转发资源,不用多次请求。</p><h4 id="5-3-1缓存的有效期限"><a href="#5-3-1缓存的有效期限" class="headerlink" title="5.3.1缓存的有效期限"></a>5.3.1缓存的有效期限</h4><p>即使是缓存服务器内有缓存,也不能保证每次都会被返回对资源的请求
当源服务器遇到资源更新了的时候,如果还是用之前的缓存就返回的是旧资源
所以当存在缓存的时候,先会缓存服务器请求源服务器看下资源的有效没,如果失效了,就重新从源服务器上获取资源</p><h4 id="5-3-2客户端的缓存"><a href="#5-3-2客户端的缓存" class="headerlink" title="5.3.2客户端的缓存"></a>5.3.2客户端的缓存</h4><p>缓存还可以缓存带客户端的浏览器上,把客户端的缓存当作临时的网络文件
浏览器缓存如果有效的话,直接本地读取
当缓存过期的时候,会向源服务器确认资源的有效性</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第四章总结</title>
<link href="/2019/07/09/http4/"/>
<url>/2019/07/09/http4/</url>
<content type="html"><![CDATA[<p>http状态码负责标示客户端http请求的返回结果,标记服务器端的处理是否正常,通知出现的错误等工作。<br><a id="more"></a></p><h1 id="返回结果的http状态码(第四章)"><a href="#返回结果的http状态码(第四章)" class="headerlink" title="返回结果的http状态码(第四章)"></a>返回结果的http状态码(第四章)</h1><p><br></p><h3 id="状态码告知从服务器端返回的请求结果"><a href="#状态码告知从服务器端返回的请求结果" class="headerlink" title="状态码告知从服务器端返回的请求结果"></a>状态码告知从服务器端返回的请求结果</h3><p>状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。<br>状态码类别如下:</p><p><img src="/images/http/http-4-1.png" alt=""></p><h3 id="2xx成功"><a href="#2xx成功" class="headerlink" title="2xx成功"></a>2xx成功</h3><p>200 OK 从客户端发来的请求在服务器端被正常处理了<br>204 No Content 请求处理成功,但没有资源可返回<br>206 Partial Content 表示客户端进行了范围请求,服务器成功执行了这部分GET请求,响应报文中包括由Content-Range指定范围的实体内容</p><h3 id="3xx-重定向"><a href="#3xx-重定向" class="headerlink" title="3xx 重定向"></a>3xx 重定向</h3><p>浏览器需要执行某些特殊的处理以正确处理请求</p><ul><li>301 Moved Permanently 永久性重定向 表示请求的资源已被分配了新的URI 需要进行书签引用的变更</li><li>302 Found 临时性重定向 表示请求的资源已被分配到新的URI,希望用户本次能使用新的URI</li><li>303 See Other 表示由于请求对应的资源存在着另一个URI,应使用GET方法定向获取请求的资源</li><li>304 Not Modified 表示客户端发送附带条件的请求时,服务器端允许访问资源,但因发生请求未满足条件的情况后,直接返回304….(和重定向无关)</li><li>307 Temporary Redirect 临时重定向 与302同,但不会从POST变为GET</li></ul><h3 id="4xx客户端错误"><a href="#4xx客户端错误" class="headerlink" title="4xx客户端错误"></a>4xx客户端错误</h3><ul><li>400 Bad Request 请求报文中存在语法错误</li><li>401 Unauthorized 表示发送的请求需要有通过HTTP认证(BASIC、 DIGEST认证)的认证信息 若之前已进行一次请求,则表示认证失败</li><li>403 Forbidden 表明对请求资源的访问被服务器拒绝了</li><li>404 Not Found 服务器上无法找到请求的资源 或者拒绝不想给理由</li></ul><h3 id="5xx服务器错误"><a href="#5xx服务器错误" class="headerlink" title="5xx服务器错误"></a>5xx服务器错误</h3><ul><li>500 Internal Server Error 服务器端在执行请求时发生了错误 也可能是Web应用存在的bug或某些临时故障</li><li>503 Service Unavailable 表明服务器暂时处于超负载或者正在停机维护,现在无法请求处理</li></ul><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第三章总结</title>
<link href="/2019/05/19/http3/"/>
<url>/2019/05/19/http3/</url>
<content type="html"><![CDATA[<p>http通信过程包括从客户端发往服务器端的请求及从服务器端返回客户端的响应。<br><a id="more"></a></p><h1 id="http报文内的http信息(第三章)"><a href="#http报文内的http信息(第三章)" class="headerlink" title="http报文内的http信息(第三章)"></a>http报文内的http信息(第三章)</h1><p><br></p><h3 id="http报文"><a href="#http报文" class="headerlink" title="http报文"></a>http报文</h3><p>Http报文主要分为请求报文和响应报文两种类型<br>从内容上来说,Http报文包含了报文首部和报文主体<br>结构如下:</p><p><img src="/images/http/http-3-1.png" alt=""></p><h3 id="请求报文及响应报文结构"><a href="#请求报文及响应报文结构" class="headerlink" title="请求报文及响应报文结构"></a>请求报文及响应报文结构</h3><p>请求报文和响应报文的结构:<br><img src="/images/http/http-3-2.png" alt=""></p><p>首部字段:包含各种请求响应的条件等等 :主要包含四种类型:通用首部,请求首部,响应首部,实体首部<br>内容编码:压缩传输,类似于邮件添加zip附件形式</p><h3 id="编码提升传输速率"><a href="#编码提升传输速率" class="headerlink" title="编码提升传输速率"></a>编码提升传输速率</h3><h4 id="报文主体和实体主体的差异"><a href="#报文主体和实体主体的差异" class="headerlink" title="报文主体和实体主体的差异"></a>报文主体和实体主体的差异</h4><p>通常报文主体等于实体主体,只有当传输中进行编码操作时,才有差别。</p><h4 id="压缩传输的内容编码"><a href="#压缩传输的内容编码" class="headerlink" title="压缩传输的内容编码"></a>压缩传输的内容编码</h4><p>内容编码:压缩传输,类似于邮件添加zip附件形式<br>内容编码常用形式:gzip / compress / deflate / identity</p><h4 id="分割发送的分块传输编码"><a href="#分割发送的分块传输编码" class="headerlink" title="分割发送的分块传输编码"></a>分割发送的分块传输编码</h4><p>将实体主体分块的功能称为分块传输编码。</p><h3 id="发送多种数据的多部分对象集合"><a href="#发送多种数据的多部分对象集合" class="headerlink" title="发送多种数据的多部分对象集合"></a>发送多种数据的多部分对象集合</h3><p>邮件包括文字以及各种附件,采用了MIME(多用途英特网邮件扩展)机制<br>HTTP也采纳了 多部分对象集合(Multipart)<br>包含的对象如下:<br>multipart/form-data:在Web表单文件上传时使用<br>multipart/byteranges:状态码206响应报文包含了多个范围的内容时使用<br>在HTTP报文中使用多部分对象集合时,需要在首部字段里加上 Content-type<br>使用boundary字符串来划分多部分对象集合指明的各类实体。在boundary字符串指定的各个实体的起始行之前插入“–”,而在多部分对象集合对应的字符串最后插入“–”标记做为结束。</p><h3 id="获取部分内容的范围请求"><a href="#获取部分内容的范围请求" class="headerlink" title="获取部分内容的范围请求"></a>获取部分内容的范围请求</h3><p>范围请求:指定范围发送的请求</p><h3 id="内容协商返回最合适的内容"><a href="#内容协商返回最合适的内容" class="headerlink" title="内容协商返回最合适的内容"></a>内容协商返回最合适的内容</h3><p>内容协商机制:指客户端和服务器就响应内容进行交涉,然后提供给客户端最为合适的资源。以语言,字符集,编码方式等为基准判断响应的资源<br>包含在请求报文中的某些首部字段就是判断标准:</p><ul><li>Accept</li><li>Accept-Charset</li><li>Accept-Encoding</li><li>Accept-Language</li><li>Content-Language</li></ul><p>内容协商技术有以下三种类型</p><ul><li>服务器驱动协商:由服务器端进行内容协商,以请求首部字段为参考,在服务器端自动处理</li><li>客户端驱动协商:有客户端进行内容协商的方式,用户从浏览器现实的可选项目组手动选择</li><li>透明协商:以上结合,是由服务器和客户端各自进行内容协商的一种方法</li></ul><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第二章总结</title>
<link href="/2019/05/14/http2/"/>
<url>/2019/05/14/http2/</url>
<content type="html"><![CDATA[<p>http协议的基础总结。<br><a id="more"></a></p><h1 id="简单的http协议(第二章)"><a href="#简单的http协议(第二章)" class="headerlink" title="简单的http协议(第二章)"></a>简单的http协议(第二章)</h1><p><br></p><h3 id="http-协议用于客户端和服务端的交互"><a href="#http-协议用于客户端和服务端的交互" class="headerlink" title="http 协议用于客户端和服务端的交互"></a>http 协议用于客户端和服务端的交互</h3><p>http协议用于客户端和服务器之间的通信。</p><p>请求访问文本或图像等资源的一端称为客户端,提供资源响应的一端称为服务器端。</p><h3 id="通过请求和响应的交换达成通信"><a href="#通过请求和响应的交换达成通信" class="headerlink" title="通过请求和响应的交换达成通信"></a>通过请求和响应的交换达成通信</h3><p>请求报文是有请求方法、请求uri、协议版本、可选的请求首部字段和内容实体构成的。<br><img src="/images/http/http-2-1.png" alt=""></p><p>响应报文基本上由协议版本、状态码、用以解释状态码的短语、可选的响应式首部字段以及实体主体构成。</p><p><img src="/images/http/http-2-2.png" alt=""></p><h3 id="http是不保存状态的协议"><a href="#http是不保存状态的协议" class="headerlink" title="http是不保存状态的协议"></a>http是不保存状态的协议</h3><p>HTTP 是不保存状态的协议(即无状态协议),协议本身不保留之前的请求或响应报文的信息,为了更快的处理大量事务,确保协议的可伸缩性。后为了实现保持状态功能引入了cookie技术。</p><h3 id="请求uri定位资源"><a href="#请求uri定位资源" class="headerlink" title="请求uri定位资源"></a>请求uri定位资源</h3><p>http协议使用uri定位互联网上的资源。</p><h3 id="告知服务器意图的http方法"><a href="#告知服务器意图的http方法" class="headerlink" title="告知服务器意图的http方法"></a>告知服务器意图的http方法</h3><p>GET 方法用来请求访问已被 URI 识别的资源<br>POST:传输实体主体<br>虽然用 GET 方法也可以传输实体的主体,但一般不用 GET 方法进行传输,而是用 POST 方法。虽说 POST 的功能与 GET 很相似,但POST 的主要目的并不是获取响应的主体内容<br>PUT:传输文件<br>像 FTP 协议的文件上传一样,要求在请求报文的主体中包含文件内容,然后保存到请求 URI 指定的位置,但是,鉴于 HTTP/1.1 的 PUT 方法自身不带验证机制,任何人都可以上传文件 , 存在安全性问题,因此一般的 Web 网站不使用该方法<br>HEAD:获得报文首部</p><p>HEAD 方法和 GET 方法一样,只是不返回报文主体部分。用于确认URI 的有效性及资源更新的日期时间等。<br>DELETE:删除文件<br>DELETE 方法用来删除文件,是与 PUT 相反的方法。DELETE 方法按请求 URI 删除指定的资源。HTTP/1.1 的 DELETE 方法本身和 PUT 方法一样不带验证机制,所以一般的 Web 网站也不使用 DELETE 方法<br>OPTIONS:询问支持的方法<br>OPTIONS 方法用来查询针对请求 URI 指定的资源支持的方法。<br>CONNECT:要求用隧道协议连接代理<br>CONNECT 方法要求在与代理服务器通信时建立隧道,实现用隧道协议进行 TCP 通信。主要使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。</p><h3 id="使用方法下达命令"><a href="#使用方法下达命令" class="headerlink" title="使用方法下达命令"></a>使用方法下达命令</h3><p><img src="/images/http/http-2-3.png" alt=""></p><h3 id="持久连接节省通信量"><a href="#持久连接节省通信量" class="headerlink" title="持久连接节省通信量"></a>持久连接节省通信量</h3><p>HTTP 协议的初始版本中(HTTP0.9和HTTP1.0),每进行一次 HTTP 通信就要断开一次 TCP连接。<br><img src="/images/http/http-2-4.png" alt=""></p><p>为解决上述 TCP 连接的问题,HTTP/1.1 想出了持久连接(HTTP Persistent Connections,也称为 HTTP keep-alive 或HTTP connection reuse)的方法。<br>持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。在 HTTP/1.1 中,所有的连接默认都是持久连接<br>持久连接的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载,Web 页面的显示速度也就相应提高了<br><img src="/images/http/http-2-5.png" alt=""></p><h4 id="管线化"><a href="#管线化" class="headerlink" title="管线化"></a>管线化</h4><p>持久连接使得多数请求以管线化(pipelining)方式发送成为可能。从前发送请求后需等待并收到响应,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求。</p><p><img src="/images/http/http-2-6.png" alt=""></p><h3 id="使用cookie的状态管理"><a href="#使用cookie的状态管理" class="headerlink" title="使用cookie的状态管理"></a>使用cookie的状态管理</h3><p>cookie技术通过在请求和响应报文中写入cookie 信息来控制客户端状态。</p><p><img src="/images/http/http-2-7.png" alt=""><br><img src="/images/http/http-2-8.png" alt=""></p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>图解HTTP 第一章总结</title>
<link href="/2019/03/27/http1/"/>
<url>/2019/03/27/http1/</url>
<content type="html"><![CDATA[<p>全章概述了web是建立在何种技术之上,以及http协议是如何诞生并发展的。<br><a id="more"></a></p><h1 id="了解web-及网络基础(第一章)"><a href="#了解web-及网络基础(第一章)" class="headerlink" title="了解web 及网络基础(第一章)"></a>了解web 及网络基础(第一章)</h1><p><br><br>核心内容 简单介绍http诞生以及关系密切的协议和基本概念</p><h3 id="使用http协议访问web"><a href="#使用http协议访问web" class="headerlink" title="使用http协议访问web"></a>使用http协议访问web</h3><p>web使用一种名为http(HyperText Transfer Protocol)-超文本传输协议,来实现客户端与服务器之间的信息传输。</p><h3 id="http的诞生"><a href="#http的诞生" class="headerlink" title="http的诞生"></a>http的诞生</h3><p>诞生背景:互联网黎明期,致力于全世界研究者知识共享。</p><h3 id="网络基础-tcp-ip"><a href="#网络基础-tcp-ip" class="headerlink" title="网络基础 tcp/ip"></a>网络基础 tcp/ip</h3><p>tcp/ip协议族-与互联网相关联的协议集合的总称,http属于其中的一个子集。<br>协议: 计算机网络设备互相通信需要基于相同的方法,包括如何发起、通信语言、结束通信等相关规则即可称为协议。<br>Tcp/ip的分层管理: 可分为4层,应用层、传输层、网络层、数据链路层。<br>层化好处:各层之间接口部分规划好后,方便替换变动的层。</p><p><img src="/images/http/http-1-1.png" alt=""></p><p><strong>tcp/ip 通信传输流</strong></p><p><img src="/images/http/http-1-2.png" alt=""></p><p>利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则往应用层往上走。<br>我们用 HTTP 举例来说明,首先作为发送端的客户端在应用层 (HTTP 协议)发出一个想看某个 Web 页面的 HTTP 请求。<br>接着,为了传输方便,在传输层(TCP 协议)把从应用层处收到的数 据(HTTP 请求报文)进行分割,并在各个报文上打上标记序号及端 口号后转发给网络层。<br>在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链 路层。这样一来,发往网络的通信请求就准备齐全了。<br>接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用 层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP 请求。</p><p><img src="/images/http/http-1-3.png" alt=""></p><p>发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该 层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层 时会把对应的首部消去。<br>这种把数据信息包装起来的做法称为封装(encapsulate)。</p><p><img src="/images/http/http-1-4.png" alt=""></p><p>当应用程序用TCP传送数据时,数据被送入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息),该过程如图所示。<br>TCP传给IP的数据单元称作TCP报文段或简称为TCP段(TCP segment);UDP数据与TCP数据基本一致。唯一的不同是UDP传给IP的信息单元称作U D P数据报(UDP datagram),而且UDP的首部长为8字节。IP传给网络接口层的数据单元称作IP数据报(IP datagram)。通过以太网传输的比特流称作帧(Frame )。 </p><h3 id="与http相关的协议:-ip、tcp、dns"><a href="#与http相关的协议:-ip、tcp、dns" class="headerlink" title="与http相关的协议: ip、tcp、dns"></a>与http相关的协议: ip、tcp、dns</h3><p>IP(Internet Protocol)网际协议位于网络层。IP 协议的作用是把各种数据包传送给对方。而要保证确实传送到对方 那里,则需要满足各类条件。其中两个重要的条件是 IP 地址和 MAC 地址(Media Access Control Address)。<br>IP 地址指明了节点被分配到的地址,MAC 地址是指网卡所属的固定 地址。IP 地址可以和 MAC 地址进行配对。IP 地址可变换,但 MAC 地址基本上不会更改。<br>使用 ARP 协议凭借 MAC 地址进行通信:<br>IP 间的通信依赖 MAC 地址。在网络上,通信的双方在同一局域网 (LAN)内的情况是很少的,通常是经过多台计算机和网络设备中转 才能连接到对方。而在进行中转时,会利用下一站中转设备的 MAC 地址来搜索下一个中转目标。这时,会采用 ARP 协议(Address Resolution Protocol)。ARP 是一种用以解析地址的协议,根据通信方 的 IP 地址就可以反查出对应的 MAC 地址。</p><p><img src="/images/http/http-1-5.png" alt=""></p><p>TCP协议位于传输层提供可靠的字节流服务。<br>字节流服务:大块数据分割成报文段为单位的数据包管。<br>为确保数据准确送达,TCP协议采用三次握手策略。发送端首先发送一个带有syn标志的数据包给对方,接收端收到后,发送一个带有syn/ack标志的数据包来表示确认。最后发送端再回传一个带有ack标志的数据包,代表三次握手的结束。若在握手过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包。</p><p><img src="/images/http/http-1-6.png" alt=""></p><h3 id="负责域名解析的dns服务"><a href="#负责域名解析的dns服务" class="headerlink" title="负责域名解析的dns服务"></a>负责域名解析的dns服务</h3><p>DNS协议提供通过域名查找IP地址,或逆向从IP地址反查域名的服务。</p><h3 id="各种协议与http协议关系"><a href="#各种协议与http协议关系" class="headerlink" title="各种协议与http协议关系"></a>各种协议与http协议关系</h3><p><img src="/images/http/http-1-7.png" alt=""></p><h3 id="URI和-URL"><a href="#URI和-URL" class="headerlink" title="URI和 URL"></a>URI和 URL</h3><p>URI 是统一资源标识符,而 URL 是统一资源定位符(互联网上所处位置)。因此,笼统地说,每个 URL 都是 URI,但不一定每个 URI 都是 URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。</p><p><img src="/images/http/http-1-8.png" alt=""></p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
</tags>
</entry>
<entry>
<title>选择排序</title>
<link href="/2017/05/24/sort/"/>
<url>/2017/05/24/sort/</url>
<content type="html"><![CDATA[<p>排名是我们经常遇到的问题,小的时候成绩排名,身高排名,各种排名。听歌曲时有各种各样的排行榜,那么如果让你做一个排行榜,你要怎样把杂乱无章的数据,变成人们能够准确判断的排行榜呢?那么你就需要用到排序算法了,排序算法有很多,选择排序、快速排序、冒泡排序等,此文章介绍的是简单易懂的选择排序法。选择排序是一种灵巧的排序方法,但是速度并不是很快,它的时间复杂度为O(n 2)<br><a id="more"></a></p><ol><li>选择排序说明</li></ol><p>选择排序的主要思想是:</p><ol><li>声明一个新的数组作为排序好的数组的容器。</li><li>每次对现有数组进行最大值或最小值查找(根据需要),将查找到的值顺序添加到新数组中,并将其从原数组中剔除。</li><li><p>重复第二步骤直到原数组的长度为一,即可停止,最后得到的新数组则是排序好的数组。</p></li><li><p>举例说明</p></li></ol><p>1)音乐播放器都会有很多统一或自己的排行榜,他就需要根据音乐的播放量或者唱片销量进行排序,然后对应显示。</p><ol start="3"><li>代码说明</li></ol><p>下面我们先写一个用于查找最小值的方法:<br>function findSmallest(arr){<br>var smallest = arr[0];<br>var smallest_index = 0;<br>for(var i=0;i arr[i]){<br>smallest = arr[i];<br>smallest_index=i;<br>}<br>}<br>return smallest_index;<br>}<br>利用findSmallest方法实现选择排序方法:<br>var newArr = [];<br>function selectionSort(arr){<br>if(arr.length >0){<br>smallest = findSmallest(arr);<br>newArr.push(arr[smallest]);<br>arr.splice(smallest,1);<br>selectionSort(arr);<br>}<br>return newArr;<br>}<br>var arr = [3,5,7,9,22,4,66,2,77];<br>console.log(selectionSort(arr));</p><ol start="4"><li>结论</li></ol><p>选择排序的方法是非常容易理解的,在数据量不大的情况下,可以使用,如果对效率有着严格要求的话,建议使用时间复杂度更低的算法。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> Algorithm </category>
</categories>
<tags>
<tag> js </tag>
<tag> Algorithm </tag>
</tags>
</entry>
<entry>
<title>移动端touch事件获取clientX, clientY</title>
<link href="/2017/04/27/touch/"/>
<url>/2017/04/27/touch/</url>
<content type="html"><![CDATA[<p>目有个交互需要实现手指滑动的交互,pc端使用mousedown,mousemove,mouseup监听实现。<br><a id="more"></a><br>但在iOS设备上mousemove是不好监听的,同类的方法是touchstart,touchmove,touchend。<br>如何获取手指滑动时的坐标位置呢?<br>使用event.clientX是不起作用的,要使用event.changedTouches[0].clientX,<br>如果是jQuery的event对象,使用event.originalEvent.changedTouches[0].clientX。</p><p>FYI~</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
</tags>
</entry>
<entry>
<title>Express使用html模板</title>
<link href="/2017/04/21/express/"/>
<url>/2017/04/21/express/</url>
<content type="html"><![CDATA[<p>express默认使用jade模板,如果你需要html或者ejs的时候,就必须要手动配置了。<br><a id="more"></a></p><ol><li>安装ejs</li></ol><p>使用npm install 命令在项目根目录安装ejs.如果你的网速过慢也可以使用cnpm哦,会快很多。<br>npm install ejs</p><ol><li><p>app.js中引入ejs<br>var ejs = require(‘ejs’);</p></li><li><p>设置html引擎<br>app.engine(‘html’, ejs.__express);</p></li><li><p>设置视图引擎<br>app.set(‘view engine’, ‘html’);</p></li></ol><p>重启服务就可以使用html模板咯~,在express搭建的服务器中,html引擎没有被配置,直接添加即可;视图引擎已配置,修改配置即可。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
<tag> ejs </tag>
</tags>
</entry>
<entry>
<title>hexo deploy 出现错误</title>
<link href="/2017/04/18/hexo-error/"/>
<url>/2017/04/18/hexo-error/</url>
<content type="html"><![CDATA[<pre><code>hexo 小问题解决方法。<!-- more --></code></pre><h2 id="错误如下:"><a href="#错误如下:" class="headerlink" title="错误如下:"></a>错误如下:</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">fatal: AggregateException encountered.</span><br><span class="line">bash: /dev/tty: No such device or address</span><br><span class="line">error: failed to execute prompt script (exit code 1)</span><br><span class="line">fatal: could not read Username for ‘https://github.com‘: Invalid argument</span><br><span class="line">FATAL Something’s wrong. Maybe you can find the solution here: http://hexo.io/docs/troubleshooting.html</span><br><span class="line">Error: fatal: AggregateException encountered.</span><br><span class="line">bash: /dev/tty: No such device or address</span><br><span class="line">error: failed to execute prompt script (exit code 1)</span><br><span class="line">fatal: could not read Username for ‘https://github.com‘: Invalid argument</span><br><span class="line">at ChildProcess. (F:\workSpace\astudentt.github.io\node_modules.0.6.0@hexo-util\lib\spawn.js:37:17)</span><br><span class="line">at emitTwo (events.js:106:13)</span><br><span class="line">at ChildProcess.emit (events.js:191:7)</span><br><span class="line">at ChildProcess.cp.emit (F:\workSpace\astudentt.github.io\node_modules.4.0.2@cross-spawn\lib\enoent.js:40:29)</span><br><span class="line">at maybeClose (internal/child_process.js:877:16)</span><br><span class="line">at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)</span><br><span class="line">FATAL fatal: AggregateException encountered.</span><br><span class="line">bash: /dev/tty: No such device or address</span><br><span class="line">error: failed to execute prompt script (exit code 1)</span><br><span class="line">fatal: could not read Username for ‘https://github.com‘: Invalid argument</span><br><span class="line">Error: fatal: AggregateException encountered.</span><br><span class="line">bash: /dev/tty: No such device or address</span><br><span class="line">error: failed to execute prompt script (exit code 1)</span><br><span class="line">fatal: could not read Username for ‘https://github.com‘: Invalid argument</span><br><span class="line">at ChildProcess. (F:\workSpace\astudentt.github.io\node_modules.0.6.0@hexo-util\lib\spawn.js:37:17)</span><br><span class="line">at emitTwo (events.js:106:13)</span><br><span class="line">at ChildProcess.emit (events.js:191:7)</span><br><span class="line">at ChildProcess.cp.emit (F:\workSpace\astudentt.github.io\node_modules.4.0.2@cross-spawn\lib\enoent.js:40:29)</span><br><span class="line">at maybeClose (internal/child_process.js:877:16)</span><br><span class="line">at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)</span><br></pre></td></tr></table></figure><h2 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</h2><p>将https 改成 ssh即可。<br>现在我的 config.yml 如下所示:</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">deploy:</span><br><span class="line">type: git</span><br><span class="line">repo: ssh://[email protected]/astudentt/astudentt.github.io</span><br><span class="line">branch: master</span><br></pre></td></tr></table></figure><p>最后执行hexo deploy命令即可。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> hexo </category>
</categories>
<tags>
<tag> hexo </tag>
</tags>
</entry>
<entry>
<title>GET和POST请求的区别</title>
<link href="/2017/03/22/get_post/"/>
<url>/2017/03/22/get_post/</url>
<content type="html"><![CDATA[<p>开发过程中,GET和POST方法我们会经常使用到,那么它们到底有什么不同呢?</p><a id="more"></a><ol><li>GET在浏览回退时是无害的,而post会再次提交请求。</li><li>GET产生的URL地址可以被收藏,POST不可以。</li><li>GET请求会被浏览器主动缓存,而POST不会。</li><li>GET请求只能进行URL编码,而POST支持多种编码方式</li><li>GET请求参数会被完整保存在浏览器历史记录里,POST参数不会被保留。</li><li>GET的URL会有长度上的限制,而POST的数据几乎无限制。</li><li>GET比POST更不安全,因为参数直接暴露在url上,所以不能暴露敏感信息。</li><li>GET参数通过URL传递,POST放在REquest body中。</li></ol><hr><p>cr.tanym</p>]]></content>
<categories>
<category> http </category>
</categories>
<tags>
<tag> http </tag>
<tag> get </tag>
<tag> post </tag>
</tags>
</entry>
<entry>
<title>ios默认样式去除</title>
<link href="/2017/03/20/ios-default-style/"/>
<url>/2017/03/20/ios-default-style/</url>
<content type="html"><![CDATA[<p>ios默认对页面有独特的显示样式,如按钮圆角渐变等,但是开发是我们自己写的样式可能并不能接受它默认的样式,所以去除它是很必要。<br><a id="more"></a></p><ol><li>-webkit-appearance: none;</li></ol><p>ios是webkit内核,所以在appearance前需要加-webkit来对其进行设置,<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">input[type=button]{</span><br><span class="line">-webkit-appearance:none;</span><br><span class="line">outline:none</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>上边代码段是对type为button的input控件设置appearance属性,所以ios手机上的button圆角等默认样式就消除了。</p><ol start="2"><li>ios手机会将它认为是手机号码的数字串,显示为默认的样式,并且设为拨号链接,可将telephone=no,则手机号码不被显示为拨号链接并且去除相关样式。</li></ol><hr><p>cr.tanym</p>]]></content>
<categories>
<category> ios </category>
</categories>
<tags>
<tag> ios </tag>
</tags>
</entry>
<entry>
<title>git 常用语句</title>
<link href="/2017/03/14/git-regular/"/>
<url>/2017/03/14/git-regular/</url>
<content type="html"><![CDATA[<h4 id="git官网:https-git-scm-com"><a href="#git官网:https-git-scm-com" class="headerlink" title="git官网:https://git-scm.com/"></a>git官网:<a href="https://git-scm.com/" target="_blank" rel="noopener">https://git-scm.com/</a></h4><p>git是linux开发团队开发的一个分布式版本控制系统,它与CVS及SVN这种集中式的版本控制系统不同,集中式版本控制系统的版本库是集中存放在中央服务器的,在开发过程中需要先将服务器上的最新版本拉取到本地,在本地开发完再传到中央服务器,这就会产生一些问题,比如你需要联网工作,从中央服务器拉取时会耗费很多时间,而分布式则不同,它没有中央服务器的概念,每个电脑都是一个服务器,每个人的电脑都有一个完整的版本库。所以你可以在未联网的情况下工作,同样的每个电脑都有一个完整的版本库,它的安全性也大大提高,不会像集中式的如果中央服务器产生问题,会影响到整个开发的进程。分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家可以工作,只是交换修改不方便而已。<br><a id="more"></a></p><h5 id="常用命令"><a href="#常用命令" class="headerlink" title="常用命令"></a>常用命令</h5><ol><li>git log<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">commit feebf8e6d873b6fdc557761c93e1e40ed27ab2fb</span><br><span class="line">Author: astudentt</span><br><span class="line">Date: Tue Mar 14 10:50:23 2017 +0800</span><br></pre></td></tr></table></figure></li></ol><p>git log命令显示从最近到最远的提交日志,你可以看到你的提交的版本,并且在你回退版本时起到非常重要的作用。你看到的一大串类似3628164…882e1e0的是commit id(版本号),和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,这是为了防止版本号和其他人有冲突。如果和svn一样使用1.2这样的数字,那么多人使用时,就会有冲突了。</p><ol><li><p>git reset<br><code>git reset –hard HEAD^</code><br>在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,再上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。<br><code>git reset –hard commit_id</code><br>只要你知道了commit_id的值,你就可以通过它来回退你的代码版本了,如果你已经回退到上一版本,但是发现你还是觉得之前最新的版本是你的爱的话,那么你可以使用<br>git reflog查看命令历史,以便确定要回到未来的哪个版本。</p></li><li><p>git status<br>git status是git中使用率非常高的语句,它是查看当前工作区状态的。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ git status</span><br><span class="line">On branch master</span><br><span class="line">nothing to commit, working tree clean</span><br></pre></td></tr></table></figure></li></ol><p>上面的语句告诉你当前分支的状态,没有需要提交的文件。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ git status</span><br><span class="line">On branch master</span><br><span class="line">Untracked files:</span><br><span class="line">(use “git add …” to include in what will be committed)</span><br><span class="line">a.txt</span><br><span class="line">nothing added to commit but untracked files present (use “git add” to track)</span><br></pre></td></tr></table></figure></p><p>在你新加入了文件或者没有提交到本地分支的时候,你使用git status语句时就会遇到类似情况,提示你需要使用git add语句或者commit语句来添加以及提交。</p><ol><li><p>git add<br>git中有两个概念是很重要,工作区和暂存区,工作区(Working Directory),工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库(不要轻易修改)。git add把文件添加进去,实际上就是把文件修改添加到暂存区,暂存区会将所有的文件存起来,然后我们再通过git commit 命令一次性提交暂存区的所有修改,并提交到分支。</p></li><li><p>git commit<br>提交语句,一次性提交暂存区的所有修改,并提交到分支。在你修改文件之后,直接执行git commit语句进行提交。</p></li><li><p>git push<br>git push origin master把本地库的所有内容推送到远程库上,这样你们一起工作的朋友就可以在master分支看到你提交的内容了。如果你需要推送其他分支的话只要将master分支改成你要推送的分支即可, git push origin [branchname]。</p></li><li><p>git pull<br>git push origin master拉取远程库上的master分支到本地,在开发中每次开发之前最好执行一次此语句,保证最新的版本内容,以避免产生不必要的冲突。如果你需要拉取其他分支的话只要将master分支改成你要拉取的分支即可, git pull origin [branchname]。</p></li><li><p>git clone<br>在我们看博客的时候,博主们很喜欢,让你下载他们的源码来自己试验,你可能经常看到git clone语句,在词语后加入相应的地址,就可以要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。</p></li><li><p>git branch<br>这是一条显示本地全部分支的语句,分支相当于一个时间线,在开发过程中,每个开发人员会创建自己的分支,在自己的分支上进行开发,最后再合并到master分支。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git branch</span><br><span class="line">master</span><br></pre></td></tr></table></figure></li></ol><p>git branch 语句也可以用来创建分支。删除分支可以使用 git branch -d</p><ol><li><p>git checkout<br>git checkout 可以用来对不同的分支切换,git checkout master就是切换回master分支,checkout在合并分支中被频繁使用。</p></li><li><p>git merge<br>git merge命令用于合并指定分支到当前分支。因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。<br>这些就是一些常用的git语句,掌握好这些命令,就可以熟练运用git了。如果你对命令不太熟悉,你也可以安装图形化工具来管理哦。</p></li></ol><hr><p>cr.tanym</p>]]></content>
<categories>
<category> git </category>
</categories>
<tags>
<tag> git </tag>
</tags>
</entry>
<entry>
<title>jQuery 事件委托总结</title>
<link href="/2017/03/07/jquery-event-delegation/"/>
<url>/2017/03/07/jquery-event-delegation/</url>
<content type="html"><![CDATA[<p>jquery 提供了四种事件监听方式,分别是 bind、live、delegate、on,对应的解除监听的函数分别是 unbind、die、undelegate、off。下面简单介绍下四种方法:<br><a id="more"></a></p><h2 id="1-bind-type-data-fn"><a href="#1-bind-type-data-fn" class="headerlink" title="1. bind(type,[data],fn)"></a>1. bind(type,[data],fn)</h2><p>为每个匹配元素的特定事件绑定事件处理函数。jQuery 3.0 中已弃用此方法,请用 on()代替。<br>type:事件类型,如 click、change、mouseover 等;<br>data:传入监听函数的参数,通过 event.data 取到。可选;<br>function:监听函数,可传入 event 对象,这里的 event 是 jQuery 封装的 event 对象,与原生的 event 对象有区别,使用时需要注意<br>bind 的特点就是会把监听器绑定到目标元素上,动态添加元素时事件是不会被绑定上的,动态生成的元素可以是用 live 方法。</p><h2 id="2-live-type-data-fn"><a href="#2-live-type-data-fn" class="headerlink" title="2. live(type, [data], fn)"></a>2. live(type, [data], fn)</h2><p>jQuery 给所有匹配的元素附加一个事件处理函数,即使这个元素是以后再添加进来的也有效。源码如下:<br><code>live: function( types, data, fn ) { jQuery( this.context ).on( types, this.selector, data, fn ); return this; }</code><br>这个方法基本是.bind() 方法的一个变体。使用 .bind() 时,选择器匹配的元素会附加一个事件处理函数,而以后再添加的元素则不会有。为此需要再使用一次 .bind() 才行。比如说</p><p>Click here</p><p>可以给这个元素绑定一个简单的 click 事件:</p><p><code>$(‘.clickme’).bind(‘click’, function() {alert(“Bound handler called.”);});</code><br>当点击了元素,就会弹出一个警告框。然后,想象一下这之后有另一个元素添加进来了。<br> <code>$(‘body’).append(‘Another target‘);</code><br> 尽管这个新的元素也能够匹配选择器 “.clickme” ,但是由于这个元素是在调用 .bind() 之后添加的,所以点击这个元素不会有任何效果。<br>.live() 就提供了对应这种情况的方法。如果我们是这样绑定 click 事件的:<br><code>$(‘.clickme’).live(‘click’, function() {alert(“Live handler called.”);});</code><br> 然后再添加一个新元素:<br><code>$(‘body’).append(‘ Another target ‘);</code><br>然后再点击新增的元素,他依然能够触发事件处理函数。<br> 事件委托<br> .live() 方法能对一个还没有添加进 DOM 的元素有效,是由于使用了事件委托:绑定在祖先元素上的事件处理函数可以对在后代上触发的事件作出回应。传递给 .live() 的事件处理函数不会绑定在元素上,而是把他作为一个特殊的事件处理函数,绑定在 DOM 树的根节点上。在我们的例子中,当点击新的元素后,会依次发生下列步骤:<br>生成一个 click 事件传递给 来处理<br>由于没有事件处理函数直接绑定在 <divgt; 上,所以事件冒泡到 DOM 树上<br>事件不断冒泡一直到 DOM 树的根节点,默认情况下上面绑定了这个特殊的事件处理函数。<br>执行由 .live() 绑定的特殊的 click 事件处理函数。<br>这个事件处理函数首先检测事件对象的 target 来确定是不是需要继续。这个测试是通过检测<br><code>$(event.target).closest(‘.clickme’)</code><br>能否找到匹配的元素来实现的。<br>如果找到了匹配的元素,那么调用原始的事件处理函数。<br>由于只有在事件发生时才会在上面的第五步里做测试,因此在任何时候添加的元素都能够响应这个事件。<br>附加说明<br>.live() 虽然很有用,但由于其特殊的实现方式,所以不能简单的在任何情况下替换 .bind()。主要的不同有:<br>在 jQuery 1.4 中,.live()方法支持自定义事件,也支持所有的 JavaScript 事件。在 jQuery 1.4.1 中,甚至也支持 focus 和 blue 事件了(映射到更合适,并且可以冒泡的 focusin 和 focusout 上)。另外,在 jQuery 1.4.1 中,也能支持 hover(映射到”mouseenter mouseleave”)。然而在 jQuery 1.3.x 中,只支持支持的 JavaScript 事件和自定义事件:click, dblclick, keydown, keypress, keyup, mousedown, mousemove, mouseout, mouseover, 和 mouseup.<br>.live() 并不完全支持通过 DOM 遍历的方法找到的元素。取而代之的是,应当总是在一个选择器后面直接使用 .live() 方法,正如前面例子里提到的。<br> 当一个事件处理函数用 .live() 绑定后,要停止执行其他的事件处理函数,那么这个函数必须返回 false。 仅仅调用 .stopPropagation() 无法实现这个目的。</p><h2 id="3-delegate-selector-type-data-fn"><a href="#3-delegate-selector-type-data-fn" class="headerlink" title="3. delegate(selector,[type],[data],fn)"></a>3. delegate(selector,[type],[data],fn)</h2><p>指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。jQuery 3.0 中已弃用此方法,请用 on()代替。<br>delegate 比 live 多了一个参数 selector,用来指定触发事件的目标元素,监听器将被绑定在调用此方法的元素上。源码如下:<br><code>delegate: function( selector, types, data, fn ) {return this.on( types, selector, data, fn );}</code><br>delegate 这个方法可作为 live()方法的替代,使得每次事件绑定到特定的 DOM 元素。</p><h2 id="4-on-events-selector-data-fn"><a href="#4-on-events-selector-data-fn" class="headerlink" title="4. on(events,[selector],[data],fn)"></a>4. on(events,[selector],[data],fn)</h2><p>on()方法绑定事件处理程序到当前选定的 jQuery 对象中的元素。on()方法绑定事件处理程序到当前选定的 jQuery 对象中的元素。在 jQuery 1.7 中,.on()方法 提供绑定事件处理程序所需的所有功能。帮助从旧的 jQuery 事件方法转换。<br>现在官方推荐使用 on 方法进行绑定,也将 bind 方法在新版 jquery 中弃用了。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> js </category>
</categories>
<tags>
<tag> js </tag>
<tag> jquery </tag>
</tags>
</entry>
<entry>
<title>CSS单位 px pt em和rem 之间的区别</title>
<link href="/2017/03/06/css-px-pt/"/>
<url>/2017/03/06/css-px-pt/</url>
<content type="html"><![CDATA[<p>前端开发中CSS可以定义大小的单位有四种px,pt,em,rem,px是网页开发中最常见的单位了。不过现在如今的部分网站已经开始用rem这个单位了。那么这四个单位有什么区别呢?<br><a id="more"></a></p><h2 id="px单位"><a href="#px单位" class="headerlink" title="px单位"></a>px单位</h2><p>px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。</p><p>特点:</p><ul><li>IE无法调整那些使用px作为单位的字体大小;</li><li>国外的大部分网站能够调整的原因在于其使用了em或rem作为字体单位;</li><li>Firefox能够调整px和em,rem,但是96%以上的中国网民使用IE浏览器(或内核)。</li></ul><h2 id="EM"><a href="#EM" class="headerlink" title="EM"></a>EM</h2><p>em是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。<br>EM特点</p><ul><li>em的值并不是固定的;</li><li>em会继承父级元素的字体大小。并且对自身显示效果有影响</li></ul><p>任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em,10px=0.625em。为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就行了。</p><h2 id="REM"><a href="#REM" class="headerlink" title="REM"></a>REM</h2><p>em是CSS3新增的一个相对单位(root em,根em),使用rem为元素设定字体大小时,是相对大小,但相对的只是HTML根元素。这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。目前,除了IE8及更早版本外,所有浏览器均已支持rem。对于不支持它的浏览器,应对方法也很简单,就是多写一个绝对单位的声明。这些浏览器会忽略用rem设定的字体大小。下面就是一个例子:<br><code>p {font-size:14px; font-size:.875rem;}</code><br>注意: 你可以根据自身的需求决定你的单位属性,如果要考虑兼容性,可以使用px,或者两者同时使用。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> css </category>
</categories>
<tags>
<tag> css </tag>
</tags>
</entry>
<entry>
<title>清除浮动实现方式</title>
<link href="/2017/03/06/clearfix/"/>
<url>/2017/03/06/clearfix/</url>
<content type="html"><![CDATA[<p>为子元素设置浮动是开发过程中常出现的场景,在为子元素设置浮动的时候,会对他的父元素,以及前后元素产生一定的影响,比如:(1)背景不能显示 (2)边框不能撑开 (3)margin、padding等设置值不能正确显示。所以我们需要清除他的浮动.<br><a id="more"></a></p><p>以下是清除浮动的部分方法</p><h2 id="1-父级div定义-height"><a href="#1-父级div定义-height" class="headerlink" title="1. 父级div定义 height"></a>1. 父级div定义 height</h2><p>原理:父级div手动定义height,就解决了父级div无法自动获取到高度的问题。<br>优点:简单、容易掌握<br>缺点:不推荐使用固定高度的元素,在适配过程中会产生很多问题,只适合高度固定的布局,要给出精确的高度。所以不推荐使用</p><h2 id="2-结尾处加空div标签-clear-both"><a href="#2-结尾处加空div标签-clear-both" class="headerlink" title="2. 结尾处加空div标签 clear:both"></a>2. 结尾处加空div标签 clear:both</h2><blockquote><p>.clear{clear:both}</p></blockquote><p>原理:添加一个空div,利用css提高的clear:both清除浮动,让父级div能自动获取到高度<br>优点:简单、容易掌握、兼容性好<br>缺点:使用过程中,会添加很多空标签,影响效率,降低代码可读性</p><h2 id="3-父级div定义-伪类-after-和-zoom"><a href="#3-父级div定义-伪类-after-和-zoom" class="headerlink" title="3. 父级div定义 伪类:after 和 zoom"></a>3. 父级div定义 伪类:after 和 zoom</h2><blockquote><p>.clearfloat:after{display:block;clear:both;content:””;visibility:hidden;height:0}<br>.clearfloat{zoom:1}</p></blockquote><p>原理:IE8以上和非IE浏览器才支持:after,原理和方法2有点类似,zoom(IE转有属性)可解决ie6,ie7浮动问题<br>优点:浏览器支持好、不容易出现怪问题<br>缺点:代码多。<br>以上代码是现在大家用的比较多的清楚浮动的方法,推荐使用第三种,不仅兼容性好,而且效率高,还有些其他方法可以清楚浮动,但是与此产生的影响可能会更大,所以本篇不予推荐。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> css </category>
</categories>
<tags>
<tag> css </tag>
</tags>
</entry>
<entry>
<title>移动端1px实现</title>
<link href="/2017/03/06/phone1px/"/>
<url>/2017/03/06/phone1px/</url>
<content type="html"><![CDATA[<p>移动端开发过程中,不可避免的会遇到1px的实现问题.那么这个1px是什么问题呢?我简单的说一下,移动端兼容过程中ios系统是很重要的一部分,retina屏幕 大家也应该有所了解, 1px变粗的原因呢就是:viewport的设置和屏幕物理分辨率是按比例而不是相同的. 移动端window对象有个devicePixelRatio属性, 它表示设备物理像素和css像素的比例, 在retina屏的iphone手机上, 这个值为2或3, css里写的1px长度映射到物理像素上就有2px或3px那么长.下面我们就说一下怎样实现1px像素。现在的实现方式有很多种,我们来列举一些<br><a id="more"></a></p><h2 id="1-ios-8-0以上支持小数点设置0-5px"><a href="#1-ios-8-0以上支持小数点设置0-5px" class="headerlink" title="1. ios 8.0以上支持小数点设置0.5px"></a>1. ios 8.0以上支持小数点设置0.5px</h2><p>IOS8下已经支持带小数的px值, 可以结合media query对应devicePixelRatio有个查询值-webkit-min-device-pixel-ratio, css可以写成这样<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">.hairline { border: 1px solid #999 }</span><br><span class="line">@media screen and (-webkit-min-device-pixel-ratio: 2) {</span><br><span class="line">.hairline { border: 0.5px solid #999 }</span><br><span class="line">}</span><br><span class="line">@media screen and (-webkit-min-device-pixel-ratio: 3) {</span><br><span class="line">.hairline { border: 0.333333px solid #999 }</span><br><span class="line">}</span><br><span class="line">-webkit-min-device-pixel-ratio属性值可以判断现有设备的 值,对应的我讲相应样式设置为小数值即可满足需求,你也可以使用js判断,但是在ios7及安卓系统中0.5px会被识别为0px显示。以下代码是识别ios8+的js判断实现:</span><br><span class="line">if (/iP(hone|od|ad)/.test(navigator.userAgent)) {</span><br><span class="line">var v = (navigator.appVersion).match(/OS (\d+)(\d+)?(\d+)?/),</span><br><span class="line">version = parseInt(v[1], 10);</span><br><span class="line">if(version >= 8){</span><br><span class="line">document.documentElement.classList.add(‘hairlines’)</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="2-transform-scale-0-5"><a href="#2-transform-scale-0-5" class="headerlink" title="2. transform: scale(0.5)"></a>2. transform: scale(0.5)</h2><p>伪类+transform是比较完美的方法了。原理是把原先元素的 border 去掉,然后利用 :before 或者 :after 重做 border ,并 transform 的 scale 缩小一半,原先的元素相对定位,新做的 border 绝对定位。<br>单条border样式设置:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">.hairline{</span><br><span class="line">position: relative;</span><br><span class="line">border:none;</span><br><span class="line">}</span><br><span class="line">.hairline:after{</span><br><span class="line">content: ‘’;</span><br><span class="line">position: absolute;</span><br><span class="line">bottom: 0;</span><br><span class="line">background: #000;</span><br><span class="line">width: 100%;</span><br><span class="line">height: 1px;</span><br><span class="line">-webkit-transform: scaleY(0.5);</span><br><span class="line">transform: scaleY(0.5);</span><br><span class="line">-webkit-transform-origin: 0 0;</span><br><span class="line">transform-origin: 0 0;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>样式使用的时候,也要结合 JS 代码,判断是否 Retina 屏<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">if(window.devicePixelRatio && devicePixelRatio >= 2){</span><br><span class="line">document.documentElement.classList.add(‘hairlines’)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="3-viewport-rem"><a href="#3-viewport-rem" class="headerlink" title="3. viewport + rem"></a>3. viewport + rem</h2><p>在devicePixelRatio = 2时,输出 viewport<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">< meta name=”viewport” content=”initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no”></span><br></pre></td></tr></table></figure></p><p>在devicePixelRatio = 3时,输出 viewport<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">< meta name=”viewport” content=”initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no”></span><br></pre></td></tr></table></figure></p><p>同时通过设置对应 viewport 的 rem 基准值,就可以实现了。</p><h2 id="4-box-shadow"><a href="#4-box-shadow" class="headerlink" title="4. box-shadow"></a>4. box-shadow</h2><p>实现方式利用css 对阴影处理的方式实现0.5px的效果<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-webkit-box-shadow:0 1px 1px -1px rgba(0, 0, 0, 0.5);</span><br></pre></td></tr></table></figure></p><p>优点基本所有场景都能满足,缺点是有阴影出现。</p><hr><p>cr.tanym</p>]]></content>
<categories>
<category> css </category>
</categories>
<tags>
<tag> css </tag>
<tag> ios </tag>
</tags>
</entry>
</search>