字符集编码与Python(一)编码历史

相信有很多人和我一样,在写代码的时候经常会被一些各种字符集编码的问题困扰吧,于是最近心血来潮准备好好的嚼嚼字符集编码 要好好的了解字符集编码,我们肯定从各种编码集的历史说起了,下面本篇就主要着手于介绍字符集编码的历史


#编码历史

##ASCII

ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。ASCII 是一种字符编码,同时也是一种最简单的字符集编码,把128 个字符映射至整数0 ~ 127。

在 ASCII码里面,虽然你看到的是一个字符,但是对于计算机来说,存的就是二进制的整数,也就是说你看到的可能是abcd,但是计算机内部存的就是97 98 99 100。

ASCII这种7-bit 字符编码系统非常简单,在计算机中以一个字节存储一个字符。如下所示,

我安装了一个ascii 下面就是详细的信息:

[root@iZ28b4rx8dxZ ~]# yum install ascii
[root@iZ28b4rx8dxZ ~]# ascii
Usage: ascii [-dxohv] [-t] [char-alias...]
   -t = one-line output  -d = Decimal table  -o = octal table  -x = hex table
   -h = This help screen -v = version information
Prints all aliases of an ASCII character. Args may be chars, C \-escapes,
English names, ^-escapes, ASCII mnemonics, or numerics in decimal/octal/hex.
 
