-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
1629 lines (1445 loc) · 234 KB
/
atom.xml
File metadata and controls
1629 lines (1445 loc) · 234 KB
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
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>我很好奇</title>
<subtitle>千反田家的小院子</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://chitanda.me/"/>
<updated>2016-08-25T16:18:43.024Z</updated>
<id>http://chitanda.me/</id>
<author>
<name>Chitanda Akari</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>“深网”和“暗网”的区别及基础扫盲</title>
<link href="http://chitanda.me/2016/08/19/difference-between-deepweb-and-darkweb/"/>
<id>http://chitanda.me/2016/08/19/difference-between-deepweb-and-darkweb/</id>
<published>2016-08-19T12:00:00.000Z</published>
<updated>2016-08-25T16:18:43.024Z</updated>
<content type="html"><![CDATA[<p>这是篇没啥技术含量的文章,单纯面向非CS行业的普通大众。主要是前几天看到微博上<code>谷大白话</code>一条<a href="http://weibo.com/1788911247/E4z4xwBrK" target="_blank" rel="external">微博</a>下很多人”深网””暗网”傻傻分不清楚;加上互联网上很多阴谋论的不入流科普文导致很多人把暗网无端端神话,变成了一个普通人不可能进入的”互联网地下世界”。和几个超自然爱好者交流过后发现他们的确在这件事上的认知偏差很大。为了给净化中文互联网做一点微小的工作,我决定站出来成为<del>IDOL</del>(科普者)。希望这篇文可以让无意点进来的读者有所收获。不喜欢概念分析的可以直接跳到后面的<a href="#谣言">谣言</a>部分。<strong>当然此文只做概念分析没有具体教程</strong></p>
<p>PS:我不是深度暗网使用者,只是花了几个小时翻了下资料而已。所以本文也不会有啥特别的深度,主要就是驳斥几个比较常见的谣言。可能有些地方会有错误,欢迎勘误(不过前提是你在暗网上确实有实际体验过,没有进过任何一个网站只凭着别人的网帖就大言不惭地指点江山的就别怪我不客气了)<br><a id="more"></a></p>
<h2 id="什么是深网"><a href="#什么是深网" class="headerlink" title="什么是深网"></a>什么是深网</h2><p>根据<a href="https://zh.wikipedia.org/wiki/%E6%B7%B1%E7%BD%91" target="_blank" rel="external">维基百科相关词条</a>的解释:<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">深网(英语:Deep Web、Dark Web,又称:不可见网、隐藏网)是指互联网上那些不能被标准搜索引擎索引的非表面网络内容。</div></pre></td></tr></table></figure></p>
<p>可以看出这<strong>深网</strong>并不仅仅是指网络站点,它的范围远大于一般的网站,它包括所有不能被搜索引擎抓取到的网络内容,比如:你的QQ聊天记录,你微博私信记录,MC私服,诸如SSH、VPN等非标准80或443端口且不走标准HTTP/HTTPS协议的内容等等。因此对于普通用户来说他们每时每刻都在和深网打交道,所谓”深网深不可测”自然是个笑话。而且实际上深网这个概念对用户来说毫无意义,因为不同用户”能抓取到的内容不同”,A的聊天记录被B来说就是”深网”;你女神对你屏蔽的朋友圈对你来说也是”深网”,而对她自己来说自然就是个普通的表层网络。所以讨论”深网”的时候只能取绝对参照物——搜索引擎,<strong>深网其实是一个仅针对搜索引擎的概念,表示不能被其抓取到的私有内容</strong></p>
<h2 id="什么是暗网"><a href="#什么是暗网" class="headerlink" title="什么是暗网"></a>什么是暗网</h2><p>暗网是深网的子集,根据维基上的解释:<code>暗网(英语:Darknet或Dark Web)是指只使用非常规协议和端口以及可信节点进行连接的私有网络</code>,暗网是不能通过”常规方式”访问的——当然你用TOR浏览器就不算常规方式了。而根据wiki还有别的方式比如<code>Freenet</code>、<code>RetroShare</code>、<code>GNUnet</code>、<code>OneSwarm</code>、<code>Tribler</code>等等就不一一列举了。对普通大众来说最简单的方法还是<code>Tor浏览器</code><br>暗网的重点在于”暗”,属于网络上的黑市,这里面有很多暴力,色情,黑产等相关的东西,比如军火、假护照、信用卡、用户信息、0day等等。网络上大部分阴谋论相关的文章也都是从暗网这些阴暗点做切入点进行发散创作</p>
<h2 id="谣言"><a href="#谣言" class="headerlink" title="谣言"></a>谣言</h2><p>由于进入暗网需要的一点点技术门槛(国外是TOR国内是VPN+TOR)导致很多文章都开始搞阴谋论和超自然分析夺人眼球。这里选几个比较经典的做下解释</p>
<h3 id="暗网和深网是同一个东西"><a href="#暗网和深网是同一个东西" class="headerlink" title="暗网和深网是同一个东西"></a>暗网和深网是同一个东西</h3><p>这个是最常见的,往往标题里写着”深网”结果写着写着就成了”暗网”。比如这两篇,就是典型的误导人:<br>《<a href="http://www.vice.cn/read/a-brief-guide-to-deep-web" target="_blank" rel="external">一篇关于 DEEP WEB 的简易指南</a>》、《<a href="http://www.admin5.com/article/20151004/625784.shtml" target="_blank" rel="external">暗网,一个比你想象中恐怖100倍的互联网世界</a>》。<br>前面也说过,暗网是深网的子集,但深网里的绝大多数网站都是普通用户可以直接接触到的内容;和暗网这种必须借助第三方工具才能访问的不一样。</p>
<h3 id="暗网的内容占了互联网全部内容的96"><a href="#暗网的内容占了互联网全部内容的96" class="headerlink" title="暗网的内容占了互联网全部内容的96%"></a>暗网的内容占了互联网全部内容的96%</h3><p>这个是上面那个谣言的变种。其实也是”深网””暗网”弄混了而已。这句话原话出自<a href="http://www.slate.com/articles/technology/bitwise/2014/02/house_of_cards_season_2_what_s_up_with_all_the_deep_web_stuff.html" target="_blank" rel="external">纸牌屋</a>:”Deep Web is 96 percent of the Internet, with us plebes only seeing a mere 4 percent.”,可见原文说的是”深网的内容占了互联网内容的4%”而不是”暗网”。<br>事实上这个谣言本身也是相当好反驳的:</p>
<ol>
<li>因为暗网本身的用户量就是相当少,可能只占网民的x万分之一,这种比例下他们的内容产出不可能超越作为大多数的普通网民所构建的普通网络</li>
<li>Apple、Google、Facebook、Amazon、腾讯、阿里巴巴、百度等公司每年在硬件和带宽上的成本至少加起来上百亿人民币,如果暗网本身内容是表层网络的几十倍的话,那他们的成本就更可怕了。然而全部暗网的流水加起来估计都覆盖不了这里的零头。而如果是深网的话这句话是没有多少问题的,这里先不论4%这个数字是否准确(因为按照有些人的计算google收录的不只4%,然而这点不好证伪,所以姑且认为是4%吧)。因为互联网大部分用户数据对搜索引擎而言都是不公开的。</li>
</ol>
<h3 id="暗网是非公开的,一般人很难进去"><a href="#暗网是非公开的,一般人很难进去" class="headerlink" title="暗网是非公开的,一般人很难进去"></a>暗网是非公开的,一般人很难进去</h3><p>这个其实是很难证伪的论点,因为有个”没有真正的苏格兰人”的诡辩点在:你举出的例子对方都可以用”这不是真正的暗网”来死缠烂打,所以具体不深入。<br>单纯说下”非公开”这点:这是个认知错误。其实暗网依旧是公开站点,它只是与普通的公网相隔绝而已。真正的非公开站点应该是那些纯局域网内的站点。而”普通人很难接触这点”,由于通过TOR浏览器就可以直接访问了,因此也是故意夸大难度好渲染阴谋论而已。网上很多帖子只说自己看到的各种光怪陆离的东西而从来不给链接可能也就是因为给了后大概立马就要被打脸了。<br>事实上访问<strong>暗网真正的难点其实在于获取URL</strong>,因为很多网站都是过几天就换一个域名。对于大众来说只能依靠<strong>hidden wiki</strong>的帮助,而真正的暗网深度人士大概会有其他的获取渠道,比如IRC聊天室,专门的发布页面等等。(这个只是个人猜测而已)</p>
<h3 id="暗网上有相当多的血腥恐怖的内容"><a href="#暗网上有相当多的血腥恐怖的内容" class="headerlink" title="暗网上有相当多的血腥恐怖的内容"></a>暗网上有相当多的血腥恐怖的内容</h3><p>这个本质上其实不能算谣言。但我拿出来就是因为<strong>这部分内容被媒体过于渲染,把少数当多数。</strong>,<br>这个说法的问题出在于<code>相当多</code>,虽然暗网上确实有部分血腥暴力的站点,但是就和表站里也有很多小众站点如食人,撒旦教等等一样,这部分站点在暗网里也只是占了极少数。从暗网的大部分<strong>hidden wiki</strong>页面来看,暗网的主流内容还是各种交易市场:比特币、毒品、枪支、信用卡等等;再就是色情站点等,买凶相关的站点也有,但是非常血腥主题的确实基本上看不到(有些人大概会认为这说明他们藏的更深,找不到不代表就没有。但是这也从侧面证明了它们的小众,由这种极小部分人群作为暗网代表,我觉得相当缺乏说服力)<br>而根据wiki上<a href="https://en.wikipedia.org/wiki/Dark_web" target="_blank" rel="external">Dark web</a>里的相关数据表明,暗网站点里数量前三的是”Drugs”、”Market”、”Fraud”,即药品、交易、欺诈前三,可以说明那些极度血腥反人类的真的只是极少数</p>
<p><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/hidden-web-category.jpg" alt="暗网网站种类数量占比。2015年一月"></p>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>写到这里就算完成了。这文里我之所以根本没提另一个”Shadow Web”是因为找不到这个更详细的说明,而从作者把”Deep WEB”当”Dark WEB”的水准来说,我估计他可能本来就是想讲暗网。由于里面阴谋论和都市传说的内容太多,所以我就不继续深入了。<br>那个所谓的暗网最深层的Marianas Web同理。如果有人有明确的网站能证明这个等级存在的话麻烦给个链接。个人对这个分级说法本身持怀疑态度。<br>另外贴几张相关的暗网页面截图吧。免得被人说我根本没去过就是瞎扯淡。</p>
<p>首先是<a href="http://uhwiki36pbooodfj.onion/wiki/index.php/Main_Page" target="_blank" rel="external">The Uncensored Hidden Wiki</a>(需要TOR。另外这种导航页其实有很多,各位可以自行挖掘)<br><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/hiddenwiki.jpg" alt="The Uncensored Hidden Wiki"></p>
<p><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/hiddenwiki-list.jpg" alt="The Uncensored Hidden Wiki"><br>另一个导航站点:<img src="http://7xiodk.com1.z0.glb.clouddn.com/static/HDWIKI.jpg" alt="HDWIKI"></p>
<p>其次是某些站点的截图。有军火、Drug、假护照、信用卡等</p>
<p><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/fake.jpg" alt="假护照"><br><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/gun.jpg" alt="枪支"><br><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/creditcard.jpg" alt="信用卡"></p>
<p>不过也不是所有站点都是违法犯罪的,也有些画风比较清奇的比如这个:<br><img src="http://7xiodk.com1.z0.glb.clouddn.com/static/PS4.jpg" alt="PS4固件"><br>这说明其实你也完全可以在暗网搭个网站放动画片。不过有没有人看就是另一回事了</p>
<h2 id="参考文档"><a href="#参考文档" class="headerlink" title="参考文档"></a>参考文档</h2><p><a href="https://zh.wikipedia.org/wiki/%E6%B7%B1%E7%BD%91" target="_blank" rel="external">深网-中文维基</a><br><a href="https://en.wikipedia.org/wiki/Darknet" target="_blank" rel="external">Darknet-Wikipedia</a><br><a href="https://en.wikipedia.org/wiki/Dark_web" target="_blank" rel="external">Dark_web</a><br><a href="http://uhwiki36pbooodfj.onion/wiki/index.php/Main_Page" target="_blank" rel="external">The Uncensored Hidden Wiki</a></p>
]]></content>
<summary type="html">
<p>这是篇没啥技术含量的文章,单纯面向非CS行业的普通大众。主要是前几天看到微博上<code>谷大白话</code>一条<a href="http://weibo.com/1788911247/E4z4xwBrK">微博</a>下很多人”深网””暗网”傻傻分不清楚;加上互联网上很多阴谋论的不入流科普文导致很多人把暗网无端端神话,变成了一个普通人不可能进入的”互联网地下世界”。和几个超自然爱好者交流过后发现他们的确在这件事上的认知偏差很大。为了给净化中文互联网做一点微小的工作,我决定站出来成为<del>IDOL</del>(科普者)。希望这篇文可以让无意点进来的读者有所收获。不喜欢概念分析的可以直接跳到后面的<a href="#谣言">谣言</a>部分。<strong>当然此文只做概念分析没有具体教程</strong></p>
<p>PS:我不是深度暗网使用者,只是花了几个小时翻了下资料而已。所以本文也不会有啥特别的深度,主要就是驳斥几个比较常见的谣言。可能有些地方会有错误,欢迎勘误(不过前提是你在暗网上确实有实际体验过,没有进过任何一个网站只凭着别人的网帖就大言不惭地指点江山的就别怪我不客气了)<br>
</summary>
<category term="科普" scheme="http://chitanda.me/categories/%E7%A7%91%E6%99%AE/"/>
<category term="科普" scheme="http://chitanda.me/tags/%E7%A7%91%E6%99%AE/"/>
</entry>
<entry>
<title>Xperia™ Tablet Z系统升至安卓5.1.1并保留root权限</title>
<link href="http://chitanda.me/2016/03/24/flash-xperia-table-z-kitkat-to-lolipop-with-root/"/>
<id>http://chitanda.me/2016/03/24/flash-xperia-table-z-kitkat-to-lolipop-with-root/</id>
<published>2016-03-24T13:21:54.000Z</published>
<updated>2016-08-25T15:36:09.977Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>手里的平板是从基友那拿的索尼日版<code>Xperia™ Tablet Z</code>(型号<code>SO-03E</code>),上一次刷系统都是两三年前的事了,所以系统一直停留在<code>4.1.2</code>不过实在不怎么适应UI了,所以想升级一下,然后这中间过程简直波澜壮阔九转十八弯,所以记录下,给以后手贱做参考——虽然其实这文可能不怎么适应时代了,因为<code>Xperia™ Tablet Z</code>这平板出来好久了,加上守<code>4.1.2</code>的人估计没那么多,所以遇到我这问题的人估计也不会太多,不过还是做个记录好了。(从<code>4.1.2</code>升级到<code>5.1.1</code>这个很重要,因为大法这机子<strong>4.1.2不能直升5.1.1</strong>,不知道这点的我扔进去了差不多三个晚上以及N次强刷)<br>PS:</p>
<ol>
<li><del>本人不是专业玩机的,所以可能概念或者过程有些认知上的错误,欢迎指正</del></li>
<li>下文提到的都是针对日版<code>Xperia™ Tablet Z</code>(型号<code>SO-03E</code>)而言不同型号机子在具体细节上肯定有区别,注意灵活多变。</li>
<li>本文所有提到的工具都建议去官网下,不过为了方便某些没梯子的群众,我还是做了份百度云的分流。目前可以满足我从<code>4.1.2</code>升级到<code>5.1.1</code>的需求,以后就不知道了╮(╯▽╰)╭ (<a href="http://pan.baidu.com/s/1qXLQV60" target="_blank" rel="external">传送门</a>密码: h6nn)<a id="more"></a>
</li>
</ol>
<h2 id="简要流程"><a href="#简要流程" class="headerlink" title="简要流程"></a>简要流程</h2><p>这个其实是给非新手看的tips,提醒下大概流程以及相应的坑,具体流程下文会讲,另外流程其实不固定,因为不同的刷法带来的结果不一样,所以我这个并不是唯一解,但是<strong>肯定是可用解</strong>,不确定的可以完全照我的流程来.</p>
<ol>
<li>确定机子是否可以解BL锁(Table Z有些型号不能解BL锁,所以不能随意刷第三方系统,反正目测日版不行,所以这里以不能解锁的机子为例)</li>
<li>将系统刷至<code>4.4.4</code>(不知道直升5.0行不行,没试过,所以这里建议升至<code>4.4.4</code>系统即可,如果已经是<code>4.4.4</code>的话就不需要动了,直接下一步即可)</li>
<li>看机子有没有root权限,有root权限的话可以刷<code>lockeddualrecovery</code>;没有root权限的话就上<code>kingroot</code>然后清理掉残留APP。</li>
<li>找个魔改过后的内置root的官方系统来刷,因为5.0以上root都比较麻烦</li>
</ol>
<h2 id="详细流程"><a href="#详细流程" class="headerlink" title="详细流程"></a>详细流程</h2><p>说是详细流程不过也不是面面俱到,有些简单的地方会略过,自行求助搜索引擎。</p>
<h3 id="安装flashtool以及相应驱动"><a href="#安装flashtool以及相应驱动" class="headerlink" title="安装flashtool以及相应驱动"></a>安装flashtool以及相应驱动</h3><p>flashtool可以去<a href="http://www.flashtool.net/downloads.php" target="_blank" rel="external">官网</a>下载,驱动安装失败的话注意<strong>取消Windows系统的驱动数字签名认证</strong>,不同操作系统处理方法可能不一样,自行解决。需要保证这一步做完后手机连上去可以同时被flashtool的adb模式和fastmode识别到。<br>PS:<br><del>sony官方有个<code>Emma</code>,是套了壳的flashtool,但是那个工具使用还要注册帐号,比较恶心,所以就不推荐了</del></p>
<h3 id="检测BL锁是否可解"><a href="#检测BL锁是否可解" class="headerlink" title="检测BL锁是否可解"></a>检测BL锁是否可解</h3><p>平板开USB调试然后连接电脑,之后再打开flashtool,点工具栏上的<code>My SGP3XX</code>-<code>Launch ServiceMenu</code>,然后在平板上选择<code>Service info</code>-<code>Configuration</code>;看最后那个<code>Bootloader unlock allowed</code>里的值是<code>yes</code>还是<code>no</code>。反正我估计日版都是NO,咱们继续下一步。如果你是<code>YES</code>的话,看完这条下面的PS信息就可以去官网解锁,然后走好不送,因为你完全可以去刷CM之类的第三方系统了,也不需要下面费事的折腾了。<br>PS:<br><a href="http://developer.sonymobile.com/unlockbootloader/unlock-yourboot-loader/" target="_blank" rel="external">Sony官方解BL锁申请链接</a><br>仅限是<code>Bootloader unlock allowed</code>是<code>YES</code>的朋友去申请,NO的就不要凑热闹了,无解。目前没有任何办法解。<br><del>另外这个页面其实也提供了另一个检测BL锁是否可解的方法,不过我没按出来,所以略过。诸位可以自行选择完设备后看出来的信息。</del></p>
<h3 id="获取root权限"><a href="#获取root权限" class="headerlink" title="获取root权限"></a>获取root权限</h3><p>有root权限的话直接跳过这步。<br><code>4.1.2</code>系统的root权限获取可以直接用<code>rootkitZ</code>(<a href="http://forum.xda-developers.com/xperia-z/development/root-tool-root-10-3-1-2-67-10-3-1-2-74-t2547714" target="_blank" rel="external">XDA原帖</a>)或者<code>Root_with_Restore_by_Bin4ry</code>(<a href="http://forum.xda-developers.com/showthread.php?t=1886460" target="_blank" rel="external">XDA原帖</a>.不过后面这个工具相对复杂+作者不允许分流,所以下载速度较慢)。<br>但是,如果你是<code>4.4.4</code>需要root的话,上面两个工具都没啥鸟用,漏洞都被sony修补掉了,所以直接上<code>kingroot</code>(不过这个装完后有自带的残留,因此有洁癖的话需要后期处理。)kingroot建议用4.0版的,因为root完不会自动重启。(<a href="http://www.kingroot.net/release" target="_blank" rel="external">官网链接</a>)<br>PS:<br><code>kingroot</code>的残留文件清理方法可以参考XDA这个<a href="http://forum.xda-developers.com/xperia-tablet-z/general/how-to-root-lollipop-xperia-tablet-z-t3115107" target="_blank" rel="external">帖子</a>,不过我是直接root完后刷recovery然后卡刷的<code>supersu</code>,然后也直接清掉了。</p>
<h3 id="刷TabZ-lockeddualrecovery"><a href="#刷TabZ-lockeddualrecovery" class="headerlink" title="刷TabZ-lockeddualrecovery"></a>刷TabZ-lockeddualrecovery</h3><p>这个是专门给未解锁BL的Sony Xperia设备刷第三方recovery的工具,<strong>只需要有root权限即可</strong>。从<a href="http://nut.xperia-files.com/path/XZDualRecovery" target="_blank" rel="external">官网</a>找到自己对应的设备的recovery,然后下载,手机连电脑后打开bat文件,按照你的root权限管理工具选择选项,中间会弹一次root权限请求,注意在手机上允许,然后会自动重启进入<code>twrp</code>.</p>
<h3 id="升级4-4-4ROM"><a href="#升级4-4-4ROM" class="headerlink" title="升级4.4.4ROM"></a>升级4.4.4ROM</h3><p>这一步其实就是我上面<strong>简单流程</strong>里说的刷法不一样的地方。我是自己刷完后才发现我这里可能有更优解,不过没验证所以不当主方法讲,先讲我自己麻烦的方法。</p>
<p>随便找个<code>4.4.4</code>的官方适应<code>SGP321</code>的ftf固件用flashtool刷进去(我是刷的港版),日版注意<code>Partition</code>别清,不然会丢失32G,然后重复上面两步把<code>twrp</code>刷回来。<br>PS:<br>我想到的另一个未验证的更优解法是直接找个内置root的<code>4.4.4</code>的系统然后用recovery卡刷,升到<code>4.4.4</code>后继续卡刷到<code>5.1.1</code>——这么做的好处是root不丢失,而且全程不需要kingroot参与进来(不过这个方法未验证,所以不保证一定可行)</p>
<h3 id="卡刷5-1-1"><a href="#卡刷5-1-1" class="headerlink" title="卡刷5.1.1"></a>卡刷5.1.1</h3><p>这里ROM很多,不过不同ROM好像需要的后续处理不一样。所以推荐一个我用过的,刷完即用不需要后续刷基带之类的ROM——<a href="http://forum.xda-developers.com/xperia-tablet-z/orig-development/rom-pre-rooted-lollipop-t3115002" target="_blank" rel="external">[OFFICIAL 5.1.1] Rooted 10.7.A.0.222 / 228</a><br>刷完重启下即可。不过如果要<code>xposed</code>框架的话,建议刷完系统后不要立即重启,先把<code>xposed</code>框架装上,否则进去后又要等半天优化APP。(<code>xposed</code>选择<code>xposed-v80-sdk22-arm</code>即可)<br>注意要点:</p>
<blockquote>
<p>这个ROM卡刷的时候不需要<code>wipe system</code>,清理掉<code>data</code>和<code>cache</code>即可。(<a href="http://forum.xda-developers.com/showpost.php?p=60940818&postcount=23" target="_blank" rel="external">作者解释</a>,另外作者这里给出了root的另一个解法,不过只刷kernel没试过,所以不评价)</p>
</blockquote>
<h2 id="某些你大概用得上的tips"><a href="#某些你大概用得上的tips" class="headerlink" title="某些你大概用得上的tips"></a>某些你大概用得上的tips</h2><ol>
<li>用flashtool刷官方固件的时候需要进<code>flashmode</code>,然而这个进入的方式并不一样,可能和固件有关。根据我自己的实验,日版固件的话是<strong>长按音量-然后USB连电脑上</strong>;而国际版固件是<strong>长按音量键连上电脑后再按一下电源键</strong>,具体哪个可能要自己多试试,实在不行几个按键都按按总是可以触发的。。</li>
<li>kingroot刷完后如果用那个帖子里的方法不好清理自带的app和授权管理工具的话,可以试试进recovery卡刷<code>superSu</code>,反正我是直接替换掉了。(建议装4.0.0版,然后root完后卸载掉另外两个无关工具后,再进recovery卡刷)</li>
<li>如果刷完机子发现无限重启或者进不去系统了,没找到解决方法的话就flashtool刷一个可用固件吧。就我所知普通刷刷机造成的砖基本上可以靠flashtool强刷救回来</li>
<li>如果你这里刷的系统版本和我不一样,但是刷完最后那个固件后无限自动重启,可能也是跳版本刷的缘故。反正<code>4.1.2</code>直接刷<code>5.1.1</code>是不行的。中间要是有跨度比较大的rom变动后无限重启又找不到解决方法,可以考虑下这个可能。</li>
<li>使用各种root脚本的时候,如果adb总是报错,可以自己另起一个cmd输入<code>adb devices</code>看看状态,如果总是无法<code>start deamon</code>的话可以去任务管理器看看,若是启用了多个ADB的话记得都关掉然后重新开脚本;若是提示<code>devices offline</code>,则有可能是你的adb版本太老,直接下载我的百度云文件夹里的adb过去覆盖掉即可</li>
</ol>
<hr>
]]></content>
<summary type="html">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>手里的平板是从基友那拿的索尼日版<code>Xperia™ Tablet Z</code>(型号<code>SO-03E</code>),上一次刷系统都是两三年前的事了,所以系统一直停留在<code>4.1.2</code>不过实在不怎么适应UI了,所以想升级一下,然后这中间过程简直波澜壮阔九转十八弯,所以记录下,给以后手贱做参考——虽然其实这文可能不怎么适应时代了,因为<code>Xperia™ Tablet Z</code>这平板出来好久了,加上守<code>4.1.2</code>的人估计没那么多,所以遇到我这问题的人估计也不会太多,不过还是做个记录好了。(从<code>4.1.2</code>升级到<code>5.1.1</code>这个很重要,因为大法这机子<strong>4.1.2不能直升5.1.1</strong>,不知道这点的我扔进去了差不多三个晚上以及N次强刷)<br>PS:</p>
<ol>
<li><del>本人不是专业玩机的,所以可能概念或者过程有些认知上的错误,欢迎指正</del></li>
<li>下文提到的都是针对日版<code>Xperia™ Tablet Z</code>(型号<code>SO-03E</code>)而言不同型号机子在具体细节上肯定有区别,注意灵活多变。</li>
<li>本文所有提到的工具都建议去官网下,不过为了方便某些没梯子的群众,我还是做了份百度云的分流。目前可以满足我从<code>4.1.2</code>升级到<code>5.1.1</code>的需求,以后就不知道了╮(╯▽╰)╭ (<a href="http://pan.baidu.com/s/1qXLQV60">传送门</a>密码: h6nn)
</summary>
<category term="折腾" scheme="http://chitanda.me/categories/%E6%8A%98%E8%85%BE/"/>
<category term="刷机" scheme="http://chitanda.me/tags/%E5%88%B7%E6%9C%BA/"/>
<category term="折腾" scheme="http://chitanda.me/tags/%E6%8A%98%E8%85%BE/"/>
</entry>
<entry>
<title>服务器初始安全设置(CentOS 6.5)</title>
<link href="http://chitanda.me/2016/02/13/Initial-Server-Secure-Settings-with-CentOS-6-5/"/>
<id>http://chitanda.me/2016/02/13/Initial-Server-Secure-Settings-with-CentOS-6-5/</id>
<published>2016-02-12T19:43:03.000Z</published>
<updated>2016-09-02T12:36:05.974Z</updated>
<content type="html"><![CDATA[<p>VPS买来好几个月了,之前因为感觉<code>fail2ban</code> 可能会造成log爆炸就没装,然后仅仅禁了root帐号登录和换了个登录帐号——倒也相安无事,但是那天去<code>/var/log/</code>目录下看log的时候发现每天的登录日志和帐号密码错误信息能塞十几二十M——被人盯上了用机器企图暴力破解,虽然由于猜不到我用户名所以VPS本身不会出事,但是天天被人这么搞也不爽,然后就稍微折腾下。在<code>禁root登录</code>、<code>换登陆用户</code> 的基础上又加了几个安全措施:<code>换SSH端口</code> 、<code>使用ssh密钥文件登录</code>。所以写个文章做个记录——其实文章里有个关于ssh <code>config</code>文件的彩蛋才是我最想推荐的(本文以Centos 6.5为例,具体的文件路径可能不同的linux发行版会有区别。)</p>
<a id="more"></a>
<blockquote>
<p>因为很重要所以写在最前面:<br>所有安全措施更新后检测是否生效的时候都不需要关闭当前的ssh term 窗口,直接另开一个就好。当前窗口不要关闭,可以用来在发生某些意外情况下做补救措施(比如换了sshd的端口但是忘记在防火墙里开放端口等)否则就只能去VPS提供商的VNC服务器里去做补救了,比较麻烦</p>
</blockquote>
<h2 id="禁用root登录"><a href="#禁用root登录" class="headerlink" title="禁用root登录"></a>禁用root登录</h2><ol>
<li><p>新建一个用户并设置密码,如添加一个用户名为<code>test</code>的用户(方便行文下文都会以<code>test</code>作为例子,建议自行替换)</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">adduser test #添加用户</div><div class="line">passwd test #会弹出设置密码的提示,输两遍即可</div></pre></td></tr></table></figure>
</li>
<li><p>添加<code>sudo</code>用户组<br>目的是为了给新添加的帐号sudo权限,不过每次都手动设置单个帐号比较麻烦,所以建议先直接添加一个免密码的<code>sudo</code>用户组,后续的用户可以一次性添加到该组(另外安全考虑不建议sudo用户组里用户过多)</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">visudo</div></pre></td></tr></table></figure>
<blockquote>
<p>如果提示<code>visudo: command not found</code>的话,可以用<code>yum -y install sudo</code>安装<strong>sudo</strong>即可</p>
</blockquote>
<p>然后往下拉找到</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">## Same thing without a password</div><div class="line"># %wheel ALL=(ALL) NOPASSWD: ALL</div></pre></td></tr></table></figure>
<p>去掉下面那个<code>#</code>注释让设置生效然后保存文件退出。</p>
<blockquote>
<p>如果没有找到该内容的话可以自己手动添加进去。另外<code>NOPASSWD:ALL</code>可以让sudo指令免密码,方便的同时<strong>降低了一定安全性</strong>,所以看个人取好自行决定</p>
</blockquote>
</li>
<li><p>将新建用户添加进<code>sudo</code>组<br>这样的话后面就不需要每次都切换到root帐号了,需要sudo权限的命令都可以直接通过<code>sudo <command></code>来执行</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">gpasswd -a test wheel</div></pre></td></tr></table></figure>
<blockquote>
<p>上面两步的<code>wheel</code>可以自行替换成你喜欢的用户组名。<br>具体可参考:<a href="https://www.digitalocean.com/community/tutorials/how-to-add-and-delete-users-on-a-centos-7-server" target="_blank" rel="external">how-to-add-and-delete-users-on-a-centos-7-server</a></p>
</blockquote>
</li>
</ol>
<h2 id="设置SSH登录"><a href="#设置SSH登录" class="headerlink" title="设置SSH登录"></a>设置SSH登录</h2><ol>
<li><p>生成ssh密钥文件</p>
<blockquote>
<p>Windows系统以<code>putty</code>为例,生成以及配置的图文教程可以参考此文:<a href="http://callmepeanut.blog.51cto.com/7756998/1336358" target="_blank" rel="external">Putty使用密钥自动登陆SSH</a><br>linux下的密钥生成过程和github的密钥生成过程类似,可以参考此文: <a href="http://chitanda.me/2015/06/11/tips-for-setup-hexo/#git多网站ssh部署方案">git多网站ssh部署方案</a></p>
</blockquote>
<hr>
</li>
<li><p>上传公钥到服务器</p>
<ul>
<li><p>客户端为Windows系统时服务器端的操作:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">cd /home/test #进入test用户文件夹下</div><div class="line">mkdir .ssh #生成.ssh文件夹</div><div class="line">touch .ssh/authorized_keys #生成服务器端公钥文件</div><div class="line">vi .ssh/authorized_keys</div></pre></td></tr></table></figure>
<p>然后将前面putty生成的公钥部分复制进去后保存文件退出。<br><strong>注意openssh需要的公钥文件格式和putty导出保存的公钥文件格式不一样,正确格式是生成框里的那部分,所以不要复制错了</strong></p>
<blockquote>
<p>正确格式:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAxx+1Ab3s5TB4umhxspJA91i2az0QW7JTVBR+J/OYPyjDH803Upxvo</div><div class="line">sg0lDkf7nTmL3nyE6YCBPgQMgT+HvVDDI6CQ68E/ZQOmgNpGo70k+x/C7VkPu8z+5yBXwwI1K5maHqY4B8RIKVCYon</div><div class="line">2eMLhtyLC6U/K1OXaCdz0wR8xwz+rT8REmoCv770yC/FOsgmI250bAvVlqircvLfknlTrETAgaQ8PR9e5pNuoGwX3v</div><div class="line">pCMBnuKjXKQpHvAX1MKFx4UFGC6MIB5Gcq4H9nv9aBUKnWO+m58JF8tAU7KhfkUc2wWG11ON21K3w/gL7dyHPRyLGJ</div><div class="line">yBZRFKBZGr+gzCfrhzw== rsa-key-20160331</div></pre></td></tr></table></figure>
</blockquote>
<hr>
</li>
<li><p>客户端为linux系统的话<code>ssh-copy-id</code>指令即可</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">ssh-copy-id -i ~/.ssh/id_rsa.pub root@123.123.123.123</div></pre></td></tr></table></figure>
<blockquote>
<p>虽然要设置的登录帐号不是root,不过还是建议先传到<code>root</code>用户文件夹下,然后服务器端做转移。(之前试过直接传给对应帐号好像出了点问题,可能是权限之类的)</p>
</blockquote>
</li>
</ul>
<hr>
</li>
<li><p>使用密钥文件登录<br>Windows下使用putty登录的配置参考步骤1的<a href="http://callmepeanut.blog.51cto.com/7756998/1336358" target="_blank" rel="external">参考文章</a> 。<br>如果<strong>有使用其他shell登录需求</strong>的可以继续往下看,以git bash为例:<br>由于putty的私钥文件不通用,所以需要转换出<code>RSA</code>格式给其他shell用,需要在 <code>PUTTYGEN.EXE</code> 上方菜单里的 <code>Conversions</code> > <code>Export OpenSSH Key</code> 转换成通用的私钥文件,假设文件名为<code>test</code><br>然后将其放到当前用户的<code>C:\Users\username\.ssh</code>目录下.(其实这里的配置过程和git的ssh登录配置过程类似)<br><strong>彩蛋:</strong>如果目录下有多个密钥网站了,还需要修改同目录下你的ssh配置文件(<code>config</code>文件),添加下面内容:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">Host test #这个名字随意</div><div class="line">HostName 123.123.123.123 #IP地址或服务器域名</div><div class="line">Port 22 #服务器端开放的ssh端口,默认22</div><div class="line">User test#登录的用户名</div><div class="line">IdentityFile ~/.ssh/test #使用的密钥文件密钥文件</div></pre></td></tr></table></figure>
<p>上面这里是完整的ssh配置格式,这么配置后git bash里可以直接用<code>ssh test</code>的方式直接登录,省去了输域名或者ip地址以及用户名的过程,简单不少。(关于ssh config文件的配置具体可以参考此文:<a href="https://www.digitalocean.com/community/tutorials/how-to-configure-custom-connection-options-for-your-ssh-client" target="_blank" rel="external">How To Configure Custom Connection Options for your SSH Client</a>)</p>
<blockquote>
<p>PS:登录这个步骤是比较容易出错的,如果服务器端配置有问题的话。建议服务器端先将sshd的<code>log level</code>开到<code>debug3</code>:<br> <code>vi /etc/ssh/sshd_config</code>后修改<code>LogLevel</code>为<code>debug3</code><br>然后保存退出并<code>service sshd restart</code>重启ssh服务.接着客户端执行登录操作,如果有错误的话,<code>less /var/log/secure</code>打开登录的log文件拉到最底下查看对应问题。<br>以我个人配置经验来看,失败的话一般无外乎以下几个原因:、</p>
<ol>
<li>key的位置不是默认的<code>~/.ssh/</code>而是<code>./home/{username}/.ssh/</code>(这里有个细节在于即使<code>sshd_config</code>配置<code>AuthorizedKeysFile .ssh/authorized_keys</code>,由于linux系统的<code>~</code>表示当前用户的根目录,所以非root用户的key路径依旧是对应的<code>home/username</code>文件夹下而不是root根目录)</li>
<li>key对应的文件夹给700权限,key本身至少400权限保证可读</li>
<li><code>authorized_keys</code>文件的用户组要设置为对应的用户组,否则读取不了 </li>
<li>在某些服务商的 CentOS 系统里,由于开启了 <code>SELinux</code> ,默认是禁止了 .ssh 目录的权限的,可以用下面的命令解除限制:<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">restorecon -R -v /root/.ssh</div></pre></td></tr></table></figure>
</li>
</ol>
</blockquote>
</li>
</ol>
<h2 id="SSH其他配置"><a href="#SSH其他配置" class="headerlink" title="SSH其他配置"></a>SSH其他配置</h2><p>如果上面ssh密钥登录设置完成了,为了最后的安全,我们还需要做三件事:</p>
<ol>
<li>禁止密码登录</li>
<li>禁止<code>root</code>用户登录</li>
<li><p>修改SSH默认端口<br>由于以上三个都是<code>sshd_config</code>里的东西,所以合一起讲:<br>修改以下三个属性保存并重启SSH即可</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">PermitRootLogin no</div><div class="line">PasswordAuthentication no</div><div class="line">Port 65525</div></pre></td></tr></table></figure>
<blockquote>
<p>修改端口后需要注意,大部分VPS应该都默认开了防火墙,所以<strong>需要防火墙里把对应端口开放</strong>,否则会无法登录</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">iptables -I INPUT -p tcp --dport 65525 -j ACCEPT</div><div class="line">service iptables save</div><div class="line">service iptables restart</div></pre></td></tr></table></figure>
</blockquote>
</li>
</ol>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ol>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-add-and-delete-users-on-a-centos-7-server" target="_blank" rel="external">how-to-add-and-delete-users-on-a-centos-7-server</a></li>
<li><a href="http://callmepeanut.blog.51cto.com/7756998/1336358" target="_blank" rel="external">Putty使用密钥自动登陆SSH</a></li>
<li><a href="http://chitanda.me/2015/06/11/tips-for-setup-hexo/#git多网站ssh部署方案">git多网站ssh部署方案</a></li>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-configure-custom-connection-options-for-your-ssh-client" target="_blank" rel="external">How To Configure Custom Connection Options for your SSH Client</a></li>
<li><a href="https://ttt.tt/104/" target="_blank" rel="external">购买 Linux VPS 服务器后简单的安全设置</a> </li>
</ol>
]]></content>
<summary type="html">
<p>VPS买来好几个月了,之前因为感觉<code>fail2ban</code> 可能会造成log爆炸就没装,然后仅仅禁了root帐号登录和换了个登录帐号——倒也相安无事,但是那天去<code>/var/log/</code>目录下看log的时候发现每天的登录日志和帐号密码错误信息能塞十几二十M——被人盯上了用机器企图暴力破解,虽然由于猜不到我用户名所以VPS本身不会出事,但是天天被人这么搞也不爽,然后就稍微折腾下。在<code>禁root登录</code>、<code>换登陆用户</code> 的基础上又加了几个安全措施:<code>换SSH端口</code> 、<code>使用ssh密钥文件登录</code>。所以写个文章做个记录——其实文章里有个关于ssh <code>config</code>文件的彩蛋才是我最想推荐的(本文以Centos 6.5为例,具体的文件路径可能不同的linux发行版会有区别。)</p>
</summary>
<category term="运维" scheme="http://chitanda.me/categories/%E8%BF%90%E7%BB%B4/"/>
<category term="运维" scheme="http://chitanda.me/tags/%E8%BF%90%E7%BB%B4/"/>
<category term="vps" scheme="http://chitanda.me/tags/vps/"/>
</entry>
<entry>
<title>个人常用一些PC软件(windows系统)</title>
<link href="http://chitanda.me/2016/01/07/use-common-software-in-PC/"/>
<id>http://chitanda.me/2016/01/07/use-common-software-in-PC/</id>
<published>2016-01-07T09:29:52.000Z</published>
<updated>2016-08-25T11:22:55.603Z</updated>
<content type="html"><![CDATA[<p>前段时间正好换硬盘重装了系统,所以全部软件都要重新装一遍,趁此机会把一些常用软件以及某些有用处但是频率较低的小软件做个记录,当备份吧(只记录名字,没有链接和破解之类的)。万一哪天记不起来了可以自己翻下。<br><a id="more"></a></p>
<h2 id="生活常用-大众向)"><a href="#生活常用-大众向)" class="headerlink" title="生活常用(大众向)"></a>生活常用(大众向)</h2><ol>
<li><p>爬墙<br><code>Shadowsocks</code></p>
</li>
<li><p>浏览器<br><code>Chrome、Firefox、Eege、IE11</code></p>
</li>
<li><p>输入法<br><code>QQ输入法</code>(有个纯净版QQPinyin_Setup_4.7.2065.400)</p>
</li>
<li><p>文件搜索工具<br><strong>Everything</strong> (只搜索文件名,但是效率极高,比原生的好太多,可以当一个集合的 launcher)</p>
</li>
<li><p>解压缩工具<br><code>Winrar</code>(现在免费版有广告,所以体验一般,但是只有<code>rar</code>可以加恢复记录,所以大文件分包的时候不能少 )、<code>7-Zip</code>、<code>Bandizip</code>(免费,功能也很多,可以当日常解压软件用)</p>
</li>
<li><p>通讯软件<br><code>QQ</code></p>
</li>
<li><p>下载工具<br><code>迅雷(离线是大杀器)、百度云管家(网盘里目前最好)、 uTorrent(PT用)、IDM(视频嗅探是神器,不过现在不怎么当搬运工, 所以这个用的少)</code></p>
</li>
<li><p>视频播放器<br><code>Potplayer+LAV解码器</code></p>
</li>
<li><p>音乐播放器<br><code>Foorbar2000</code>、<code>网易云音乐(UWP版的功能稍微弱了点。不过好看)</code></p>
</li>
<li><p>图片浏览器<br><code>Honeyview(和前面的"Bandizip"出自同门,效果和体验比自带的好不少)</code>、<code>MangaMeeya(漫画阅读器,除了对特殊字符支持不好以外,其他都很好。虽然PC上本来看漫画的体验就一般般)</code></p>
</li>
<li><p>PDF/EPUB阅读器<br><strong>SumatraPDF</strong>(绿色轻量而且免费,支持的格式也不少,比Adobe家的好太多)</p>
</li>
<li><p>Office文档阅读器<br><code>WPS海外版</code>(Office365太贵而且没啥大用,WPS海外版除了语言是英文外没其他问题)</p>
</li>
<li><p>虚拟光驱<br><code>DAEMON Tools Lite</code></p>
</li>
<li><p>游戏客户端<br><code>STEAM</code></p>
</li>
<li><p>远程协助<br><code>TeamViewer</code></p>
</li>
<li><p>CD抓轨<br><code>Exact Audio Copy</code></p>
</li>
<li><p>DVD抓取<br><code>DVD Decryter</code></p>
</li>
<li><p>视频处理(剪辑/拼接/remux/压制等)<br><code>小丸工具箱</code>(其实一个小丸不够处理全部情况,不过大部分情况这个gui是够用了,这里细写下去太多,目前不怎么弄视频了,所以就略过了)</p>
</li>
<li><p>系统垃圾清理<br><code>Dism++</code>(www.chuyu.me)</p>
</li>
<li><p>其他小工具</p>
<ol>
<li>粘贴板记录 : <strong>CLIPCUE</strong>(可以记录全部的粘贴板记录,而且可以按照设置来保留N久之前的记录,哪怕重启过电脑,防手贱神器。1.2.1版还可以记录文档,类似系统自带的便签)</li>
<li>计算文件HASH值 : <code>HASH.exe</code>(毫无辨识度的名字,搜索的话需要加个<code>Robin Keir</code>的关键词。可以计算MD5、SHA1、CRC32,比起集成到系统属性页的某些插件,这个更轻量)</li>
<li>GIF录制 : <strong>GifCam</strong> (轻量且免费,功能强大)</li>
<li>取色器 : <code>Takecolor</code>(全局取色器,这个其实算是工作用。)</li>
<li>QQ表情包EIF解压 : <code>EIF解压工具 by coolslob</code>(QQ表情包现在导出后都不能直接被解压,可以利用这个工具。虽然写的很早,不过2015版的QQ表情也是可以被处理</li>
</ol>
</li>
</ol>
<p>PS : 如果不想弄太多乱七八糟的小工具,可以试试软媒魔方的工具,虽然是国产,但是基本上没啥流氓行为,而且里面也都是绿色的小工具,完全可以拆开来用</p>
<h2 id="工作用(技术向)"><a href="#工作用(技术向)" class="headerlink" title="工作用(技术向)"></a>工作用(技术向)</h2><ol>
<li><p>编辑器<br><code>Sublime Text</code>、<code>EmEditor</code>(可以自动切换文件编码,二进制模式很好用)</p>
</li>
<li><p>IDE<br>暂无在用的,前端用编辑器足够。不过有在考虑要不要用下<code>WebStorm</code></p>
</li>
<li><p>本地服务器环境<br><strong>phpStudy</strong> (最简单最好用的一键环境包,全版本且无捆绑,切换也极度方便,虽然现在很多Node.js的后台,不过我还是比较推荐这个)</p>
</li>
<li><p>抓包软件<br><code>Fiddler</code>(足够对付大部分情况,轻松上手)、<code>SRSniffer</code>(by “suprole#gmail.com”,一个全局的应用程序抓包工具)、<code>Wireshark</code>(虽然把这个写上去了,然而学习门槛太高现在还没学会怎么用)</p>
</li>
<li><p>版本管理</p>
<ol>
<li>Git : <code>git-for-windows</code>(个人感觉比官方的<code>Github Desktop</code>好用不少)</li>
<li>SVN : <code>TortoiseSVN</code></li>
</ol>
</li>
</ol>
<ol>
<li><p>远程shell管理工具<br><code>putty</code>(远程VPS管理工具。VPS已经买好,就差学shell指令了)</p>
</li>
<li><p>FTP管理工具<br><code>FileZilla</code></p>
</li>
<li><p>虚拟机<br><code>Windows XP Mode</code>(win7下,装XP的话比其他虚拟机好很多。WIN10下取消了)、<code>VirtualBox</code>、<code>Hyper-V</code>(WIN10自带虚拟机管理工具)</p>
<p></p>
</li>
</ol>
<hr>
]]></content>
<summary type="html">
<p>前段时间正好换硬盘重装了系统,所以全部软件都要重新装一遍,趁此机会把一些常用软件以及某些有用处但是频率较低的小软件做个记录,当备份吧(只记录名字,没有链接和破解之类的)。万一哪天记不起来了可以自己翻下。<br>
</summary>
<category term="技术" scheme="http://chitanda.me/tags/%E6%8A%80%E6%9C%AF/"/>
</entry>
<entry>
<title>单个GitHub帐号下添加多个GitHub Pages的相关问题</title>
<link href="http://chitanda.me/2015/11/03/multiple-git-pages-in-one-github-account/"/>
<id>http://chitanda.me/2015/11/03/multiple-git-pages-in-one-github-account/</id>
<published>2015-11-03T08:06:55.000Z</published>
<updated>2016-08-25T15:36:56.989Z</updated>
<content type="html"><![CDATA[<p>好久没更新文章了,这边都快成荒地了。今天想到一个比较简单的问题,所以先处理了写篇文章上来,好给blog加点生机(<del>其实post里躺着不少草稿,不过一直没办法写完╮(╯▽╰)╭</del>)</p>
<p>很早之前我就记得某篇讲hexo的文章里提到<strong>每个GitHub只能拥有一个GitHub Pages页面</strong>,所以后来一直不敢在自己的帐号底下添加除blog外的其他GitHub Pages项目。直到今天仔细研究了下GitHub的规则,才发现上面那句话有很大的问题。</p>
<p>这篇文章主要是讲github下多个GitHub Pages项目相关以及自定义域名访问的问题,没太多技术上的东西,基本上都是属于GitHub的文档意译和解释,英语好的可以直接看这官网这两篇FAQ:</p>
<ol>
<li><a href="https://help.github.com/articles/about-custom-domains-for-github-pages-sites/" target="_blank" rel="external">About custom domains for GitHub Pages sites</a></li>
<li><a href="https://help.github.com/articles/user-organization-and-project-pages/" target="_blank" rel="external">User, Organization, and Project Pages</a></li>
</ol>
<a id="more"></a>
<hr>
<blockquote>
<p>注:虽然全文基本上都在讲GitHub Pages,<strong>但我个人亲测这些规则也都适用于GitCafe Pages,两者没有本质区别。</strong> 所以像我一样双线部署blog的可以安心地把GitHub的东西搬到GitCafe来。不过为了行文方便,下文不再特意强调GitCafe Page,均以<code>GitHub Pages</code>代指(“Coding”的是否也如此并不清楚,有心人可以自测)</p>
</blockquote>
<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>以我个人为例,我在GitHub上已经有了一个和用户名同名的<a href="https://github.com/chitanda/chitanda.github.io" target="_blank" rel="external">GitHub Pages项目</a>当作个人主页(<a href="http://chitanda.github.io" target="_blank" rel="external">chitanda.github.io</a>),但是我现在又有了几个想法:</p>
<ol>
<li>再在GitHub上弄一个GitHub Pages项目当作我的demo页面展示,而不是在原先的blog项目下加子目录(一来访问url不好看,二来很多主题会强制对所有项目内的文件添加样式,影响展示效果)</li>
<li>同时demo页面的访问链接是我自定义的一个域名(如:是<code>demo.chitanda.me</code>或者<code>demo.chitanda.github.io</code>而不是<code>chitanda.github.io/demo</code>)</li>
</ol>
<p>那么上面两个要求,GitHub能否都满足呢?卖个关子先,结论放在<a href="#总结">下文</a>。</p>
<h2 id="GitHub-Pages的分类及区别"><a href="#GitHub-Pages的分类及区别" class="headerlink" title="GitHub Pages的分类及区别"></a>GitHub Pages的分类及区别</h2><p>根据<a href="https://help.github.com/articles/user-organization-and-project-pages/" target="_blank" rel="external">官方文档</a>,GitHub Pages分为两类:<strong>个人/组织主页</strong>以及<strong>项目主页</strong>,两者基本上没啥区别,但是有以下几点不同:(该文场景下个人和组织帐号没什么区别,所以下文为了行文方便将统一用<strong>个人主页</strong>代指)</p>
<ol>
<li><strong>个人主页</strong>必须要和用户的GitHub帐号同名,所以每个用户有且只能有一个repo作为个人主页,且必须是<code><username>/<username>.github.io</code>的形式;而<strong>项目主页</strong>的命名则没有这种限制,且数量有任意多个。</li>
<li>不考虑绑定的自定义域名的前提下,<strong>个人主页</strong>的GitHub二级域名为<code><username>.github.io</code>;<strong>项目主页</strong>的GitHub二级域名为<code><username>.github.io/<projectname></code>,没有<code><projectname>.<username>.github.io</code>这种方式</li>
<li><strong>个人主页</strong>的展示内容以<code>master</code>分支里的文件为准;而<strong>项目主页</strong>的展示内容以<code>gh-pages</code>分支内的文件为准</li>
</ol>
<blockquote>
<p>从上面的分析可以发现两个问题已经解决掉一个半了。那么剩下来的问题就是如何配置一个项目主页并绑定自定义域名了。</p>
</blockquote>
<h2 id="项目主页的建立和自定义域名配置"><a href="#项目主页的建立和自定义域名配置" class="headerlink" title="项目主页的建立和自定义域名配置"></a>项目主页的建立和自定义域名配置</h2><p><strong>注:配置过程和个人主页一模一样,如果之前配置过个人主页的,可以跳过这部分内容了</strong></p>
<h3 id="建立项目主页"><a href="#建立项目主页" class="headerlink" title="建立项目主页"></a>建立项目主页</h3><ol>
<li>新建一个repo,repo名字随意。</li>
<li>点进repo主页然后点击右面的<code>Settings</code>,页面往下拉到<strong>GitHub Pages</strong>部分,选择<code>Launch automatic page generator</code>><code>Continue to layouts</code>><code>Publish page</code>即可.(由于大部分情况下并不用默认的页面和样式,所以这里不需要太纠结于内容编辑)</li>
</ol>
<blockquote>
<p>这样一个项目主页就建立完成了,此时可以用<code><username>.github.io/<projectname></code>访问到了。</p>
</blockquote>
<h3 id="绑定自定义域名"><a href="#绑定自定义域名" class="headerlink" title="绑定自定义域名"></a>绑定自定义域名</h3><ol>
<li>在项目的repo里新建一个<code>CNAME</code>文件,并将不带协议名的裸域名写进去(<code>demo.chitanda.me</code>而不是<code>http://demo.chitanda.me/</code>)<blockquote>
<p>这一步可以参考<a href="https://help.github.com/articles/adding-a-cname-file-to-your-repository/" target="_blank" rel="external">官方文档</a></p>
</blockquote>
</li>
<li>到你域名的DNS服务商里给对应的二级域名添加<code>CNAME</code>解析到<code><username>.github.io</code>(和个人主页的配置相同)</li>
<li>等待DNS生效,具体时间和服务商有关(十几分钟到几小时都有可能)。<blockquote>
<p>如果不确定自己的解析是否生效了,可以在linux系统下用<code>dig</code>命令来检测.参考<a href="https://help.github.com/articles/tips-for-configuring-a-cname-record-with-your-dns-provider/#configuring-a-custom-subdomain-with-your-dns-provider" target="_blank" rel="external">官方文档</a></p>
</blockquote>
</li>
</ol>
<h2 id="GitHub和GitCafe双线部署的小tips"><a href="#GitHub和GitCafe双线部署的小tips" class="headerlink" title="GitHub和GitCafe双线部署的小tips"></a>GitHub和GitCafe双线部署的小tips</h2><p>上面的配置对于单线部署的来说已经完成了,不过对于双线部署的用户而言,有几个小问题需要注意下</p>
<ol>
<li>DNS服务商里要按照来源对对应的二级域名做分流配置。(具体过程可以参考<a href="/2015/06/11/tips-for-setup-hexo/#单域名多线路解析">此处</a></li>
<li>如果想要所有用户都可以用<code>example.com/project</code>的方式访问到repo,GitHub和GitCafe的repo名字必须相同,否则会导致有一边跳404<blockquote>
<p>可以参考我这里的例子:GitHub上的<a href="https://github.com/chitanda/demo" target="_blank" rel="external">项目主页</a>名字为<code>demo</code>,GitCafe上的<a href="https://gitcafe.com/chitanda/demos" target="_blank" rel="external">项目主页</a>名字为<code>demos</code>,则不翻墙的情况下国内用户访问<a href="http://chitanda.me/demo/">chitanda.me/demo</a>会跳404,而用<a href="http://demo.chitanda.me/" target="_blank" rel="external">demo.chitanda.me</a>则正常(另外同个链接在翻墙和不翻墙的情况下看到的页面不同,也是分线部署的功劳)</p>
</blockquote>
</li>
</ol>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>聊胜于无的总结。对于上面提到的几个问题,也有了答案:</p>
<ol>
<li>每个GitHub帐号下只能有<code>1</code>个<strong>个人主页</strong>repo,但是可以有<code>不限数量</code>的<strong>项目主页</strong>repo。</li>
<li>没有自定义域名的情况下,<strong>项目主页</strong>的访问链接只能是<code><username>.github.io/<projectname></code>而不是<code><projectname>.<username>.github.io</code></li>
<li>GitCafe添加GitHub Pages后必须要自己本地同步文件上去,而不能像GitHub那样一键建站,GitCafe每个repo初始化页面的代码是有步骤略过去的,新手的话一开始可能同步不了。建议看他们的<a href="https://gitcafe.com/GitCafe/Help/wiki/Pages-%E7%9B%B8%E5%85%B3%E5%B8%AE%E5%8A%A9#wiki" target="_blank" rel="external">帮助</a></li>
</ol>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ol>
<li><a href="https://help.github.com/articles/about-custom-domains-for-github-pages-sites/" target="_blank" rel="external">About custom domains for GitHub Pages sites</a></li>
<li><a href="https://help.github.com/articles/user-organization-and-project-pages/" target="_blank" rel="external">User, Organization, and Project Pages</a></li>
<li><a href="https://help.github.com/articles/adding-a-cname-file-to-your-repository/" target="_blank" rel="external">Adding a CNAME file to your repository</a></li>
<li><a href="https://help.github.com/articles/tips-for-configuring-a-cname-record-with-your-dns-provider/#configuring-a-custom-subdomain-with-your-dns-provider" target="_blank" rel="external">Tips for configuring a CNAME record with your DNS provider</a></li>
<li><a href="https://gitcafe.com/GitCafe/Help/wiki/Pages-%E7%9B%B8%E5%85%B3%E5%B8%AE%E5%8A%A9" target="_blank" rel="external">GitCage Pages-相关帮助</a></li>
<li><a href="/2015/06/11/tips-for-setup-hexo/#单域名多线路解析">单域名多线路解析</a></li>
</ol>
<hr>
]]></content>
<summary type="html">
<p>好久没更新文章了,这边都快成荒地了。今天想到一个比较简单的问题,所以先处理了写篇文章上来,好给blog加点生机(<del>其实post里躺着不少草稿,不过一直没办法写完╮(╯▽╰)╭</del>)</p>
<p>很早之前我就记得某篇讲hexo的文章里提到<strong>每个GitHub只能拥有一个GitHub Pages页面</strong>,所以后来一直不敢在自己的帐号底下添加除blog外的其他GitHub Pages项目。直到今天仔细研究了下GitHub的规则,才发现上面那句话有很大的问题。</p>
<p>这篇文章主要是讲github下多个GitHub Pages项目相关以及自定义域名访问的问题,没太多技术上的东西,基本上都是属于GitHub的文档意译和解释,英语好的可以直接看这官网这两篇FAQ:</p>
<ol>
<li><a href="https://help.github.com/articles/about-custom-domains-for-github-pages-sites/">About custom domains for GitHub Pages sites</a></li>
<li><a href="https://help.github.com/articles/user-organization-and-project-pages/">User, Organization, and Project Pages</a></li>
</ol>
</summary>
<category term="blog" scheme="http://chitanda.me/categories/blog/"/>
<category term="github" scheme="http://chitanda.me/tags/github/"/>
<category term="hexo" scheme="http://chitanda.me/tags/hexo/"/>
<category term="博客" scheme="http://chitanda.me/tags/%E5%8D%9A%E5%AE%A2/"/>
</entry>
<entry>
<title>JS原生Date类型方法的一些冷知识</title>
<link href="http://chitanda.me/2015/08/21/the-trivia-of-js-date-function/"/>
<id>http://chitanda.me/2015/08/21/the-trivia-of-js-date-function/</id>
<published>2015-08-21T06:49:08.000Z</published>
<updated>2016-08-25T15:41:00.307Z</updated>
<content type="html"><![CDATA[<p>一个多月没更新了- -偷懒中。这个东西其实很早之前就在整理了,不过后来发现自己不少地方没弄明白,然后就一直卡那边了(其实就是不想写吧),想了下反正是给自己熟悉js的原生API而已,所以也没必要太钻牛角尖,也不一定要多完整,因此就当是<code>Date()</code>函数的一个冷门知识点小补充吧。这篇文章主要讲Date()的字符串与时间戳转换以及用户时间本地化,可能内容上比较乱(不然也不会卡我一个月时间了),见谅<br><a id="more"></a><br>ps:由于<code>Date()</code>是js原生函数,不同浏览器的解析器对其实现方式并不同,所以返回值也会有所区别。本文测试未特别申明浏览器的情况下,均是指<code>win7 x64</code>+<code>chrome 44.0.2403.155 (正式版本) m (32 位)</code>版本</p>
<h2 id="Date-与new-Date-的区别"><a href="#Date-与new-Date-的区别" class="headerlink" title="Date()与new Date()的区别"></a>Date()与new Date()的区别</h2><p><code>Date()</code>直接返回当前时间字符串,<strong>不管参数是number还是任何string</strong><br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="built_in">Date</span>();</div><div class="line"><span class="built_in">Date</span>(<span class="string">'sssss'</span>);</div><div class="line"><span class="built_in">Date</span>(<span class="number">1000</span>);</div><div class="line"><span class="comment">//Fri Aug 21 2015 15:46:21 GMT+0800 (中国标准时间)</span></div></pre></td></tr></table></figure></p>
<p>而<code>new Date()</code>则是会根据参数来返回对应的值,无参数的时候,返回当前时间的字符串形式;有参数的时候返回参数所对应时间的字符串。<strong><code>new Date()</code>对参数不管是格式还是内容都要求,且只返回字符串</strong>,</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>();</div><div class="line"><span class="comment">//Fri Aug 21 2015 15:51:55 GMT+0800 (中国标准时间)</span></div><div class="line"></div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="number">1293879600000</span>);</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2011-01-01T11:00:00'</span>)</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2011/01/01 11:00:00'</span>)</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="number">2011</span>,<span class="number">0</span>,<span class="number">1</span>,<span class="number">11</span>,<span class="number">0</span>,<span class="number">0</span>)</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'jan 01 2011,11 11:00:00'</span>)</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'Sat Jan 01 2011 11:00:00'</span>)</div><div class="line"><span class="comment">//Sat Jan 01 2011 11:00:00 GMT+0800 (中国标准时间)</span></div><div class="line"></div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'sss'</span>);</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2011/01/01T11:00:00'</span>);</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2011-01-01-11:00:00'</span>)</div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'1293879600000'</span>);</div><div class="line"><span class="comment">//Invalid Date</span></div><div class="line"></div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'2011-01-01T11:00:00'</span>)-<span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'1992/02/11 12:00:12'</span>)</div><div class="line"><span class="comment">//596069988000</span></div></pre></td></tr></table></figure>
<p>从上面几个测试结果可以很容易发现</p>
<ol>
<li><code>new Date()</code>在参数正常的情况只会返回当前时间的字符串(且是当前时区的时间)</li>
<li><code>new Date()</code>在解析一个具体的时间的时候,对参数有较严格的格式要求,格式不正确的时候会直接返回<code>Invalid Date</code>,比如将<code>number</code>类的时间戳转换成<code>string</code>类的时候也会导致解析出错</li>
<li>虽然<code>new Date()</code>的返回值是字符串,然而两个<code>new Date()</code>的结果字符串是可以直接相减的,结果为相差的毫秒数。</li>
</ol>
<p>那么,<code>new Date()</code>能接受的参数格式到底是什么标准呢?(相对于严格要求的多参数传值方法。非严格的单参数(数字日期表示格式)更常用且更容易出错,所以下文只考虑单参数数字时间字符串转换的情况)</p>
<hr>
<h2 id="new-Date-解析所支持的参数格式标准"><a href="#new-Date-解析所支持的参数格式标准" class="headerlink" title="new Date()解析所支持的参数格式标准"></a>new Date()解析所支持的参数格式标准</h2><h3 id="时间戳格式"><a href="#时间戳格式" class="headerlink" title="时间戳格式"></a>时间戳格式</h3><p>这个是最简单的也是最不容易出错的。当然唯一的缺点大概就是对开发者不直观,无法一眼看出具体日期。<br>需要注意的以下两点:</p>
<blockquote>
<ol>
<li>js内的时间戳指的是当前时间到<code>1970年1月1日00:00:00 UTC</code>对应的<strong>毫秒数</strong>,和unix时间戳不是一个概念,后者表示秒数,差了1000倍</li>
<li><code>new Date(timestamp)</code>中的时间戳必须是<code>number</code>格式,<code>string</code>会返回<code>Invalid Date</code>。所以比如<code>new Date('11111111')</code>这种写法是错的</li>
</ol>
</blockquote>
<h3 id="时间数字字符串格式"><a href="#时间数字字符串格式" class="headerlink" title="时间数字字符串格式"></a>时间数字字符串格式</h3><p>不大清楚这种该怎么描述,就是类似<code>YYYY/MM/DD HH:mm:SS</code>这种。下文以<code>dateString</code>代指。<br><code>new Date(dateString)</code>所支持的字符串格式需要满足<a href="http://tools.ietf.org/html/rfc2822#page-14" target="_blank" rel="external">RFC2822标准</a>或者<a href="http://www.w3.org/TR/NOTE-datetime" target="_blank" rel="external">ISO 8601标准</a><br>这两种标准对应的格式分别如下:</p>
<ol>
<li><p>RFC2822 标准日期字符串</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">YYYY/MM/DD HH:MM:SS ± timezon(时区用4位数字表示)</div><div class="line">// eg 1992/02/12 12:23:22+0800</div></pre></td></tr></table></figure>
<blockquote>
<p>RFC2822还有别的格式,不过上面这个是比较常用的(另外这标准太难啃了,实在没耐心啃完,所以也就没太深入)。RFC2822标准本身还有其他的非数字日期表达方式,不过不在这个话题讨论范围内了,略过</p>
</blockquote>
</li>
<li><p>ISO 8601标准日期字符串</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">YYYY-MM-DDThh:mm:ss ± timezone(时区用HH:MM表示)</div><div class="line"></div><div class="line">1997-07-16T08:20:30Z</div><div class="line">// “Z”表示UTC标准时区,即"00:00",所以这里表示零时区的`1997年7月16日08时20分30秒`</div><div class="line">//转换成位于东八区的北京时间则为`1997年7月17日16时20分30秒`</div><div class="line"></div><div class="line">1997-07-16T19:20:30+01:00</div><div class="line">// 表示东一区的1997年7月16日19时20秒30分,转换成UTC标准时间的话是1997-07-16T18:20:30Z</div></pre></td></tr></table></figure>
<blockquote>
<ol>
<li>日期和时间中间的<code>T</code>不可以被省略,一省略就出错。</li>
<li>虽然在chrome浏览器上时区也可以用<code>+0100</code>这种RFC2822的形式来表示,然而IE上不支持这种混搭写法,所以用ISO8601标准形式表示的时候时区要用<code>+HH:MM</code></li>
</ol>
</blockquote>
</li>
</ol>
<p>单单从格式上来说,两者的区别主要在于分隔符的不同。不过需要注意的是,ISO 8601标准的兼容性比RFC2822差得多(比如IE8和iOS均不支持前者。<del>我知道IE8很多人会无视,不过iOS也有这个坑的话,各位或多或少会谨慎点了吧?</del>),所以一般情况下建议用<code>RFC 2822</code>格式的。<br>不过需要注意的是,在未指定时区的前提下,对于只精确到<code>day</code>的日期字符串,<code>RFC 2822</code>返回结果是以<code>当前时区的零点</code>为准,而<code>ISO8601</code>返回结果则会以<code>UTC时间</code>的零点为标准进行解析。<br>例如:<br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="comment">//RFC2822:</span></div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'1992/02/13'</span>) <span class="comment">//Thu Feb 13 1992 00:00:00 GMT+0800 (中国标准时间)</span></div><div class="line"><span class="comment">//ISO8601:</span></div><div class="line"><span class="keyword">new</span> <span class="built_in">Date</span>(<span class="string">'1992-02-13'</span>) <span class="comment">//Thu Feb 13 1992 08:00:00 GMT+0800 (中国标准时间)</span></div></pre></td></tr></table></figure></p>
<p>然而上面这个只是ES5的标准而已,在ES6里这两种形式都会变成<code>当前时区的零点</code>为基准<sup><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Differences_in_assumed_time_zone" target="_blank" rel="external">1</a></sup><br><del><em>不管你们崩溃没,反正我是已经想死了</em></del><br>关于跨浏览器的dataString解析情况,还可以参考这个页面:<br><a href="http://dygraphs.com/date-formats.html" target="_blank" rel="external">JavaScript and Dates, What a Mess!</a></p>
<p><strong>所以对于时间字符串对象,个人意见是要么用<code>RFC2822</code>形式,要么自己写个解析函数然后随便你传啥格式进来。</strong></p>
<hr>
<h2 id="时间格式化函数的效率"><a href="#时间格式化函数的效率" class="headerlink" title="时间格式化函数的效率"></a>时间格式化函数的效率</h2><p>这里的<code>时间格式化</code>值得是将时间字符串转换成毫秒数的过程。js原生的时间格式化函数有<code>Date.parse</code>、<code>Date.prototype.valueOf</code>、<code>Date.prototype.getTime</code>、<code>Number(Date)</code>、<code>+Date</code>(还有个<code>Date.UTC</code>方法,然而对参数要求严格,不能直接解析日期字符串,所以略过)<br>这5个函数从功能上来说一模一样,但是具体的效率如何呢?我写了个检测页面,诸位也可以自己测试下。</p>
<p></p><p data-height="268" data-theme-id="0" data-slug-hash="NqeZag" data-default-tab="result" data-user="chitanda" class="codepen">See the Pen <a href="http://codepen.io/chitanda/pen/NqeZag/" target="_blank" rel="external">efficiency-of-time-format-function</a> by chitanda (<a href="http://codepen.io/chitanda" target="_blank" rel="external">@chitanda</a>) on <a href="http://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>
<h3 id="核心测试函数:"><a href="#核心测试函数:" class="headerlink" title="核心测试函数:"></a>核心测试函数:</h3><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"> <span class="function"><span class="keyword">function</span> <span class="title">test</span>(<span class="params">dateString,times,func</span>)</span>{</div><div class="line"> <span class="keyword">var</span> startTime=<span class="built_in">window</span>.performance.now();</div><div class="line"> <span class="comment">// console.log('start='+startTime.getTime());</span></div><div class="line"> <span class="keyword">for</span> (<span class="keyword">var</span> i = <span class="number">0</span>; i < times; i++) {</div><div class="line"> func(dateString);<span class="comment">//这里填写具体的解析函数</span></div><div class="line"> };</div><div class="line"> <span class="keyword">var</span> endTime=<span class="built_in">window</span>.performance.now();</div><div class="line"> <span class="comment">// console.log('endTime='+endTime.getTime());</span></div><div class="line"> <span class="keyword">var</span> gapTime=endTime-startTime;</div><div class="line"> <span class="built_in">console</span>.log(<span class="string">'一共耗时:'</span>+gapTime+<span class="string">'ms'</span>);</div><div class="line"> <span class="comment">// console.log('时间字符串'+dateString);</span></div><div class="line"> <span class="keyword">return</span> gapTime;</div><div class="line">}</div></pre></td></tr></table></figure>
<blockquote>
<p>之所以这里用<code>window.performance.now()</code>而不用<code>new Date()</code>,是因为前者精确度远比后者高。后者只能精确到ms。会对结果造成较大影响</p>
</blockquote>
<h3 id="测试结果:"><a href="#测试结果:" class="headerlink" title="测试结果:"></a>测试结果:</h3><p>单次执行50W次时间格式化函数,并重复测试100次,最后的结果如下:<br>(表格中的数字为单次执行50W次函数的平均结果。单位为毫秒)</p>
<table>
<thead>
<tr>
<th style="text-align:center">函数</th>
<th style="text-align:center">chrome</th>
<th style="text-align:center">IE</th>
<th style="text-align:center">Firefox</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">Date.parse()</td>
<td style="text-align:center">151.2087</td>
<td style="text-align:center">55.5811</td>
<td style="text-align:center">315.0446</td>
</tr>
<tr>
<td style="text-align:center">Date.prototype.getTime()</td>
<td style="text-align:center">19.5452</td>
<td style="text-align:center">21.3423</td>
<td style="text-align:center">14.0169</td>
</tr>
<tr>
<td style="text-align:center">Date.prototype.valueOf()</td>
<td style="text-align:center">20.1696</td>
<td style="text-align:center">21.7192</td>
<td style="text-align:center">13.8096</td>
</tr>
<tr>
<td style="text-align:center">+Date()</td>
<td style="text-align:center">20.0044</td>
<td style="text-align:center">31.3511</td>
<td style="text-align:center">22.7861</td>
</tr>
<tr>
<td style="text-align:center">Number(Date)</td>
<td style="text-align:center">23.0900</td>
<td style="text-align:center">24.8838</td>
<td style="text-align:center">23.3775</td>
</tr>
</tbody>
</table>
<p>从这个表格可以很容易得出以下结论:</p>
<blockquote>
<ol>
<li>从计算效率上来说,<code>Date.prototype.getTime()</code>≈<code>Date.prototype.valueOf()</code>><br><code>+Date</code>≈<code>Number(Date)</code>>><code>Date.parse()</code></li>
<li>从代码书写效率上来说,对于少量的时间格式化计算,用<code>+Date()</code>或者<code>Number(Date)</code>即可。而若页面内有大量该处理,则建议用Date原生的函数<code>Date.prototype.getTime()</code>或者<code>Date.prototype.valueOf()</code>.只有<code>Date.parse</code>,找不到任何使用的理由。</li>
<li>这个结果和计算机的计算性能以及浏览器有关,所以具体数字可能会有较大偏差,很正常。然而几个函数结果的时间差大小顺序并不会变。</li>
<li>codepen的在线demo限制比较大,对于这个测验个人建议最好将源代码复制到本地文件然后进行测试</li>
</ol>
</blockquote>
<hr>
<h2 id="UTC,GMT时间的区别"><a href="#UTC,GMT时间的区别" class="headerlink" title="UTC,GMT时间的区别"></a>UTC,GMT时间的区别</h2><p>这个不是啥重要东西,单纯当课外知识吧。</p>
<h3 id="格林威治标准时间GMT"><a href="#格林威治标准时间GMT" class="headerlink" title="格林威治标准时间GMT"></a>格林威治标准时间GMT</h3><p>GMT即「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.),指位于英国伦敦郊区的皇家格林威治天文台的标准时间,因为本初子午线被定义为通过那里的经线。<strong>然而由于地球的不规则自转,导致GMT时间有误差,因此目前已不被当作标准时间使用。</strong></p>
<h3 id="世界协调时间UTC"><a href="#世界协调时间UTC" class="headerlink" title="世界协调时间UTC"></a>世界协调时间UTC</h3><p>UTC是最主要的世界时间标准,是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间。UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。<strong>不过日常使用中,GMT与UTC的功能与精确度是没有差别的。</strong><br>协调世界时区会使用“Z”来表示。而在航空上,所有使用的时间划一规定是协调世界时。而且Z在无线电中应读作“Zulu”(可参见北约音标字母),协调世界时也会被称为“Zulu time”。</p>
<h2 id="浏览器获取用户当前时间以及喜好语言"><a href="#浏览器获取用户当前时间以及喜好语言" class="headerlink" title="浏览器获取用户当前时间以及喜好语言"></a>浏览器获取用户当前时间以及喜好语言</h2><p>首先需要注意一点,浏览器获取当前用户所在的时区等信息只和系统的<code>日期和时间</code>设置里的时区以及时间有关。<code>区域和语言</code>设置影响的是浏览器默认时间函数(Date.prototype.toLocaleString等)显示的格式,不会对时区等有影响。以window为例,<code>控制面板\时钟、语言和区域</code>中的两个子设置项目的区别如下:</p>
<blockquote>
<p><code>日期和时间</code>:设置当前用户所处的时间和时区,浏览器获取到的结果以此为准,哪怕用户的设置时间和时区是完全错误的。比如若东八区的用户将自己的时区设置为东9区,浏览器就会将视为东9区;时间数据上同理。这里的设置会影响<code>Date.prototype.getTimezoneOffset</code>、<code>new Date()</code>的值<br><code>区域和语言</code>:主要是设置系统默认的时间显示方式。其子设置的<code>格式</code>会影响<code>Date.prototype.toLocaleString</code>方法返回的字符串结果</p>
</blockquote>
<h3 id="浏览器判断用户本地字符串格式"><a href="#浏览器判断用户本地字符串格式" class="headerlink" title="浏览器判断用户本地字符串格式"></a>浏览器判断用户本地字符串格式</h3><p>Date有个<code>Date.prototype.toLocaleString()</code>方法可以将时间字符串返回用户本地字符串格式,这个方法还有两个子方法<code>Date.prototype.toLocaleDateString</code>和<code>Date.prototype.toLocaleTimeString</code>,这两个方法返回值分别表示<code>日期</code>和<code>时间</code>,加一起就是<code>Date.prototype.toLocaleString</code>的结果。<br>这个方法的默认参数会对时间字符串做一次转换,将其转换成用户当前所在时区的时间,并按照对应的系统设置时间格式返回字符串结果。<strong>然而不同浏览器对用户本地所使用的语言格式的判断依据是不同的。</strong><br>IE:获取系统当前的<code>区域和语言</code>-<code>格式</code>中设置的格式,依照其对应的格式来显示当前时间结果;<strong>IE浏览器实时查询该系统设置</strong>(即你在浏览器窗口打开后去更改系统设置也会引起返回格式变化)<br>FF:获取方式和结果与IE浏览器相同,区别在于FF只会在浏览器进程第一次启动的时候获取一次系统设置,中间不管怎么系统设置怎么变化,FF都无法获取到当前系统设置。除非重启FF浏览器。<br>Chrome:获取方式和以上两个都不同。chrome无视系统的<code>区域和语言</code>-<code>格式</code>格式,只依照自己浏览器的界面设置的菜单语言来处理。(比如英文界面则按系统’en-US’格式返回字符串,中文界面则按系统’zh-CN’格式返回结果)<br>综上可得:</p>
<blockquote>
<p>chrome下<strong>浏览器语言设置优先系统语言设置。</strong>而IE和FF则是<strong>系统语言设置优先浏览器语言设置</strong>,不管浏览器界面语言是什么,他们只依照系统设置来返回格式。(没有MAC,所以不知道safari是啥情况,等以后看情况补充吧)<br>另外,不同浏览器对<code>toLocaleString</code>返回的结果也是不同的,IE浏览器严格遵守系统设置,而chrome和FF会有自己内置的格式来替换。</p>
</blockquote>
<h3 id="浏览器界面语言设置和语言设置的区别"><a href="#浏览器界面语言设置和语言设置的区别" class="headerlink" title="浏览器界面语言设置和语言设置的区别"></a>浏览器界面语言设置和语言设置的区别</h3><p>这小节貌似有点跑题,然而不说明下的很容易和上面提到的浏览器设置的语言混淆,所以也拿出来说一下。<br>需要注意<strong>浏览器的语言设置和界面语言设置不是一回事</strong>。<br><code>浏览器的语言设置</code>设置的是浏览器发送给服务器的<code>Request Header</code>里的<code>Accept-Language</code>的值,这个值可以告诉服务器用户的喜好语言,对于某些跨国网站,服务器可以以此为依旧来返回对应语言的页面(不过实际应用上这个限制比较大,大部分网站还是根据IP来判断用户来源的,或者直接让用户自己选择)<br>对于各大浏览器而言,这个设置的更改也是比较显性,容易找到的。<br>IE: <code>Internet选项</code>-<code>语言</code><br>FF: <code>选项</code>-<code>内容</code>-<code>语言</code><br>chrome:<code>设置</code>-<code>显示高级设置</code>-<code>语言</code>-<code>语言和输入设置...</code><br>上面这里的设置不会影响到浏览器的界面语言设置,以国内大部分用户而言,即不管你怎么设置这里的语言选项,浏览器菜单等默认都会是以中文显示的.<br>而<code>浏览器的界面语言设置</code>一般来说则藏的深得多,没那么容易找到。<br>IE:<br>卸载前面安装过的浏览器语言包,去微软官网下载对应的<a href="http://www.microsoft.com/en-us/download/details.aspx?id=40904" target="_blank" rel="external">IE浏览器语言包</a>安装。(和安装的语言包有关。系统界面语言和该语言包相同的情况下,变为该语言。否则以安装的语言包为准。)<br>FF:地址栏输入<code>about:config</code>,然后找到<code>general.useragent.locale</code>字段,修改对应字段即可。<br>chrome:<code>设置</code>-<code>显示高级设置</code>-<code>语言</code>-<code>语言和输入设置...</code></p>
<h3 id="利用js获取用户浏览器语言喜好"><a href="#利用js获取用户浏览器语言喜好" class="headerlink" title="利用js获取用户浏览器语言喜好"></a>利用js获取用户浏览器语言喜好</h3><p>对于获取这两种设置,js原生方法支持度都比较一般:<br>IE下的<code>navigator</code>方法有四种和<code>language</code>有关的方法,区别如下:<br>假设系统语言为 <code>ja-JP</code>,系统unicode语言为<code>zh-CN</code>日期格式为<code>nl-NL</code>,浏览器语言设置(accept-language)为<code>de</code>,浏览器界面语言为<code>en-US</code>(其他条件不变,浏览器界面语言改为<code>zh-CN</code>的时候结果也是一样),<br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="built_in">window</span>.navigator.language</div><div class="line"><span class="comment">//"nl-NL"</span></div><div class="line"><span class="built_in">window</span>.navigator.systemLanguage</div><div class="line"><span class="comment">//"zh-CN"(设置中的非unicode程序所使用语言选项)</span></div><div class="line"><span class="built_in">window</span>.navigator.userLanguage</div><div class="line"><span class="comment">//"nl-NL"</span></div><div class="line"><span class="built_in">window</span>.navigator.browserLanguage</div><div class="line"><span class="comment">//"ja-JP"(系统菜单界面语言)</span></div><div class="line"><span class="built_in">window</span>.navigator.languages</div><div class="line"><span class="comment">//undefined</span></div></pre></td></tr></table></figure></p>
<p>chrome下,当浏览器界面语言为<code>zh-CN</code>,<code>accept-language</code>首位为<code>en-US</code>的时候:<br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="built_in">window</span>.navigator.language</div><div class="line"><span class="comment">//'zh-CN'</span></div><div class="line"><span class="built_in">window</span>.navigator.languages</div><div class="line"><span class="comment">//["en-US", "en", "zh-CN", "zh", "ja", "zh-TW", "de-LI", "de", "pl"]</span></div><div class="line"><span class="comment">//当界面语言改为"en-US"时</span></div><div class="line"><span class="built_in">window</span>.navigator.language</div><div class="line"><span class="comment">//'en-US'(浏览器界面语言)</span></div></pre></td></tr></table></figure></p>
<p>FF下,当浏览器界面语言为<code>zh-CN</code>,<code>accept-language</code>首位为<code>en-US</code>的时候:<br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="built_in">window</span>.navigator.language</div><div class="line"><span class="comment">//'en-US'</span></div><div class="line"><span class="built_in">window</span>.navigator.languages</div><div class="line"><span class="comment">//["en-US", "zh-CN", "de", "zh", "en"]</span></div><div class="line"><span class="comment">//当界面语言改为"en-US",`accept-language`首位为`zh-CN`的时候</span></div><div class="line"><span class="built_in">window</span>.navigator.language</div><div class="line"><span class="comment">//'zh-CN'(`accept-language`首选值)</span></div><div class="line"><span class="built_in">window</span>.navigator.languages</div><div class="line"><span class="comment">//["zh-CN", "de", "zh", "en-US", "en"]</span></div></pre></td></tr></table></figure></p>
<blockquote>
<ol>
<li>从上面的测试结果可以很明显的发现IE浏览器的这几个函数都是获取系统信息的,无法获取到前面提到的两个浏览器层面上的设置。<br>这几个函数具体含义还有疑问的可以参考<a href="https://msdn.microsoft.com/en-us/library/ms535867.aspx" target="_blank" rel="external">MSDN官方文档</a></li>
<li><code>window.navigator.language</code>这个函数虽然三个浏览器都可以兼容,然而代表的意义完全不同。IE下该函数返回系统设置的时间显示格式所遵守的标准的地区代码;chrome下返回浏览器界面语言;FF下返回<code>accept-language</code>的首选语言值</li>
</ol>
</blockquote>
<p>由此:</p>
<blockquote>
<ol>
<li><code>浏览器设置的语言</code>即<code>accept-language</code>值,IE浏览器无法利用JS获取。chrome和FF浏览器都可以利用<code>window.navigator.languages</code>来获取,而FF还可以直接用<code>window.navigator.language</code>直接获取<code>accept-language</code>的首选语言值。<br>所以对于<code>accept-language</code>,兼容性最好的获取方法应该是利用后端,发起一个ajax请求,分析header。而不是直接js来处理。</li>
<li><code>浏览器界面语言</code>,IE和FF都无法利用js来获取,chrome可以用<code>window.navigator.language</code>来获取</li>
<li>系统级别的语言设置(系统菜单界面语言,系统设置的时间显示格式),chrome和FF都无法用JS获取到</li>
</ol>
</blockquote>
<hr>
<h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>这篇文章断断续续地写了一个多月,不过由于对<code>Date()</code>函数的掌握不足因此个人感觉其实还是思路有点乱,所以文章看起来可能稍微有点跳跃性。不过用户本地化那块内容确实用了不少心思去写,希望对看到这篇文章的人有点帮助。</p>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ol>
<li><a href="http://www.w3.org/TR/NOTE-datetime" target="_blank" rel="external">Date and Time Formats</a></li>
<li><a href="http://tools.ietf.org/html/rfc2822#page-14" target="_blank" rel="external">Date and Time Specification(RFC2822)</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#Differences_in_assumed_time_zone" target="_blank" rel="external">Date.parse()-Differences in assumed time zone</a></li>
<li><a href="http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html" target="_blank" rel="external">JavaScript and Dates, What a Mess!</a></li>
<li><a href="https://msdn.microsoft.com/en-us/library/ms535867.aspx" target="_blank" rel="external">navigator object(IE浏览器私有language函数的解析)</a></li>
</ol>
]]></content>
<summary type="html">
<p>一个多月没更新了- -偷懒中。这个东西其实很早之前就在整理了,不过后来发现自己不少地方没弄明白,然后就一直卡那边了(其实就是不想写吧),想了下反正是给自己熟悉js的原生API而已,所以也没必要太钻牛角尖,也不一定要多完整,因此就当是<code>Date()</code>函数的一个冷门知识点小补充吧。这篇文章主要讲Date()的字符串与时间戳转换以及用户时间本地化,可能内容上比较乱(不然也不会卡我一个月时间了),见谅<br>
</summary>
<category term="前端" scheme="http://chitanda.me/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="CSS" scheme="http://chitanda.me/tags/CSS/"/>
<category term="javascript" scheme="http://chitanda.me/tags/javascript/"/>
<category term="前端" scheme="http://chitanda.me/tags/%E5%89%8D%E7%AB%AF/"/>
<category term="Date" scheme="http://chitanda.me/tags/Date/"/>
</entry>
<entry>
<title>利用javascript获取并修改伪元素的值</title>
<link href="http://chitanda.me/2015/07/15/get-and-modify-pseudo-elements-value-by-javascript/"/>
<id>http://chitanda.me/2015/07/15/get-and-modify-pseudo-elements-value-by-javascript/</id>
<published>2015-07-15T07:22:16.000Z</published>
<updated>2016-08-25T15:36:11.629Z</updated>
<content type="html"><![CDATA[<p>虽然标题里写的是<code>伪元素</code>,不过这篇文章主要是说<code>::before</code>和<code>::after</code>,其余几个伪元素(<code>::first-letter</code>、<code>::first-line</code>、<code>::selection</code>等)由于没有<code>content</code>属性,所以本文一笔带过,其实方法是一样的。<br>伪元素的重点在于一个<strong>伪</strong>,虽然它们可以被浏览器渲染引擎识别并正确渲染,然而<strong>伪元素本身并不是DOM元素,</strong>所以无法被js直接操作——因此任何基于JS直接选取DOM元素的CSS更改方法对伪元素都不起作用。(JQ看似万能,这个问题上是直接就栽了。因为JQ的选择符都是基于DOM元素)关于JS和JQ选择器,可以参考这两篇文档: <a href="http://www.w3.org/TR/selectors-api/" target="_blank" rel="external">Selectors API Level 1</a>、<a href="http://api.jquery.com/category/selectors/" target="_blank" rel="external">jQuery Selectors</a><br><a id="more"></a></p>
<h2 id="获取伪元素的属性值"><a href="#获取伪元素的属性值" class="headerlink" title="获取伪元素的属性值"></a>获取伪元素的属性值</h2><p>虽然JS里没有可以直接操作伪元素的选择符,然而获取其CSS属性的方法还是有的。</p>
<h3 id="window-getComputedStyle"><a href="#window-getComputedStyle" class="headerlink" title="window.getComputedStyle"></a>window.getComputedStyle</h3><p>利用<code>window.getComputedStyle</code>方法选择到伪元素,然后利用<code>getPropertyValue</code>方法获取对应的属性的值。<br>根据<a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle" target="_blank" rel="external">MDN的文档</a>,<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">window.getComputedStyle(element[, pseudoElt]);</div></pre></td></tr></table></figure></p>
<p>此方法包含两个参数,一个是元素本身另一个是元素的伪元素。<br>js语法实例(<a href="http://codepen.io/chitanda/full/mJKZPK/" target="_blank" rel="external">完整DEMO在线链接</a>):<br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> div=<span class="built_in">document</span>.querySelector(<span class="string">'div'</span>);</div><div class="line"><span class="keyword">var</span> fontSize=<span class="built_in">window</span>.getComputedStyle(div,<span class="string">'::before'</span>).getPropertyValue(<span class="string">'font-size'</span>);<span class="comment">//获取before伪元素的字号大小</span></div></pre></td></tr></table></figure></p>
<p>关于这个方法,详解可以参考这篇文章:<br><a href="http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/" target="_blank" rel="external">获取元素CSS值之getComputedStyle方法熟悉</a></p>
<hr>
<h2 id="更改伪元素的属性值"><a href="#更改伪元素的属性值" class="headerlink" title="更改伪元素的属性值"></a>更改伪元素的属性值</h2><p><code>window.getComputedStyle</code>方法虽然可以获取到伪元素的属性值,然而根据该方法名字也知道其只能获取CSS样式,并无法更改css属性,那么如果想要用js动态更改伪元素属性值的话,该怎么处理呢?<br>思路有以下几个:</p>
<ol>
<li>js更改<code>data-*</code>属性值来更改伪元素的<code>content</code>值</li>
<li>创建多个<code>class</code>,通过切换<code>class</code>来达到改变样式的目的</li>
<li>利用CSSStyleSheet的<code>insertRule</code>方法来添加样式</li>
<li>利用内部css样式的高优先级来覆盖外部css<blockquote>
<p>以上实现思路的推荐程度<strong>依次递减</strong></p>
</blockquote>
</li>
</ol>
<h3 id="利用DOM的data-属性来更改content的值"><a href="#利用DOM的data-属性来更改content的值" class="headerlink" title="利用DOM的data-*属性来更改content的值"></a>利用DOM的<code>data-*</code>属性来更改<code>content</code>的值</h3><p><code>data-*</code>是HTML5新增的DOM元素属性,作用大致可以理解为标记。具体用法可以参考MDN的<a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes" target="_blank" rel="external">这篇文章</a>.而伪元素的<code>content</code>属性值除了常规赋值外,还有一种特殊的<code>attr()</code>方法来获取。<br>HTML:<br><figure class="highlight html"><table><tr><td class="code"><pre><div class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"test"</span> <span class="attr">data-text</span>=<span class="string">"TEXT"</span> <span class="attr">data-color</span>=<span class="string">"red"</span>></span><span class="tag"></<span class="name">div</span>></span></div></pre></td></tr></table></figure></p>
<p>CSS:<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">.test::before{</div><div class="line"> content: attr(data-text);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>结果:</p>
<p><pre><br> <div class="test" data-text="TEXT"></div><br> <style>.test::before{content: attr(data-text);}</style><br></pre><br>另外<code>content</code>其实可以多个<strong>attr</strong>连写,而且attr()内的可以是DOM元素的任意属性(比如<code>class</code>等,甚至非W3C标准属性也支持,不过不推荐这么做)所以很方便凑一些模版文字。像下面这种写法也是完全没问题的。<strong>注意用空格连接,不要用”+”号。</strong><br>EXAM:<br><figure class="highlight css"><table><tr><td class="code"><pre><div class="line"><span class="selector-class">.test</span><span class="selector-pseudo">::before</span> {</div><div class="line"> <span class="attribute">content</span>: <span class="string">'我的类是'</span> <span class="built_in">attr</span>(class) <span class="string">'想要变成'</span> <span class="built_in">attr</span>(data-color);</div><div class="line">}</div></pre></td></tr></table></figure></p>
<blockquote>
<p>虽然W3C给<code>attr()</code>赋予了<a href="http://www.w3.org/TR/css3-values/#attr-notation" target="_blank" rel="external">无限可能性</a>,包括<code>color</code>,<code>width</code>等属性在未来都有希望用这个方法更改,然而<strong>目前只有<code>content</code>支持该方法</strong>,其余的都还是草稿状态,尚未有浏览器支持。之所以把这个方法放在第一位只是因为相比别的实现手法来说,这个方法真的太简单太优雅。</p>
</blockquote>
<hr>
<p>但是如果真的想要改伪元素里的<code>color</code>等元素呢?</p>
<h3 id="更改class来实现伪元素样式的更改"><a href="#更改class来实现伪元素样式的更改" class="headerlink" title="更改class来实现伪元素样式的更改"></a>更改<code>class</code>来实现伪元素样式的更改</h3><p>把这个方法放到推荐位第二位估计会被很多人骂我:“卧槽,这么简单又没逼格的办法你竟然放到第二位!太没水平了”。不过再看完后面两种方法后或许你会对这种看法有所改观。<br>这个方法的优点是简单好用且无兼容性问题。缺点是多了一些其实用处不大的<code>class</code>,很像是jQuery类选择器中毒患者的做法;另外不适合多状态的场景(比如实时改变伪元素文字大小等)。<br>实现过于简单就不贴代码了。</p>
<hr>
<p>前面的<code>class切换大法</code>可能让人感觉不痛快,这里来个高大上(伪)点的方法:</p>
<h3 id="利用CSSStyleSheet的insertRule方法来添加样式"><a href="#利用CSSStyleSheet的insertRule方法来添加样式" class="headerlink" title="利用CSSStyleSheet的insertRule方法来添加样式"></a>利用CSSStyleSheet的<code>insertRule</code>方法来添加样式</h3><blockquote>
<p>这部分内容和W3C标准牵连比较多,加上较冷门,没多少人关注,个人目前啃不动标准,所以这部分内容不会做深入分析,理解可能也会有问题,望斧正。</p>
</blockquote>
<p>CSSStyleSheet是浏览器存放页面内所有css样式表的对象方法(不包括行内样式),每个<code>link</code>和<code>style</code>标签都代表一个CSSStyleSheet对象,获取他们可以用<code>document.styleSheets</code>方法。(需要注意的是虽然<code>styleSheets</code>方法返回的结果把<code>link</code>标签引进的外部样式也算进去了,但是非IE浏览器没办法获取到他们的<code>cssRules</code>属性,只有内嵌的<code>style</code>标签内的元素可以被获取到)</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="built_in">document</span>.styleSheets[<span class="number">0</span>].insertRule(<span class="string">'.test::before{color:green}'</span>,<span class="number">0</span>)<span class="comment">//chrome,firefox等非IE浏览器使用</span></div><div class="line"><span class="built_in">document</span>.styleSheets[<span class="number">0</span>].addRule(<span class="string">'.test::before{color:green}'</span>,<span class="number">0</span>)<span class="comment">//IE系列浏览器使用</span></div><div class="line"><span class="comment">/* 虽然部分浏览器也可以通过id来指定,'document.styleSheets.id.insertRule()'这种写法在chrome和IE下都行得通,但是firefox会返回'undefined',所以建议还是使用index值来获取stylesheet */</span></div></pre></td></tr></table></figure>
<p>.<code>insertRule</code>的语法是<code>stylesheet.insertRule(rule, index)</code>,另一个参数是<code>index</code>,意思是在对应的styleSheets里的<code>cssRules</code>样式表中的位置,这个值越大则样式优先级越高,但是值不能超过当前样式表规则(<code>cssRules</code>)长度(CSS中先定义的样式总是会被后定义的覆盖就是这个缘故。),当值小于<code>cssRules</code>长度时,添加的样式规则会插入到<code>index</code>值定义的位置,之前其余的规则依次顺延。</p>
<blockquote>
<p><code>addrule</code>和<code>insertRule</code>方法本质上没区别,只是后者不被IE浏览器识别,所以前者作为浏览器兼容方法存在。(下文为节省篇幅,以<code>insertRule</code>方法指代此两种方法。)<br>上面的代码看似简单一行,然而却不是每次都有效的。原因有以下几点:</p>
<pre><code>1. `document.styleSheets`虽然按照`style`和`link`的顺序返回对应的`StyleSheetList`,然而第一个如果是`link`而不是`style`,前面讲过此时无法获取对应的`cssRules`,则`document.styleSheets[0].cssRules`为`null`,`insertRule`方法不起作用。(此情况只针对非IE浏览器,IE浏览器正常,但是定义的早往往意味着被后面的样式覆盖,所以意义不大)
2. 同上,如果页面内没有内嵌样式的`style`标签,则`insertRule`方法也无法发挥作用。
3. `index`值不够大的话很有可能会早于css文件开始的定义位置,导致被覆盖。因此有个折衷办法就是给添加的样式增加`!important`,虽然我个人比较反感这么做。
</code></pre></blockquote>
<p>由此可见此方法的局限性,但是这种方法的优雅之处在于避免了直接写内嵌样式,而是通过css api来做更改。相比下面的方法来说,稍微好点。</p>
<hr>
<p>但是这种方法好像局限性有点大啊?</p>
<h3 id="HEAD中添加style标签强制覆盖初始属性"><a href="#HEAD中添加style标签强制覆盖初始属性" class="headerlink" title="HEAD中添加style标签强制覆盖初始属性"></a><code>HEAD</code>中添加<code>style</code>标签强制覆盖初始属性</h3><p>这个方法是利用内部css样式的高优先级来覆盖外部css,好处是简单易理解,实现简单。坏处就是吃相太难看,过于粗暴。<br><figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> style=<span class="built_in">document</span>.createElement(<span class="string">'style'</span>);</div><div class="line">style.innerHTML=<span class="string">".test::before{color:green}"</span>;<span class="comment">//添加样式内容的话也可以用上面提到过的`insertRule`,相对例子里的硬编码会更优雅点。</span></div><div class="line"><span class="built_in">document</span>.head.appendChild(style);</div></pre></td></tr></table></figure></p>
<p>看到这里可能有些人反应过来了,其实加<code>style</code>标签这种方法可以是<code>insertRule</code>实现方法的大前提——因为不是所有页面一开始都有内嵌的<code>style</code>样式的。这种方法虽然不是很好,但是有时候却又确确实实是必须的——比如“拖动滑块改变伪元素内文字大小”这个需求。</p>
<h2 id="练习"><a href="#练习" class="headerlink" title="练习"></a>练习</h2><h3 id="功能需求"><a href="#功能需求" class="headerlink" title="功能需求"></a>功能需求</h3><ol>
<li>拖动滑块改变伪元素内的文字大小</li>
<li>且伪元素内随时显示当前字号</li>
<li>通过一个按钮可以改变伪元素内文字颜色</li>
</ol>
<p>这个需求可以将本文前面提到的四种改变伪元素样式的方法都塞进去。具体实现参照DEMO,不再做具体分析:</p>
<p></p><p data-height="268" data-theme-id="0" data-slug-hash="OVBJEw" data-default-tab="result" data-user="chitanda" class="codepen">See the Pen <a href="http://codepen.io/chitanda/pen/OVBJEw/" target="_blank" rel="external">js-edit-pseudo-element-stylesheet-rules</a> by chitanda (<a href="http://codepen.io/chitanda" target="_blank" rel="external">@chitanda</a>) on <a href="http://codepen.io" target="_blank" rel="external">CodePen</a>.</p><p></p>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>
<hr>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ol>
<li><p>getComputedStyle()</p>
<ol>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle" target="_blank" rel="external">Window.getComputedStyle()</a></li>
<li><a href="http://www.zhangxinxu.com/wordpress/2012/05/getcomputedstyle-js-getpropertyvalue-currentstyle/" target="_blank" rel="external">获取元素CSS值之getComputedStyle方法熟悉</a></li>
</ol>
</li>
<li><p>attr-notation</p>
<ol>
<li><a href="http://www.w3.org/TR/css3-values/#attr-notation" target="_blank" rel="external">W3C CSS3-Attribute References: ‘attr()’</a></li>
<li><a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/attr" target="_blank" rel="external">MDN ATTR()</a></li>
</ol>
</li>
<li>CSSRules<ol>
<li><a href="http://help.dottoro.com/ljdxvksd.php" target="_blank" rel="external">CSSRule object</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule" target="_blank" rel="external">MDN insertRule</a></li>
<li><a href="http://www.w3.org/wiki/Dynamic_style_-_manipulating_CSS_with_JavaScript" target="_blank" rel="external">Dynamic style - manipulating CSS with JavaScript</a></li>
<li><a href="http://davidwalsh.name/add-rules-stylesheets" target="_blank" rel="external">Add Rules to Stylesheets with JavaScript</a></li>
<li><a href="http://pankajparashar.com/posts/modify-pseudo-elements-css/" target="_blank" rel="external">Modify pseudo element styles with JavaScript</a></li>
<li><a href="https://gist.github.com/yckart/5563717" target="_blank" rel="external">Add css-rules to an existing stylesheet</a></li>
</ol>
</li>
</ol>
]]></content>
<summary type="html">
<p>虽然标题里写的是<code>伪元素</code>,不过这篇文章主要是说<code>::before</code>和<code>::after</code>,其余几个伪元素(<code>::first-letter</code>、<code>::first-line</code>、<code>::selection</code>等)由于没有<code>content</code>属性,所以本文一笔带过,其实方法是一样的。<br>伪元素的重点在于一个<strong>伪</strong>,虽然它们可以被浏览器渲染引擎识别并正确渲染,然而<strong>伪元素本身并不是DOM元素,</strong>所以无法被js直接操作——因此任何基于JS直接选取DOM元素的CSS更改方法对伪元素都不起作用。(JQ看似万能,这个问题上是直接就栽了。因为JQ的选择符都是基于DOM元素)关于JS和JQ选择器,可以参考这两篇文档: <a href="http://www.w3.org/TR/selectors-api/">Selectors API Level 1</a>、<a href="http://api.jquery.com/category/selectors/">jQuery Selectors</a><br>
</summary>
<category term="前端" scheme="http://chitanda.me/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="CSS" scheme="http://chitanda.me/tags/CSS/"/>
<category term="javascript" scheme="http://chitanda.me/tags/javascript/"/>
<category term="前端" scheme="http://chitanda.me/tags/%E5%89%8D%E7%AB%AF/"/>
<category term="伪元素" scheme="http://chitanda.me/tags/%E4%BC%AA%E5%85%83%E7%B4%A0/"/>
<category term="W3C" scheme="http://chitanda.me/tags/W3C/"/>
</entry>
<entry>
<title>浏览器和服务器实现跨域(CORS)判定的原理</title>
<link href="http://chitanda.me/2015/07/04/the-implementation-about-CORS-achieved-by-server-and-broswer/"/>
<id>http://chitanda.me/2015/07/04/the-implementation-about-CORS-achieved-by-server-and-broswer/</id>
<published>2015-07-04T14:37:37.000Z</published>
<updated>2016-08-25T15:37:24.206Z</updated>
<content type="html"><![CDATA[<p>前端对Cross-Origin Resource Sharing 问题(CORS,中文又称’跨域’)应该很熟悉了。众所周知出于安全的考虑,浏览器有个<code>同源策略</code>,对于不同源的站点之间的相互请求会做限制(<strong>跨域限制是浏览器行为,不是服务器行为。</strong>)。不过下午想到了一个略无趣的问题:浏览器和服务器到底是如何判定有没有跨域呢?本文主要分两个部分,一是对这个问题的总结,二是nginx下如何配置服务器允许跨域。<br><a id="more"></a></p>
<h2 id="同源策略"><a href="#同源策略" class="headerlink" title="同源策略"></a>同源策略</h2><blockquote>
<p>同源指的是域名(或IP),协议,端口都相同,不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对方的资源。</p>
</blockquote>
<p><a href="https://en.wikipedia.org/wiki/Same-origin_policy" target="_blank" rel="external">同源的判定:</a><br>以<code>http://www.example.com/dir/page.html</code>为例,以下表格指出了不同形式的链接是否与其同源:(原因里未申明不同的属性即说明其与例子里的原链接对应的属性相同)</p>
<table>
<thead>
<tr>
<th style="text-align:left">链接</th>
<th style="text-align:center">结果</th>
<th style="text-align:left">原因</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><a href="1">http:// <strong><code>www.example.com</code></strong> /dir/page2.html</a></td>
<td style="text-align:center"><strong><code>是</code></strong></td>
<td style="text-align:left">同协议同域名同端口</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http:// <strong><code>www.example.com</code></strong> /dir2/other.html</a></td>
<td style="text-align:center"><strong><code>是</code></strong></td>
<td style="text-align:left">同协议同域名同端口</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http://user:pwd@ <strong><code>www.example.com</code></strong>/dir2/other.html</a></td>
<td style="text-align:center"><strong><code>是</code></strong></td>
<td style="text-align:left">同协议同域名同端口</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http://www.example.com: <strong><code>81</code></strong>/dir/other.html</a></td>
<td style="text-align:center">否</td>
<td style="text-align:left">端口不同</td>
</tr>
<tr>
<td style="text-align:left"><a href="1"> <strong><code>https</code></strong>://www.example.com/dir/other.html</a></td>
<td style="text-align:center">否</td>
<td style="text-align:left">协议不同端口不同</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http:// <strong><code>en.example.com</code></strong>/dir/other.html</a></td>
<td style="text-align:center">否</td>
<td style="text-align:left">域名不同</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http:// <strong><code>example.com</code></strong>/dir/other.html</a></td>
<td style="text-align:center">否</td>
<td style="text-align:left">域名不同(要求精确匹配)</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http:// <strong><code>v2.www.example.com</code></strong>/dir/other.html</a></td>
<td style="text-align:center">否</td>
<td style="text-align:left">域名不同(要求精确匹配)</td>
</tr>
<tr>
<td style="text-align:left"><a href="1">http://www.example.com: <strong><code>80</code></strong>/dir/other.html</a></td>
<td style="text-align:center"><strong><code>不确定</code></strong></td>
<td style="text-align:left">取决于浏览器的实现方式</td>
</tr>
</tbody>
</table>
<h2 id="是否允许跨域的判定"><a href="#是否允许跨域的判定" class="headerlink" title="是否允许跨域的判定"></a>是否允许跨域的判定</h2><p>前文提到了同源策略的判定,然而同源策略在加强了安全的同时,对开发却是极大的不便利。因此开发者们又发明了很多办法来允许数据的跨域传输(常见的办法有<code>JSONP</code>、<code>CORS</code>)。当域名不同源的时候,由于跨域实现的存在,浏览器不能直接根据域名来判定跨域限制。那么浏览器具体又是如何实现判定的呢?看下面的例子。</p>
<h3 id="环境说明"><a href="#环境说明" class="headerlink" title="环境说明"></a>环境说明</h3><ol>
<li>参与实验的前端域名三个有:<code>http://www.zhihu.com</code>、<code>http://segmentfault.com</code>、<br><code>http://localhost</code>。</li>
<li>请求的服务器端地址为<code>http://localhost/city.json</code>,服务器解析引擎使用的<code>nginx</code>,且服务器只配置了允许来自<code>http://segmentfault.com</code>的跨域请求</li>
<li>检测方法:在各个域名下利用chrome浏览器的<code>console</code>界面模拟发送ajax请求,代码如下: <figure class="highlight javascript"><table><tr><td class="code"><pre><div class="line"><span class="keyword">var</span> xhr = <span class="keyword">new</span> XMLHttpRequest();</div><div class="line">xhr.open(<span class="string">'GET'</span>, <span class="string">'http://localhost/city.json'</span>,<span class="literal">true</span>);</div><div class="line">xhr.send();</div></pre></td></tr></table></figure>
</li>
</ol>
<h3 id="实验过程"><a href="#实验过程" class="headerlink" title="实验过程"></a>实验过程</h3><ol>
<li><p>在<code>http://localhost</code>域名下,<strong>请求成功。</strong><br> 服务器回应的http文件头如下:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">HTTP/1.1 200 OK</div><div class="line">Server: nginx/1.6.2</div><div class="line">Date: Sun, 05 Jul 2015 17:44:06 GMT</div><div class="line">Content-Type: application/octet-stream</div><div class="line">Content-Length: 2084</div><div class="line">Last-Modified: Sat, 18 Apr 2015 06:20:12 GMT</div><div class="line">Connection: keep-alive</div><div class="line">ETag: "5531f79c-824"</div><div class="line">Access-Control-Allow-Credentials: true</div><div class="line">Access-Control-Allow-Methods: GET, POST, OPTIONS</div><div class="line">Accept-Ranges: bytes</div></pre></td></tr></table></figure>
</li>
<li><p>在<code>http://segmentfault.com</code>域名下,<strong>请求成功</strong><br> 服务器回应的http文件头如下:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">HTTP/1.1 200 OK</div><div class="line">Server: nginx/1.6.2</div><div class="line">Date: Sun, 05 Jul 2015 18:17:27 GMT</div><div class="line">Content-Type: application/octet-stream</div><div class="line">Content-Length: 2084</div><div class="line">Last-Modified: Sat, 18 Apr 2015 06:20:12 GMT</div><div class="line">Connection: keep-alive</div><div class="line">ETag: "5531f79c-824"</div><div class="line">**Access-Control-Allow-origin: http://segmentfault.com**</div><div class="line">Access-Control-Allow-Credentials: true</div><div class="line">Access-Control-Allow-Methods: GET, POST, OPTIONS</div><div class="line">Accept-Ranges: bytes</div></pre></td></tr></table></figure>
</li>
<li><p>在<code>http://www.zhihu.com</code>下,<strong>请求失败</strong><br><strong>虽然都是失败,但是返回的HTTP文件头内容会视服务器是否有配置跨域请求而发生变化</strong><br> ####服务器允许跨域请求####<br> (仅允许来自<code>http://segmentfault.com</code>的跨域请求)<br> console.log窗口提示:</p>
<blockquote>
<p> XMLHttpRequest cannot load <a href="http://localhost/city.json" target="_blank" rel="external">http://localhost/city.json</a>. The ‘Access-Control-Allow-Origin’ header has a value ‘<a href="http://segmentfault.com" target="_blank" rel="external">http://segmentfault.com</a>‘ that is not equal to the supplied origin. Origin ‘<a href="http://www.zhihu.com" target="_blank" rel="external">http://www.zhihu.com</a>‘ is therefore notallowed access.</p>
</blockquote>
<p> 服务器回应的http文件头如下:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">HTTP/1.1 200 OK</div><div class="line">Server: nginx/1.6.2</div><div class="line">Date: Sun, 05 Jul 2015 17:59:25 GMT</div><div class="line">Content-Type: application/octet-stream</div><div class="line">Content-Length: 2084</div><div class="line">Last-Modified: Sat, 18 Apr 2015 06:20:12 GMT</div><div class="line">Connection: keep-alive</div><div class="line">ETag: "5531f79c-824"</div><div class="line">Access-Control-Allow-origin: http://segmentfault.com</div><div class="line">Access-Control-Allow-Credentials: true</div><div class="line">Access-Control-Allow-Methods: GET, POST, OPTIONS</div><div class="line">Accept-Ranges: bytes</div></pre></td></tr></table></figure>
<p> ####服务器不允许任何跨域请求####<br> console.log窗口提示:</p>
<blockquote>
<p>XMLHttpRequest cannot load <a href="http://localhost/city.json" target="_blank" rel="external">http://localhost/city.json</a>. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘<a href="http://www.zhihu.com" target="_blank" rel="external">http://www.zhihu.com</a>‘ is therefore not allowed access.</p>
</blockquote>
<p> 服务器回应的http文件头如下:</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">HTTP/1.1 200 OK</div><div class="line">Server: nginx/1.6.2</div><div class="line">Date: Sun, 05 Jul 2015 17:51:29 GMT</div><div class="line">Content-Type: application/octet-stream</div><div class="line">Content-Length: 2084</div><div class="line">Last-Modified: Sat, 18 Apr 2015 06:20:12 GMT</div><div class="line">Connection: keep-alive</div><div class="line">ETag: "5531f79c-824"</div><div class="line">Access-Control-Allow-Credentials: true</div><div class="line">Access-Control-Allow-Methods: GET, POST, OPTIONS</div><div class="line">Accept-Ranges: bytes</div></pre></td></tr></table></figure>
</li>
</ol>
<p>###跨域的判定流程###<br>从<code>zhihu</code>页面的两次浏览器报错以及<code>segmentfault</code>的成功返回值来看,可以很容易得出浏览器和服务器的合作判定步骤如下:</p>
<blockquote>
<ol>
<li>浏览器先根据同源策略对前端页面和后台交互地址做匹配,若同源,则直接发送数据请求;若不同源,则发送跨域请求。</li>
<li>服务器解析程序收到浏览器跨域请求后,根据自身配置返回对应文件头。若未配置过任何允许跨域,则文件头里不包含<code>Access-Control-Allow-origin</code>字段,若配置过域名,则返回<code>Access-Control-Allow-origin</code>+ <code>对应配置规则里的域名的方式</code>。</li>
<li>浏览器根据接受到的http文件头里的<code>Access-Control-Allow-origin</code>字段做匹配,若无该字段,说明不允许跨域;若有该字段,则对字段内容和当前域名做比对,如果同源,则说明可以跨域,浏览器发送该请求;若不同源,则说明该域名不可跨域,不发送请求<br>(但是不能仅仅根据服务器返回的文件头里是否包含<code>Access-Control-Allow-origin</code>来判断其是否允许跨域,因为服务器端配置多域名跨域的时候,也会出现不能跨域的域名返回包里没有<code>Access-Control-Allow-origin</code>字段的情况。下文配置说明里会讲。)</li>
</ol>
</blockquote>
<h2 id="配置服务器实现跨域传输"><a href="#配置服务器实现跨域传输" class="headerlink" title="配置服务器实现跨域传输"></a>配置服务器实现跨域传输</h2><p>前面讲到了同源策略的基本判定,以及浏览器实现跨域判断的方式,那么,如何在服务器端做配置来允许跨域传输呢?下文将以Nginx为例,讲一下三种情况下的配置。</p>
<h3 id="配置项解析"><a href="#配置项解析" class="headerlink" title="配置项解析"></a>配置项解析</h3><p>CORS常用的配置项有以下几个:</p>
<blockquote>
<ul>
<li><strong>Access-Control-Allow-Origin</strong>(必含) – 允许的域名,<strong>只能填通配符或者单域名</strong></li>
<li><strong>Access-Control-Allow-Methods</strong>(必含) – 这允许跨域请求的http方法(常见有<code>POST</code>、<code>GET</code>、<code>OPTIONS</code>)</li>
<li><strong>Access-Control-Allow-Headers</strong>(当预请求中包含Access-Control-Request-Headers时必须包含) – 这是对预请求当中Access-Control-Request-Headers的回复,和上面一样是以逗号分隔的列表,可以返回所有支持的头部。</li>
<li><strong>Access-Control-Allow-Credentials</strong>(可选) – 该项标志着请求当中是否包含cookies信息,只有一个可选值:true(必为小写)。如果不包含cookies,请略去该项,而不是填写false。这一项与XmlHttpRequest2对象当中的withCredentials属性应保持一致,即withCredentials为true时该项也为true;withCredentials为false时,省略该项不写。反之则导致请求失败。</li>
<li><strong>Access-Control-Max-Age</strong>(可选) – 以秒为单位的缓存时间。预请求的的发送并非免费午餐,允许时应当尽可能缓存。</li>
</ul>
</blockquote>
<h3 id="具体配置举例"><a href="#具体配置举例" class="headerlink" title="具体配置举例"></a>具体配置举例</h3><h4 id="全域名或者单域名允许跨域"><a href="#全域名或者单域名允许跨域" class="headerlink" title="全域名或者单域名允许跨域"></a>全域名或者单域名允许跨域</h4><p>这个最省心<br>打开Nginx的配置文件(默认为<code>nginx.conf</code>)。找到对应域名设置的<code>local</code>配置部分。<br>添加以下内容:<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">add_header 'Access-Control-Allow-origin' 'http://www.example.com';</div><div class="line">add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';</div></pre></td></tr></table></figure></p>
<blockquote>
<p>添加的域名必须带<code>http://</code>协议头(否则服务器无法区分是http还是https),如果接受所有域名的跨域请求,则可以用<code>*</code>(安全性有问题,不推荐)</p>
</blockquote>
<h4 id="添加多域名跨域配置"><a href="#添加多域名跨域配置" class="headerlink" title="添加多域名跨域配置"></a>添加多域名跨域配置</h4><p>如果允许跨域的域名有多个但出于安全问题又不想配置全域名通配的时候,就可以用到nginx里的<code>if</code>判断了。<br>添加如下内容:<br><figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">if ($http_origin = 'http://segmentfault.com' ) { </div><div class="line"> add_header 'Access-Control-Allow-Origin' "$http_origin";</div><div class="line"> }</div><div class="line">if ($http_origin = 'http://localhost:4000' ) { </div><div class="line"> add_header 'Access-Control-Allow-Origin' "$http_origin";</div><div class="line"> }</div><div class="line"> add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';</div></pre></td></tr></table></figure></p>
<blockquote>
<ul>
<li>如果对正则比较熟悉的,可以直接用正则来匹配条件判断,不需要用if这么麻烦的方式。</li>
<li>‘Access-Control-Allow-Methods’ 允许多参数,’Access-Control-Allow-origin’不允许多参数,所以只能是条件语句判断要不要加这个。这也是我前面提到的为什么即使HTTP文件头返回值里没有’Access-Control-Allow-origin’,也不能说明它就是不允许跨域的。</li>
<li>nginx配置文件的<code>http</code>配置部分不能用<code>if</code>条件语句,所以多域名的时候必须加在<code>local</code>部分内。另外加在<code>local</code>内的只对对应的服务器域名做跨域请求的配置,加在<code>http</code>里会让跑在该nginx下的所有网站都统一采取这种配置。</li>
<li><code>Access-Control-Allow-Origin</code>也可以改成全小写的形式,不影响结果.(<code>access-control-allow-origin</code>也可以)</li>
</ul>
</blockquote>
<p>PS:<br>这篇文章写的可能有点绕,另外由于运维方面和WEB安全方面不是特别熟悉,所以后面配置那里未必是最优解,恳请看到的各位指点。</p>
<h2 id="参考文献"><a href="#参考文献" class="headerlink" title="参考文献"></a>参考文献</h2><ol>
<li><a href="https://en.wikipedia.org/wiki/Same-origin_policy" target="_blank" rel="external">Same-origin policy</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS" target="_blank" rel="external">HTTP access control (CORS)</a></li>
<li><a href="http://www.html5rocks.com/en/tutorials/cors/" target="_blank" rel="external">Using CORS</a></li>
<li><a href="http://newhtml.net/using-cors/" target="_blank" rel="external">利用CORS实现跨域请求</a> (是参考文献2的中译版,配置参数解析那里有所参考)</li>
<li><a href="http://enable-cors.org/" target="_blank" rel="external">enable cross-origin resource sharing</a></li>
</ol>
]]></content>
<summary type="html">
<p>前端对Cross-Origin Resource Sharing 问题(CORS,中文又称’跨域’)应该很熟悉了。众所周知出于安全的考虑,浏览器有个<code>同源策略</code>,对于不同源的站点之间的相互请求会做限制(<strong>跨域限制是浏览器行为,不是服务器行为。</strong>)。不过下午想到了一个略无趣的问题:浏览器和服务器到底是如何判定有没有跨域呢?本文主要分两个部分,一是对这个问题的总结,二是nginx下如何配置服务器允许跨域。<br>
</summary>
<category term="运维" scheme="http://chitanda.me/categories/%E8%BF%90%E7%BB%B4/"/>
<category term="运维" scheme="http://chitanda.me/tags/%E8%BF%90%E7%BB%B4/"/>
<category term="nginx" scheme="http://chitanda.me/tags/nginx/"/>
<category term="前端" scheme="http://chitanda.me/tags/%E5%89%8D%E7%AB%AF/"/>
<category term="跨域" scheme="http://chitanda.me/tags/%E8%B7%A8%E5%9F%9F/"/>
</entry>
<entry>
<title>利用DigitalOcean中转大文件</title>
<link href="http://chitanda.me/2015/07/03/transfer-big-file-by-digitalocean/"/>
<id>http://chitanda.me/2015/07/03/transfer-big-file-by-digitalocean/</id>
<published>2015-07-03T03:36:54.000Z</published>
<updated>2016-08-25T15:39:09.660Z</updated>
<content type="html"><![CDATA[<p>声明:本文基于<strong>Ubuntu 14.04 x64</strong>,由于本人自身对linux的掌握仅仅是初级阶段,所以本文只记录操作指令流程,不做具体分析。其中大部分操作指令来自google搜索结果,所以这篇文章些地方理解或有错误,恳请指正。</p>
<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>昨天有朋友让他帮他从海外ftp拖一个16G的文件,由于国内直连速度实在太渣,加上ftp网站那边权限限制较严格,无法使用目前已有的大部分公网离线服务,也不能用第三方FTP客户端下载,只能通过浏览器下载。所以我就自己用DO转了下,上传到国内的百度云,做个记录。方便下次使用。<br><strong>本文适用场景:下载链接不固定且只能通过浏览器下载的文件。</strong><br><a id="more"></a></p>
<hr>
<h2 id="需要的软件"><a href="#需要的软件" class="headerlink" title="需要的软件"></a>需要的软件</h2><ol>
<li>xrdp(假设文件所在站点权限验证严格,无法用curl直接下载,必须通过浏览器)</li>
<li>Firefox浏览器(chrome浏览器默认不能在root下运行,配置较比较麻烦)</li>
<li>rar(其他压缩软件都没有<strong>恢复记录</strong>功能。当然这里如果对网速和RP有信心的话也可以直接FTP传回来。不过有一定几率坏档,所以不推荐)</li>
<li>bcloud(linux下百度云的非官方客户端。也可以用<a href="https://github.com/houtianze/bypy" target="_blank" rel="external">bypy</a>,不过后者没有gui,配置相对麻烦)</li>
</ol>
<hr>
<p>##操作过程##<br>DO上建立VPS并利用终端连接等前略过程省略。从进入VPS系统开始。</p>
<p>###安装远程桌面###<br>中间可能要输密码,确认等,自行根据shell显示的指令输入即可,这段内容参考了<a href="http://c-nergy.be/blog/?p=5305" target="_blank" rel="external">Ubuntu 14.04 – How to install xrdp in Ubuntu 14.04</a>。以下命令均在本机shell终端下执行(putty等)</p>
<ol>
<li><p>安装XRDP包</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">sudo apt-get install xrdp</div></pre></td></tr></table></figure>
</li>
<li><p>安装xfce4桌面环境</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">sudo apt-get update</div><div class="line">sudo apt-get install xfce4</div></pre></td></tr></table></figure>
</li>
<li><p>配置xrdp使用xfce桌面</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">echo xfce4-session >~/.xsession</div><div class="line">sudo service xrdp restart</div></pre></td></tr></table></figure>
</li>
</ol>
<blockquote>
<p>此时远程桌面已经可以用了,windows打开<strong>远程桌面连接</strong>,输入ip和linux的用户名(DO默认是<code>root</code>)然后登录即可。</p>
</blockquote>
<h3 id="安装Firefox"><a href="#安装Firefox" class="headerlink" title="安装Firefox"></a>安装Firefox</h3><p>由于DO的vps默认是root帐户登录,而出于安装考虑,chrome不能在root账户下运行,所以改用Firefox。</p>
<ol>
<li>apt源安装Firefox <figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">sudo apt-get update</div><div class="line">sudo apt-get --purge --reinstall install firefox</div></pre></td></tr></table></figure>
</li>
</ol>
<blockquote>
<p>安装完成后可以切换到远程桌面,在左上角的<code>Applications Menu</code>><code>Internet</code>下可以看到Firefox了。打开之后即可使用。(这里的Firefox对非拉丁文的支持不好,不会显示字符。猜测是xfce的问题,不过不是很影响使用,所以略过不提)</p>
</blockquote>
<h3 id="打包文件"><a href="#打包文件" class="headerlink" title="打包文件"></a>打包文件</h3><p>略过在远程桌面内用Firefox下载等一系列过程,现在假设文件已经下载到vps了,需要压缩了。</p>
<blockquote>
<p>上传之前建议用rar打包,理由如下:</p>
<ol>
<li><strong>文件大,直接传容易坏档。</strong>压缩包可以保证文件不坏(能解压出来就证明和源文件一样,解压不了的话就说明压缩包坏了,重下一部分即可)</li>
<li><strong>rar可以加恢复记录。</strong> 之所以用rar而不是zip、7z等,主要原因在于出现部分压缩包坏档的情况下,恢复记录有很大的可能可以避免重复下载。而目前流行的压缩软件里,<strong>只有rar可以加恢复记录</strong>(当然要是网速快硬盘大那当我没说。你随意)<br>DO自带ubuntu源可能不是很多,无法用<code>apt</code>方式安装,所以下文用比较原始的编译安装方法。以<code>WinRAR 5.21 64位</code>为例</li>
</ol>
</blockquote>
<ol>
<li><p>下载安装包</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">wget http://www.rarlab.com/rar/rarlinux-x64-5.2.1.tar.gz</div></pre></td></tr></table></figure>
</li>
<li><p>解压</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">tar -xzvf rarlinux-x64-5.2.1.tar.gz</div></pre></td></tr></table></figure>
</li>
<li><p>编译安装</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">cd rar</div><div class="line">make</div><div class="line">sudo make install</div></pre></td></tr></table></figure>
</li>
<li><p>压缩文件<br> 进入文件下载目录(默认为<code>~/Downloads</code>),并执行以下代码</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">rar a -v1000m -m3 -rr3% -t 'output'</div></pre></td></tr></table></figure>
<blockquote>
<p>linux下的rar的语法和windows下的一样。上面的指令意思是`将当前文件夹下的全部文件以默认压缩比添加到“output.rar”文件下,1000M每个分卷,并设置恢复记录为3%,压缩完成后测试文件。<strong>outpu文件不需要加’.rar’后缀</strong><br>由于默认Downloads文件夹下只有一个下载文件,所以上面的指令一般情况下也是可以的,但是如果文件夹下文件比较多的情况,可能需要排除或者指定只添加某个文件,所以贴两个可能用处较大的指令,其余的可以自行借助搜索引擎</p>
<ol>
<li><p>只添加文件夹下指定文件。</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">rar a -n'你要压缩的文件1' -n'你要压缩的文件2' 'output'</div></pre></td></tr></table></figure>
</li>
<li><p>排除文件夹下的指定文件</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">rar a -x'你要排除的文件1' -x'你要排除的文件2' 'output'</div></pre></td></tr></table></figure>
</li>
<li><p>列出压缩包内的文件</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">rar l '你要查看的rar文件'</div></pre></td></tr></table></figure>
</li>
</ol>
</blockquote>
</li>
</ol>
<h3 id="上传文件到百度云"><a href="#上传文件到百度云" class="headerlink" title="上传文件到百度云"></a>上传文件到百度云</h3><ol>
<li><p>下载bcloud</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">wget https://github.com/LiuLang/bcloud-packages/blob/master/bcloud_3.7.1-3_all.deb</div></pre></td></tr></table></figure>
</li>
<li><p>安装<br> 由于bcloud需要很多依赖,所以需要强制更新安装依赖环境</p>
<figure class="highlight plain"><table><tr><td class="code"><pre><div class="line">sudo dpkg -i bcloud_3.7.1-3_all.deb</div><div class="line">sudo apt-get -f install</div></pre></td></tr></table></figure>
</li>
<li><p>配置并上传文件。<br>回到远程桌面,在左上角的<code>Applications Menu</code>><code>Internet</code>里找到<code>bcloud</code>,并打开,将弹出的默认设置窗口,即可登录使用。gui使用较简单,过程省略。</p>
</li>
</ol>
<hr>
<p>到此,整个中转过程完成,之后就是等上传完去DO删droplet之类的事了。很简单,略过。<br>PS:<br>DO的机子resize上去后就不可以下来了。所以如果是空间不够的话,请另开一个Droplet,DO以小时计费,并不贵。否则升级了使用完后想降下来的话,就有得折腾了。<br>PSP:<br>你如果真的不小心将DO升上去了,想降下来,也可以参考官方这个文档。过程虽然多,但是不难。<br><a href="https://www.digitalocean.com/community/tutorials/how-to-downgrade-digitalocean-droplets" target="_blank" rel="external">How To Downgrade DigitalOcean Droplets</a><br>PSV:<br><strong>DO的droplet即使关机状态下也是计费的。</strong>但是你可以做个快照备份(snapshot),然后后面每次需要中转的时候都可以直接从这个快照里快速建立一个新的droplet,不需要每次都重新设置。</p>
]]></content>
<summary type="html">
<p>声明:本文基于<strong>Ubuntu 14.04 x64</strong>,由于本人自身对linux的掌握仅仅是初级阶段,所以本文只记录操作指令流程,不做具体分析。其中大部分操作指令来自google搜索结果,所以这篇文章些地方理解或有错误,恳请指正。</p>
<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>昨天有朋友让他帮他从海外ftp拖一个16G的文件,由于国内直连速度实在太渣,加上ftp网站那边权限限制较严格,无法使用目前已有的大部分公网离线服务,也不能用第三方FTP客户端下载,只能通过浏览器下载。所以我就自己用DO转了下,上传到国内的百度云,做个记录。方便下次使用。<br><strong>本文适用场景:下载链接不固定且只能通过浏览器下载的文件。</strong><br>
</summary>
<category term="运维" scheme="http://chitanda.me/categories/%E8%BF%90%E7%BB%B4/"/>
<category term="运维" scheme="http://chitanda.me/tags/%E8%BF%90%E7%BB%B4/"/>
<category term="vps" scheme="http://chitanda.me/tags/vps/"/>
<category term="ubuntu" scheme="http://chitanda.me/tags/ubuntu/"/>
</entry>
<entry>
<title>绕过限制,在PC上调试微信手机页面</title>
<link href="http://chitanda.me/2015/06/29/debug-wechat-website-in-pc/"/>
<id>http://chitanda.me/2015/06/29/debug-wechat-website-in-pc/</id>
<published>2015-06-29T08:31:07.000Z</published>
<updated>2017-01-10T11:15:34.281Z</updated>
<content type="html"><![CDATA[<h2 id="场景"><a href="#场景" class="headerlink" title="场景"></a>场景</h2><p>假设一个手机页面,开发者对其做了限制,导致只能在微信客户端中打开。而众所周知手机上非常不利于调试页面,所以需要能在电脑上打开并进行调试。这里针对常见的三种页面做一下分析,一一绕过其限制,(当然不要拿去干坏事)<br><a id="more"></a></p>
<hr>
<h3 id="工具准备"><a href="#工具准备" class="headerlink" title="工具准备"></a>工具准备</h3><ol>
<li>方便调试的浏览器。个人喜欢<strong>Chrome</strong>,本文基于<strong>Chrome 43.0.2357.130 (正式版本) m (32 位)</strong>环境。</li>
<li>抓包工具,推荐<strong>fiddler4</strong>,当然你比较喜欢Wireshark的话也可以,反正只要是能抓到cookies就都可以</li>
<li>能编辑cookies的浏览器插件。Chrome下我推荐<strong><a href="https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg" target="_blank" rel="external">EditThisCookie</a></strong>,Firefox的话试用<strong>Firebug</strong>自带的编辑功能即可</li>
</ol>
<hr>
<h2 id="更新"><a href="#更新" class="headerlink" title="更新"></a>更新</h2><p>更新于2016-04-05,针对第三种要openid验证的页面<br>没想到这文竟然会是我blog的最大流量来源= =<br>由于时间进入2016年,调试工具已经大大升级,所以我更新下个人比较推荐的更具有普适性也更简单的方法:</p>
<ol>
<li>安装微信的<a href="http://weixin.qq.com/cgi-bin/readtemplate?uin=&stype=&promote=&fr=&lang=zh_CN&ADTAG=&check=false&nav=download&t=weixin_download_list&loc=readtemplate,weixin,body,3" target="_blank" rel="external">PC版</a></li>
<li>打开<code>fiddler</code>,然后在微信PC版里打开要调试的页面(一般会弹出授权窗口,确定即可),接着在fiddler里找到进入后的实际页面的cookies</li>
<li>打开要调试页面的任意主页,如要调试<code>www.aaa.com/mobile/xxx.php</code>的页面的话,就跳转到<code>www.aaa.com</code>首页,然后按照第二步抓到的页面的cookies,一个个填给chrome即可。(<strong>之所以要跳到首页去填是因为该域名下没有其他更容易编辑cookies的页面了</strong>)</li>
</ol>
<p>PS:<strong>复制以及更改cookies</strong>的具体步骤可以参照下文<a href="#绕过方法-3">第三部分</a>的<code>第3-6</code>几个步骤(虽然有些人推荐<a href="https://mp.weixin.qq.com/wiki/10/e5f772f4521da17fa0d7304f68b97d7e.html" target="_blank" rel="external">微信官方调试工具</a>,但是个人认为对非开发者来说这个工具不是必须的,而微信的PC端、fiddler和chrome浏览器则是可以常备的。另外加上内置的chrome调试工具远低于正常版本,所以推荐度不如微信PC客户端)</p>
<p><del>更新于2015-10-12,针对第三种要openid验证的页面:<br>除了原先上文提到的抓包取cookies方法外,现在其实还有更简单的办法,利用微信官方的tbs调试。<br>最简单的办法就是安装QQ浏览器最新版,然后利用内置的<a href="http://blog.qqbrowser.cc/wei-xin-gong-zhong-hao-ben-di-diao-shi/" target="_blank" rel="external">微信调试工具</a>,可以省掉很多麻烦。具体步骤省略。<br>不喜欢用QQ浏览器的话,可以利用官方的tbs插件加上本地inspect的办法,可以参考此文:<br><a href="http://bbs.mb.qq.com/thread-243399-1-1.html" target="_blank" rel="external">微信、手Q、Qzone之x5内核inspect调试解决方案</a><br>不过这个方法我个人并没有尝试过,因为感觉配置过程过于麻烦。</del></p>
<hr>