Dec Hex    Dec Hex    Dec Hex  Dec Hex  Dec Hex  Dec Hex   Dec Hex   Dec Hex 
  0 00 NUL  16 10 DLE  32 20    48 30 0  64 40 @  80 50 P   96 60 `  112 70 p
  1 01 SOH  17 11 DC1  33 21 !  49 31 1  65 41 A  81 51 Q   97 61 a  113 71 q
  2 02 STX  18 12 DC2  34 22 "  50 32 2  66 42 B  82 52 R   98 62 b  114 72 r
  3 03 ETX  19 13 DC3  35 23 #  51 33 3  67 43 C  83 53 S   99 63 c  115 73 s
  4 04 EOT  20 14 DC4  36 24 $  52 34 4  68 44 D  84 54 T  100 64 d  116 74 t
  5 05 ENQ  21 15 NAK  37 25 %  53 35 5  69 45 E  85 55 U  101 65 e  117 75 u
  6 06 ACK  22 16 SYN  38 26 &  54 36 6  70 46 F  86 56 V  102 66 f  118 76 v
  7 07 BEL  23 17 ETB  39 27 '  55 37 7  71 47 G  87 57 W  103 67 g  119 77 w
  8 08 BS   24 18 CAN  40 28 (  56 38 8  72 48 H  88 58 X  104 68 h  120 78 x
  9 09 HT   25 19 EM   41 29 )  57 39 9  73 49 I  89 59 Y  105 69 i  121 79 y
 10 0A LF   26 1A SUB  42 2A *  58 3A :  74 4A J  90 5A Z  106 6A j  122 7A z
 11 0B VT   27 1B ESC  43 2B +  59 3B ;  75 4B K  91 5B [  107 6B k  123 7B {
 12 0C FF   28 1C FS   44 2C ,  60 3C <  76 4C L  92 5C \  108 6C l  124 7C |
 13 0D CR   29 1D GS   45 2D -  61 3D =  77 4D M  93 5D ]  109 6D m  125 7D }
 14 0E SO   30 1E RS   46 2E .  62 3E >  78 4E N  94 5E ^  110 6E n  126 7E ~
 15 0F SI   31 1F US   47 2F /  63 3F ?  79 4F O  95 5F _  111 6F o  127 7F DEL
[root@iZ28b4rx8dxZ ~]#

 

##Latin-1

虽然ASCII好用,但是,很多时候一个字符用一个字节并不够。例如,各种符号和重音字符并不在ASCII所定义的可能字符的范围中,

为了容纳特殊字符,一些标准允许一个8位字节的所有bit都用来表示字符,那么,一个字节最多就可以表示255个字符了,这样的一个标准叫 latin-1

Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。ISO-8859-1编码是单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。

因为Latin-1 编码范围使用了单字节内的所有空间,在支持Latin-1 的系统中传输和存储其他任何编码的字节流都不会被抛弃。换句话说就是把其他任何编码的字节流当作Latin-1 编码看待都没有问题。这是个很重要的特性,MySQL数据库默认编码是Latin1就是利用了这个特性

在latin-1中,127以上的字符代码分配给了重音和其他特殊字符

    >>> print chr(169)
    ©
    >>> print chr(189)        #chr这个函数把数字转换成字符
    ½
    >>> print chr(174)
    ®

 

###总结 latin-1ASCII 的区别:

 

##GB 2312

GB 2312是一个简体中文汉字编码国家标准,GB2312对汉字采用双字节编码,由6763个常用汉字和682个全角的非汉字字符组成。其中汉字根据使用的频率分为两级。一级汉字3755个,二级汉字3008个。由于字符数量比较大,GB2312采用了二维矩阵编码法对所有字符进行编码。

 

##BIG5编码

台湾地区繁体中文标准字符集,采用双字节编码,也称为大五码,具体的信息我就不介绍了,百度上一堆

 

##GBK编码

1995年12月发布的汉字编码国家标准,是对GB2312编码的扩充,对汉字采用双字节编码。GBK字符集共收录21003个汉字,包含国家标准GB13000-1中的全部中日韩汉字,和BIG5编码中的所有汉字。

最一开始,在Unicode 出现之前,各地区国家制定了不同的编码系统,也就是说中文自己进行编码,如GB 2312 和大五码等,日文也自己进行编码,如主要用JIS ,这样会造成混乱不便,例如一个文本信息里面混合了不同的语言,就不能正确的表示信息,也就是无法进行混合的使用。

 

##Unicode

Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字,以满足跨语言、跨平台进行文本转换、处理的要求。

统一码为每一个字符而非字形定义唯一的代码(即一个整数)。换句话说,统一码以一种抽象的方式(即数字)来处理字符,并将视觉上的演绎工作(例如字体大小、外观形状、字体形态、文体等)留给其他软件来处理,例如网页浏览器或是文字处理器

Unicode是为了解决传统的字符编码方案的局限而产生的

每个字符映射至一个整数码点(code point),码点的范围是0 至0x10FFFF,在表示一个Unicode的字符时,通常会用 U+ 然后紧接着一组十六进制的数字来表示这一个字符。在Python中,用 \uxxxx 表示。所以有的时候用写Python的过程中看到了像 \u 四个十六进制的的字符的话,说明这个字符是Unicode。

其中Unicode 还制定了各种储存码点的方式,这些方式称为Unicode 转换格式(Uniform Transformation Format, UTF)。

现在流行的UTF 为 UTF-8UTF-16UTF-32 。每种UTF 会把一个码点储存为一至多个编码单元(code unit)。例如UTF-8 的编码单元是8 位的字节、UTF-16 为16 位、UTF-32 为32 位。除UTF-32 外,UTF-8 和UTF-16 都是可变长度编码。

其中UTF-8 成为现在互联网上最流行的格式,有几个原因:

单字节的情况下不会出现大端小端的问题,比如说有两个字节,ab就要考虑是a放在前面还是b放在前面,对于大端的话就是a放前面,对于小端的话就是b放前面。我们常用的X86结构是小端模式

 

##UTF-8的实现

首先声明:utf8Unicode 并不是竞争的关系

UTF-8 的编码单元是8 位字节,每个码点编码成1 至4 个字节。它的编码方式很简单,按照码点的范围,把码点的二进位分拆成1 至最多4 个字节

UTF-8 编码方法的好处之一是,码点范围U+0000 ~ U+007F 编码为一个字节,与ASCII 编码兼容。这范围的 Unicode 码点也是和ASCII 字符相同的。因此,一个 ASCII 文本也是一个 UTF-8 文本

也就是说Unicode编码成utf-8有自己的一套编码方法

码点范围码点位数字节1字节2字节3字节4
U+0000 ~ U+007F70xxxxxxx   
U+0080 ~ U+07FF11110xxxxx10xxxxxx  
U+0800 ~ U+FFFF161110xxxx10xxxxxx10xxxxxx 
U+10000 ~ U+10FFFF2111110xxx10xxxxxx10xxxxxx 

用Python举个例子解释一下:

    In [24]: name = u'张三'
     
    In [25]: name
    Out[25]: u'\u5f20\u4e09'

把“张三”编码成为 `utf-8`

    In [26]: name.encode('utf-8')
    Out[26]: '\xe5\xbc\xa0\xe4\xb8\x89'     #张:e5 bc a0  三:e4 b8 89 

这其中的转换过程如下所示:

把5f20和4e09分别翻译成二进制然后转为 utf-8


5f20:

翻译为二进制:

0101      1111      0010      0000

按照上面码点范围的转换方式,5f20 应该属于第三个范围 也就是

1110+0101(四位)+10+111100(六位)+10+100000(六位):

1110 0101 1011 1100 1010 0000

    e         5       b        c         a       0


4e09:

翻译为二进制:

0100    1110    0000    1001

按照上面码点范围的转换方式,4e09 应该属于第三个范围 也就是

1110+0100(四位)+ 10 +111000(六位)+ 10 +001001(六位):

1110 0100 1011 1000 1000 1001

    e         4       b         8         8       9

下一篇详细理解Python里面Unicodeutf-8



简单的讲Python内置数据类型

在众多语言的学习和应用中,数据类型必不可少,当然了核心数据类型也无外乎就那么几种 (很多语言中提供了数字,字符串,文件数据类型,有一部分形式的数据类型以标准库的形式表示 ) ,但是在 python 有很多数据类型都是内置的,不需要 import 。



#python基本内置数据类型

  1. 数字
  2. 字符串
  3. 列表list
  4. 字典dict
  5. 元组
  6. 集合
  7. None
  8. 布尔
  9. 文件

#1、数字

(整数,浮点数)

python的数字是无限扩展的(没有溢出的概念,也就是说可以无限大)在python2里面整数有int和long,但是python3里面已经统一了

数字(python支持一个特殊的方法(幂次方),比如说3的10次方,表示的方法就是3**10)

    In [1]: 3**10
    Out[1]: 59049
    In [2]:
    In [15]: 5//2.0
    Out[15]: 2.0
    
    In [16]: 5/2.0
    Out[16]: 2.5

例如: abs:绝对值 round:四舍五入 float:转换成浮点型 bin:把十进制转换成二进制 oct:把十进制 转换成八进制 hex:把十进制 转换成十六进制 int:转换成十进制(int(”20”),int(”20”,8),int(”20”,16) ,int(”100000”,2) )

例如:

    In [2]: import math
    
    In [3]: math.pi
    Out[3]: 3.141592653589793
    
    In [4]: math.sqrt(100)     #开根号                            
    Out[4]: 10.0
    
    In [1]: import random     #随机数
    
    In [2]: random.random()
    Out[2]: 0.10360162039961152

 

#2、字符串

字符串有三种形式,单引号,双引号,和三引号(好处就是可以嵌套嘛,比如说你代码里面有一段话里面就有双引号,这样外面就可以用单引号,也就是说不需要进行特殊处理了,说白了就是不需要转义了,当然你完全可以用两个双引号或者是什么的)

    In [3]: "my"
    Out[3]: 'my'
    
    In [4]: "\"my"
    Out[4]: '"my'
    
    In [5]: '"my'
    Out[5]: '"my'

(但是最好用双引号,因为其他语言中几乎都是双引号,这样能够让人看得懂)

字符串是字符的一个容器,可以用下标来访问:

    In [7]: a = "abcd"
    
    In [8]: a[0]
    Out[8]: 'a'
    
    In [9]: a[1]
    Out[9]: 'b'
    
    In [10]: a[-1]     #负数就是从右往左
    Out[10]: 'd'
    
    In [11]: a + "efg"
    Out[11]: 'abcdefg'
    
    In [13]: a[1:3]     #分片操作
    Out[13]: 'bc'

但是我们也是可以通过别的办法来进行一定意义上的修改,可以通过表达式来创建新的对象,并将结果分配给变量来进行修改。

举个例子吧:比如说

    In [7]: a = "abcd"
    
    In [8]: a
    Out[8]: 'abcd'
    
    #此时我们要修改a 变成bbcd
    #我们首先可能想到的会是这样
    
    In [9]: a[0]="b"
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-15-4820869b496e> in <module>()
    ----> 1 a[0]="b"
    
    TypeError: 'str' object does not support item assignment
    
    #所以我们可以这样
    
    In [10]: "b" + a[1:]     #终点不指定就是到最后
    Out[10]: 'bbcd'
    
    In [11]: a = "b"+a[1:]     #可以赋值给a
    
    In [12]: a
    Out[12]: 'bbcd'

例如:

     a.capitalize a.endswith   a.isalnum    a.istitle    a.lstrip
     a.center     a.expandtabs a.isalpha    a.isupper    a.partition
     a.count      a.find       a.isdigit    a.join       a.replace
     a.decode     a.format     a.islower    a.ljust      a.rfind
     a.encode     a.index      a.isspace    a.lower      a.rindex
     a.rjust      a.splitlines a.translate
     a.rpartition a.startswith a.upper
     a.rsplit     a.strip      a.zfill
     a.rstrip     a.swapcase
     a.split      a.title

对于一些特定类型的操作,都是以方法调用的形式提供的

    #比如
    
    In [21]: b = a.upper()
        
    In [22]: b
    Out[22]: 'BBCD'
    
    In [23]: b = b.lower()
    
    In [24]: b
    Out[24]: 'bbcd'

 

#3 、列表 list

  1. (任意类型的集合)
  2. (大小可变)
  3. (可以嵌套)
  4. (支持列表综合,也可以叫做列表解析)

下面我们就来看一些例子

    In [25]: a = ["abc",123.1,"123"]
    
    In [26]: a
    Out[26]: ['abc', 123.1, '123']
    
    #大小可变
    
    In [27]: a.append("de")
    
    In [28]: a
    Out[28]: ['abc', 123.1, '123', 'de']     #默认添加到末尾,当然可以指定添加的位置
    
    In [29]: a.insert?     #查看帮助
    Docstring: L.insert(index, object) -- insert object before index
    Type:      builtin_function_or_method
    
    In [30]: a.insert(0,"li")
    
    In [31]: a
    Out[31]: ['li', 'abc', 123.1, '123', 'de']
    
    #可以嵌套(列表里面含有列表)
    
    In [33]: b = ["a","b",[1,2]]     #嵌套
    
    In [34]: b
    Out[34]: ['a', 'b', [1, 2]]
    
    
    #支持列表综合,也可以叫做列表推导
    
    In [47]: a = [i*2 for i in range(10)]
    
    In [48]: a
    Out[48]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

 

reverse的一个例子:

    In [44]: b
    Out[44]: ['a', 'b', [1, 2]]
    
    In [45]: b.reverse()
    
    In [46]: b
    Out[46]: [[1, 2], 'b', 'a']

 

append和extend的区别

    In [38]: a
    Out[38]: ['li', 'abc', 123.1, '123', 'de']
    
    In [39]: b
    Out[39]: ['a', 'b', [1, 2]]
    
    In [40]: a.append(b)     #以列表的形式添加到另一个列表中
    
    In [41]: a
    Out[41]: ['li', 'abc', 123.1, '123', 'de', ['a', 'b', [1, 2]]]
    
    In [42]: a.extend(b)     #向列表里面增加另一个列表里面的元素
    
    In [43]: a
    Out[43]: ['li', 'abc', 123.1, '123', 'de', ['a', 'b', [1, 2]], 'a', 'b', [1, 2]]

 

#4、字典dict

(K:V),键值对

例如: 写出字典的形式:

    In [50]: a = {
        ...:   "array": [
        ...:     1,
        ...:     2,
        ...:     3
        ...:   ],
        ...:   "number": 123,
        ...:   "object": {
        ...:     "a": "b",
        ...:     "c": "d",
        ...:     "e": "f"
        ...:   },
        ...:   "string": "Hello World"
        ...: }
    
    
    In [51]: a
    Out[51]:
    {'array': [1, 2, 3],
     'number': 123,
     'object': {'a': 'b', 'c': 'd', 'e': 'f'},
     'string': 'Hello World'}
    
    
    In [56]: a.keys()
    Out[56]: ['array', 'object', 'number', 'string']
    
    In [57]: a.values()
    Out[57]: [[1, 2, 3], {'a': 'b', 'c': 'd', 'e': 'f'}, 123, 'Hello World']

 

#5、元组

(可以理解为不可变的一个列表,很像)

支持像列表一样的 分片,索引操作等等

    In [59]: a = (1,2,"ab")
    
    In [60]: a
    Out[60]: (1, 2, 'ab')
    
    In [61]: a[0]
    Out[61]: 1
    
    In [62]: a[1]
    Out[62]: 2
    
    In [63]: a[-1]
    Out[63]: 'ab'
    
    In [66]: a[1:]
    Out[66]: (2, 'ab')

元组不可以修改!!!!!!!!!!!

    In [67]: a[0]= 42
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-67-675ed0d52101> in <module>()
    ----> 1 a[0]= 42
    
    TypeError: 'tuple' object does not support item assignment

 

    a.count     #统计
    a.index     #索引,查找

 

#6、集合

(可以参考数学上面的概念,所以集合会有一些与操作,或操作,并集,交集,补集,等)

 

#7、None

(与C语言的NULL指针类似)

None是一个常量,类型是NoneType,而且就是一个空值对象,既不是空字符串 ,不是False,也不是0,其数据遵循单例模式,也是唯一的,因而,不能创建None对象。

例如:

    In [23]: id(None)
    Out[23]: 1377856600L
    
    In [25]: a = None
    
    In [26]: id(a)
    Out[26]: 1377856600L
    
    In [27]: type(None)
    Out[27]: NoneType

所有赋值为None的变量都相等,并且None与任何非None的对象比较结果都为False。

 

#8、布尔

(bool) 非零数字,或者其他非空的对象,则为True(True在数字上面可以代表1,False可以代表0) 否则为False None为False

    In [68]: a = 2>4
    
    In [69]: a
    Out[69]: False
    
    In [70]: b = 2>1
    
    In [71]: b
    Out[71]: True

##声明!!!!!!!!!!!!!

 

#9、文件

首先用open函数打开一个文件,打开的时候可以指定打开的模式:读 ,写 ,默认以读的方式打开

    In [72]: f = open ('/usr/local/file/file2')
    
    In [73]: f
    Out[73]: <open file '/usr/local/file/file2', mode 'r' at 0xmcadb80>
    
    In [81]: f.readlines()
    Out[81]:
    ['Hello Word ! \n',
     'my friend, \n',
     'my name is ***,welcome to my blog.\n',
     '\n']
    
    
    In [82]: f = open ('/usr/local/file/file3','w')
    
    In [83]: f.write(("hello"*5) + '\n')
    
    In [84]: f.close()
    
    In [85]: myfile = open('/usr/local/file/file3')
    
    In [86]: text = myfile.read()
    
    In [87]: text
    
    'hellohellohellohello\n'
    f.close      f.flush      f.next       f.seek      #从第几个字节开始读
    f.writelines
    f.closed     f.isatty     f.read       f.softspace  f.xreadlines
    f.encoding   f.mode       f.readinto   f.tell
    f.errors     f.name       f.readline   f.truncate
    f.fileno     f.newlines   f.readlines  f.write

##(打开文件 读写完一定要关闭!!!!!!!!!!!!!!!) 所以Python 提供了with,with语句结束的时候文件就自动关闭了,

    In [11]: with open('/usr/local/file/file3') as f:
        ...: for line in f:
        ...: ...........#操作

 

#总结

所有类型的分类  

数字 序列(字符串、元组、列表 )(可以通过下标的形式来访问),支持索引和分片 映射(字典dict),没有顺序,通过键进行访问  

不可变(数字、字符串、元组),不支持原处修改,可以通过表达式来创建新的对象,并将结果分配给变量来进行修改。

可变(列表、字典、集合),可以原处修改,也就是说不用创建新的对象



HTTPS=HTTP + SSL / TLS

应一个学长的强烈安利,并且经过他的一番刻苦指导,总结了一下关于为什么要用HTTPS以及HTTPS是如何实现的知识 首先先说说HTTP


#HTTP

HTTP协议(HyperTextTransfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议,是一个基于TCP/IP 协议的应用层协议。 ![请输入图片描述][1] 但是HTTP协议由诸多不足,比如说:

1 . 通信使用明文(也就是不加密),内容可能被窃听 2 . 不验证对方身份,可能遭遇伪装 3 . 无法证明报文的完整性,报文可能被篡改

于是为了防止以上的不安全的情况发生人们普遍会想到把浏览器和服务器之间的通信在HTTP的基础上进行加密,也就是把通信间的数据进行加密, 对原来为明文的文件或数据按某种算法进行处理,让其成为不可读的一段代码,通常称为“密文”,使其只能在输入相应的密钥之后才能显示出本来内容,通过这样的途径来达到保护数据不被非法人窃取、阅读的目的。

加密的技术通常分为两大类:对称式加密技术和非对称式加密技术

1、对称加密技术:

通俗来说对称式加密也就是说加密和解密使用同一个密钥。

2、非对称加密技术: 而非对称式加密就是加密和解密所使用的不是同一个密钥,也就是说通常有两个密钥,分别称为“公钥”和“私钥”,它们两个必需配对使用,否则不能打开加密文件。“公钥”顾名思义也就是可以对外公布的,“私钥”就是私有的,只能由持有人一个人知道的。而且有一个好处就是,公钥和私钥没有必然的联系,也就是完全没有关系的两个密钥,通俗说:也就是公钥无法推出私钥,相反私钥也无法推出公钥。

接下来我们开始了给HTTP发送和接收的数据进行加密处理

1、首先假设我们单独用对称加密技术进行加密:

也就是说浏览器把要发送的数据用密钥进行加密,发送给服务器,那么问题来了,本次回话的密钥密钥怎么交给服务器,如果不给服务器,那岂不是服务器也不知道浏览器发的是什么,也就无法回应浏览器了,所以瞬间陷入了一个死循环, 所以算法和密钥泄露,加密也就就无意义了。于是这个方法被pass掉了。

2、然后我们开始想使用单独的非对称加密技术:

也就是说浏览器用公钥把数据进行加密,然后服务器再根据私钥进行解密, 因为私钥是私密的,所以算法和公钥公开也是无法解密,也就是说此时是安全的,服务器解密了数据报,但是,想要把响应的数据报加密发送给浏览器,应该拿什么加密!于是这个方法也被pass掉了。

3、把对称和非对称一起考虑:

第一步: 服务器先基于非对称加密,随机生成一对密钥(K1,K2)

第二步: 服务器吧k1保留,把k2发送给浏览器(k2有可能被偷窥,但是没有关系,因为K1和K2没有联系)

第三步: 浏览器拿到K2后,首先随机生成一个对称加密的密钥(K) 然后用K2加密K,得到K’ (K’是一个加密的结果) 浏览器把K’发送给服务器 由于K1和K2 是一对非对称的密钥,所以只有K1能够解密K2 加密的结果 因此这个过程中,即使被偷窥,偷窥者也无法从K’解密得到K

第四步: 服务器拿到K’后,用K1 进行解密,也就是得到了K 到现在为止 ,浏览器和服务器之间完成了密钥的交换,也就是说,双方都知道K,貌似偷窥者也无法拿到K,接下来,浏览器和服务器就可以用K来进行数据的双向传输的加密了。

但是!!!!!!!!!!!!!!!!!!!!!!!!!!!!!但是!!!!!!!!!!!!!!! 假设有个攻击者,他在A和B的中间,对A称自己的B,对B称自己是A,那么他就可以随意的篡改信息,

![请输入图片描述][2] 通俗点说就是你和我语言不通,需要翻译,那么这个翻译实际上就充当了我们两个之间的中间人,我们说了什么他都知道,而且还能随意的篡改信息,也就是所说的中间人攻击。于是这个方法也被pass掉了。

那么我们想想为什么第三种方法行不通?因为他 缺乏有效的身份认证机制,也就是说, 浏览器不知道跟它通信的是真正的服务器还是别人伪装的服务器。所以引进了CA证书,也就是双方都信任的“公证人 ”

CA证书

关于CA证书可以参考以下链接,写的很详细,很棒 https://program-think.blogspot.com/2010/02/introduce-digital-certificate-and-ca.html

HTTPS

墨迹半天终于说到正题HTTPS了 众所周知 HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。

HTTPS所要做到的安全性需求

隐私性:通信无法别劫持(理论上不可能做到) 保密性:防止被嗅探,即使被嗅探了也无法解密、也就等于防止泄密了 正确性(认证):发送给了真正的接受者 完整性:通信完整无缺,防止篡改。

在这里强烈声明!!!!

HTTPS不是一种新的协议,是HTTP + SSL/TLS, 也就是在TCP(负责网络数据传输)和HTTP层之间,增加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过SSL/TLS进行加密,所以传输的数据都是加密后的数据。

( 其中SSL是Secure Sockets Layer安全套接层的缩写,TLS Transport Layer Security缩写,传输层安全协议 SSL是比较古董的、使用广泛的,后来人们给他标准化了,就叫TLS了,也就是说SSL和TLS是不同事物在不同阶段的名称 )

具体加密解密的过程如下所示:

第一步:

浏览器向服务器发一个请求

第二步:

服务器配置一套证书:这套证书其实就是一对公钥和私钥相当于我上面说的(K1,K2)。

第三步:

服务器传送证书中的公钥(K1)给浏览器,其中也包含了很多信息,如证书的过期的时间啊等。

第四步:

浏览器吧证书公钥解析,由SSL/TLS来完成,首先会验证公钥是否有效,如果有异常情况,就会弹出一个警告,提示证书有问题。否则,就生成一个随机的值(相当于上面说的K)。然后用证书中的公钥对该随机值进行加密。得到的加密后的随机值(相当于面说的K’)发送给服务器,以后浏览器和服务器之间的的通信就可以用这个随机值(K)来进行加密解密了。

于是就实现了我们通常所说的安全的传输HTTPS。

在这里我也不得不说一下HTTPS本身也是存在一些弊端的(没有绝对意义上的好嘛):

1、

就比如说SSL/TLS证书存在滥用问题,一些著名证书授权机构错误地签名了大量的伪造和欺诈的证书,直接损害数以万计的Mozilla用户的安全。

2、

NSA( 美国国家安全局) 植入后门:实际上是在bsafe中使用Dual_EC_DRBG作为Bsafe中的首选随机数生成算法。(但是好几年前的事情了,现在已经解决了,我简单的查了一下,效率也相当的高)

3 、 PKI体系的漏洞(社会学问题)、不安全的密钥协商(RC4等)、不安全的协议(SSL全系列)、SSLStrip(SSL降级攻击)、野兽攻击等等。

但是在网络化科技发达的今天,所谓的网络安全是很重要的,非常重要的(也可以这么说),所以相对于 传统意义上的不安全的HTTP, 毫无疑问,你应该使用HTTPS。


#参考资料

  1. https://www.bennythink.com/school-1.html
  2. https://www.bennythink.com/school-2.html


系统监控glances以及Python&pip 安装

glances 是前几天一个前辈推荐的系统监控系统,最近尝试用了一下,感觉比很多的监控系统实用,比如 top 只能监控本机的系统,但是 glances 即可以监控本机,也可以通过客户端模式监控其他的机器,可以把数据输出到 csv 或者 html 格式的文件 也就方便了绘制图表或者是其他程序处理,而且很实用的是他提供了基于 Xml/RPC 的 API ,这就让他实现可编程的应用


glances支持很多系统,比如说 Linux,Mac OS,Win 等等

其中glances是python开发的,我也是从python这方面了解到的,下面简单介绍一下它的功能,其中他是使用psutil库采集系统数据,可以在终端上面显示动态的系统数据变化:CPU,磁盘,网络等等,以及内核,负载,I/O等消耗资源的进程,交互性很好,可读性很好,一眼能看到很多信息

下面简单安装,使用一下

其中安装之前必须安装了Python

下面先装一下python:

yum install wget#安装编译Python需要的组件
yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel
 
#下载并解压Python的源代码
wget https://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz
tar zxvf Python-2.7.9.tgz
mv Python-2.7.9 /usr/local/
cd /usr/local/
 
#编译安装Python
cd Python-2.7.9
./configure –prefix=/usr/local
 
make && make install
#将系统python命令指向Python 2.7
mv /usr/bin/python /usr/bin/python2.6.6
ln -s /usr/local/bin/python2.7 /usr/bin/python
 
#将yum需要执行的python指定为2.6.6 
vi /usr/bin/yum 
#将文件头部的
 
#!/usr/bin/python
#改成
 
#!/usr/bin/python2.6.6
  
#我们可以用ipython进行交互,比python自带的shell好用的多
#安装
ipython-0.13.1.tar.gz
tar zvxf ipython-0.13.1.tar.gz
cd ipython-0.13.1
python setup.py install

下面我装一下pip:

首先安装setup-tools:

wget https://pypi.python.org/packages/2.7/s/setuptools/setuptools-0.6c11-py2.7.egg  --no-check-certificate
chmod +x setuptools-0.6c11-py2.7.egg
sh setuptools-0.6c11-py2.7.egg

#或者
wget https://pypi.python.org/packages/2.7/s/setuptools/setuptools-1.4.2.tar.gz  --no-check-certificate
cp setuptools-1.4.2.tar.gz /usr/local/
cd /usr/local/
tar zxvf setuptools-1.4.2.tar.gz
cd /usr/local/setuptools-1.4.2sudo python setup.py install
#安装pip
wget https://pypi.python.org/packages/source/p/pip/pip-1.3.1.tar.gz --no-check-certificatecp pip-1.3.1.tar.gz /usr/src/
tar zxvf pip-1.3.1.tar.gz
cd pip-1.3.1
python setup.py install
ln -s /usr/local/Python2.7/bin/pip /usr/bin/pip
#安装 glances
pip install psutil
pip install pysensors
pip install hddtemp
pip install glances

python setup.py install

glances的使用方法可以–help得到:

 -b:显示网络连接速度 Byte/ 秒
 -B @IP|host :绑定服务器端 IP 地址或者主机名称
 -c @IP|host:连接 glances 服务器端
 -C file:设置配置文件默认是 /etc/glances/glances.conf 
 -d:关闭磁盘 I/O 模块
 -e:显示传感器温度
 -f file:设置输出文件(格式是 HTML 或者 CSV)
 -m:关闭挂载的磁盘模块
 -n:关闭网络模块
 -p PORT:设置运行端口默认是 61209 
 -P password:设置客户端 / 服务器密码
 -s:设置 glances 运行模式为服务器
 -t sec:设置屏幕刷新的时间间隔,单位为秒,默认值为 2 秒,数值许可范围:1~32767 
 -h : 显示帮助信息
 -v : 显示版本信息

让glances让输出 HTML 格式文件

pip install jinja2
glances -o HTML -f  /usr/local/nginx/html/glances.html
#在浏览器里面输入网址:http://localhost/usr/local/nginx/html/glances.html 就可以访问到

输出 csv 格式

glances -o CSV -f /usr/local/glances_test/glances.csv

glances 可以实现客户端/服务器 的工作方式:可以实现远程监控:

服务器Ip地址:111.111.111.111

客户端Ip地址:222.222.222.222

而且两个都已经安装了glances,首先应该现在服务器端启动

[root@Z ~]# glances -s -B 111.111.111.111
Glances server is running on 111.111.111.111:61209

可以看到glances 使用的端口号是61209,所以用户需要确保防火墙打开这个端口。

下面在客户端使用如下命令连接服务器 glances -c 111.111.111.111

客户端Ip地址:222.222.222.222



MySQL5.7的Linux安装shell脚本之二进制安装

之前写了一个 MySQL5.6 的安装脚本 MySQL 5.7 已经开发两年多了。相比 MySQL 5.6,有很多改进的地方。不论是在速度还是在性能上相比于 5.6 都提升了很多 ! 所以在 5.7 上有很多值得学习的新特征,比如说:


 等等等,在这里我就不细说了

所以想在写一个5.7的安装脚本

下面看一下安装过程

shell> groupadd mysql
shell> useradd -r -g mysql mysql
shell> cd /usr/local
shell> tar zxvf /path/to/mysql-VERSION-OS.tar.gz
shell> ln -s full-path-to-mysql-VERSION-OS mysql
shell> cd mysql
shell> mkdir mysql-files
shell> chmod 770 mysql-files
shell> chown -R mysql .
shell> chgrp -R mysql .
shell> bin/mysql_install_db --user=mysql    # Before MySQL 5.7.6
shell> bin/mysqld --initialize --user=mysql # MySQL 5.7.6 and up
shell> bin/mysql_ssl_rsa_setup              # MySQL 5.7.6 and up
shell> chown -R root .
shell> chown -R mysql data mysql-files
shell> bin/mysqld_safe --user=mysql &
# Next command is optional
shell> cp support-files/mysql.server /etc/init.d/mysql.server

安装之前首先检查有没有mysql的进程

mysqlProcessNum=`/bin/ps aux | /bin/grep mysql | /usr/bin/wc -l | /bin/awk '{ print $1 }'`;
if [ $mysqlProcessNum -gt 3 ]; then
    echo "已经安装MySQL"
    exit
fi

然后下载(可以从官网下载,但是个人感觉太慢了,于是就搭建了一个简单的ftp服务器,当然也可以本地上传嘛,在这里我就不细说了)

# download mysql package
yum install libaio   #MySQL的一个依赖包
/usr/bin/yum install awk wget -y
mysqlDownloadURL=ftp://。。。。。。。。。/pub/mysql/mysql-5.7.8-rc-linux-glibc2.5-x86_64.tar.gz;
cd /tmp;
/bin/rm -rf mysql*.tar.gz
/usr/bin/wget $mysqlDownloadURL;

解压,建立软连接

添加用户和用户组(判断一下,如果没添加就添加一下)

packageName=`/bin/ls | /bin/grep mysql*.tar.gz`;
# unpakcage mysql
/bin/tar zxvf $packageName -C /usr/local
mysqlAllNameDir=`/bin/ls -l /usr/local | grep mysql | /bin/awk '{ print $9 }'`
/bin/ln -s $mysqlAllNameDir /usr/local/mysql
userNum=`/bin/cat /etc/passwd | /bin/grep mysql | /bin/awk -F ':' '{ print $1 }' | /usr/bin/wc -l`
if [ $userNum -lt 1 ];then
    /usr/sbin/groupadd mysql
    /usr/sbin/useradd -d /usr/local/mysql -s /sbin/nologin -g mysql mysql
    echo "成功添加"
fi

检查/etc下面是否有my.cnf文件,有的话就干掉,或者备份

/bin/mv /etc/my.cnf /etc/my.cnf.bak

建立mysql-files文件夹并且赋予770权限

/bin/mkdir /usr/local/mysql/mysql-files
/bin/chmod 770 /usr/local/mysql/mysql-files
/bin/chown -R mysql /usr/local/mysql/
/bin/chgrp -R mysql /usr/local/mysql/

初始化

/usr/local/mysql/bin/mysql_install_db --user=mysql --datadir=/usr/local/mysql/data
/usr/local/mysql/bin/mysqld --initialize --user=mysql
/usr/local/mysql/bin/mysql_ssl_rsa_setup

写一份配置文件my.cnf 放到/etc下面

/etc/my.cnf (这里也说明一点,MySQL配置文件有参数替换原则)

顺序是这样的

[client]
socket=/usr/local/mysql/mysql-files/mysql.sock
[mysqld]
explicit_defaults_for_timestamp=true
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql-files/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# LOG
slow_query_log = 1
slow_query_log_file = /usr/local/mysql/mysql-files/mysql-slow.log
long_query_time = 2
# GENERAL LOG
#general_log = 1
#general_log_file = /usr/local/mysql/mysql-files/mysql-general.log
# BINARY LOG
server_id=101
log_bin=/usr/local/mysql/mysql-files/mysql-bin.log
binlog_format=ROW
sync_binlog=1
expire_logs_days=7
# ERROR LOG
log_error=/usr/local/mysql/mysql-files/mysql.err

# OTHER
character_set_server = utf8mb4
transaction-isolation = READ-COMMITTED
max_connections = 1000
log-queries-not-using-indexes
log_throttle_queries_not_using_indexes = 10

# INNODB
innodb_strict_mode=1
innodb_file_format=Barracuda
innodb_file_format_max=Barracuda
innodb_read_io_threads=4
innodb_write_io_threads=8 # 8 ~ 12
innodb_io_capacity=1000 # HDD:800 ~ 1200 SSD: 10000+
innodb_adaptive_flushing=1 # SSD: 0
innodb_flush_log_at_trx_commit=1
innodb_max_dirty_pages_pct=75
innodb_buffer_pool_dump_at_shutdown=1
innodb_buffer_pool_load_at_startup=1
innodb_flush_neighbors=1 # SSD:0
innodb_log_file_size=1024M # SSD:4G~8G HDD:1G~2G
innodb_purge_threads=1 # SSD:4
innodb_lock_wait_timeout=3
innodb_print_all_deadlocks=1
pid-file=/usr/local/mysql/data/mysqld/mysqld.pid

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/usr/local/mysql/data/mysqld/mysqld.pid

 

修改使用权限

/bin/chown -R root .
/bin/chown -R mysql /usr/local/mysql/data /usr/local/mysql/mysql-files

 

以safe 方式启动

/usr/local/mysql/bin/mysqld_safe --user=mysql &

 

mysql5.7会生成一个初始化密码,而在之前的版本首次登陆不需要登录。

#重启mysqld
#cd /usr/local/mysql
#./bin/mysqld restart
#mysql5.7有默认密码
cat /root/.mysql_secret 
[root@db mysql]# cat /root/.mysql_secret 
# Password set for user 'root@localhost' at 2016-11-16 19:10:59 
ny8(ko+lhtPu
[root@db mysql] ./bin/mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.8-rc-log

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

下面上完整的脚本

但是因为没有修改默认的密码

所以在回报这样的错

mysql> show databases;
ERROR 1820 (HY000): You must reset your password using ALTER USER statement before executing this statement.

修改密码步骤如下所示

mysql> SET PASSWORD = PASSWORD('123123');
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

然后退出再登录就好了!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#!/bin/bash
# mysql install script, the home directory is /usr/local/mysql-VERSION and the soft link is /usr/local/mysql
yum install libaio
/usr/bin/yum install awk wget -y
config=`/bin/pwd`
mysqlProcessNum=`/bin/ps aux | /bin/grep mysql | /usr/bin/wc -l | /bin/awk '{ print $1 }'`;
if [ $mysqlProcessNum -gt 3 ];then
    echo "已经安装MySQL"
fi

# download mysql package
mysqlDownloadURL=ftp://。。。。。。。。/pub/mysql/mysql-5.7.8-rc-linux-glibc2.5-x86_64.tar.gz;
cd /tmp;
/bin/rm -rf mysql*.tar.gz
/usr/bin/wget $mysqlDownloadURL;
packageName=`/bin/ls | /bin/grep mysql*.tar.gz`;
# unpakcage mysql
/bin/tar zxvf $packageName -C /usr/local
mysqlAllNameDir=`/bin/ls -l /usr/local | grep mysql | /bin/awk '{ print $9 }'`
/bin/ln -s $mysqlAllNameDir /usr/local/mysql
userNum=`/bin/cat /etc/passwd | /bin/grep mysql | /bin/awk -F ':' '{ print $1 }' | /usr/bin/wc -l`
if [ $userNum -lt 1 ];then
    /usr/sbin/groupadd mysql
    /usr/sbin/useradd -d /usr/local/mysql -s /sbin/nologin -g mysql mysql
    echo "成功添加"
fi
#/bin/mv /etc/my.cnf /etc/my.cnf.bak
/bin/mkdir /usr/local/mysql/mysql-files
/bin/chmod 770 /usr/local/mysql/mysql-files
/bin/chown -R mysql /usr/local/mysql/
/bin/chgrp -R mysql /usr/local/mysql/

/usr/local/mysql/bin/mysql_install_db --user=mysql --datadir=/usr/local/mysql/data
/usr/local/mysql/bin/mysqld --initialize --user=mysql
/usr/local/mysql/bin/mysql_ssl_rsa_setup
#我的配置文件放到root目录下面了
/bin/cp $config/my.cnf /etc/    

/bin/chown -R root .
/bin/chown -R mysql /usr/local/mysql/data /usr/local/mysql/mysql-files
/usr/local/mysql/bin/mysqld_safe --user=mysql &
#重启mysqld
cd /usr/local/mysql
./bin/mysqld restart
#mysql5.7有默认密码

cat /root/.mysql_secret 

#cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
#chmod 755 /etc/init.d/mysqld



Pagination