我的总结之nginx https的配置 自己生成ssl证书 curl命令总结 https工作原理 find命令 PolarSSL http协议总结 json url nginx_lua

鉴于公司的业务需要需要,我需要对nginx的ssl模块研究一下,顺便记录一下研究过程。
首先需要将ssl模块配置跑通(前提是要已经with了该模块,可用/data/nginx/sbin/nginx -V 看一下)。现在有了,那就配置吧,先看他自带的默认配置文件,如下
   server {
        listen       1500 ssl;
        server_name  localhost;

        ssl_certificate      cert.pem;
        ssl_certificate_key  cert.key;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }   
    }   
这是它自带的https的默认配置文件,下面我们一项一项研究。
listen 和 server_name 就不说了。
ssl_certificate 和 ssl_certificate_key是一块来使用的。ssl_certificate是ssl的证书,ssl_certificate_key是ssl证书的密钥。现在谈ssl的证书和密钥什么的感觉很突兀,那就先来了解一下ssl证书:
SSL证书是数字证书的一种,类似于驾驶证、护照和营业执照的电子副本。SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layer(SSL)安全协议是由Netscape Communication公司设计开发。该安全协议主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性,现已成为该领域中全球化的标准。由于SSL技术已建立到所有主要的浏览器和WEB服务器程序中,因此,仅需安装服务器证书就可以激活该功能了)。即通过它可以激活SSL协议,实现数据信息在客户端和服务器之间的加密传输,可以防止数据信息的泄露。保证了双方传递信息的安全性,而且用户可以通过服务器证书验证他所访问的网站是否是真实可靠。

上面也说了,很多工作别人都给咱们做了,这里需要我们做的就是安装服务器证书就可以使用https功能了。
ssl证书可以自己颁发,也可以向ssl提供商请求颁发(这里只谈技术问题,先不谈收费问题)。自己颁发是不受浏览器信任的,你每次访问的时候会提示你有危险信息。需要你自己选择是否继续。如果是ssl提供商颁发的证书的话就可以直接访问了。 下面说一下证书的生成过程(包括自己颁发和ssl提供商颁发)。
1.进入你想创建证书和私钥的目录,例如:

$ cd ./conf

2.创建服务器私钥,命令会让你输入一个口令,你自定义输入一个就行了:

$ openssl genrsa -des3 -out server.key 1024
3.生成一个证书请求(CSR)会提示输入省份 城市 域名信息等,重要的是email,email一定要是你的域名后缀的,比如[email protected] 并且可以接收邮件。如果下面是自己颁发的话全部可以不用填,全部用默认的或空的。如果要是向ssl提供商请求的话就需要认真填写了。:

$ openssl req -new -key server.key -out server.csr

这样就有一个csr文件了,将这个文件提交给ssl提供商即可,一般半个钟头到一天的时间就会发给你证书。证书是crt为后缀的。如果是自己颁发,就继续往下走。
4.在加载SSL支持的Nginx并使用上述私钥时除去必须的口令:

$ cp server.key server.key.org
$ openssl rsa -in server.key.org -out server.key

5.最后生成证书(crt):

$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

下面就是修改nginx的配置文件了,
server {
        listen       1500 ssl;
        server_name  localhost;

        ssl_certificate      ./conf/server.crt;
        ssl_certificate_key  ./conf/server.key;
      ....
    }

服务器证书是公开的,会被传送到每一个连接到服务器的客户端。而私钥不是公开的,需要存放在访问受限的文件中,当然,nginx主进程必须有读取密钥的权限。私钥和证书可以存放在同一个文件中,这种情况下,证书文件同样得设置访问限制。当然,虽然证书和密钥存放在同一个文件,只有证书会发送给客户端,密钥不会发送。
然后就是测试了
先通过浏览器来访问:https://localhost:1500 回车后果然会报告不是信任站点,自己选择信任后,就访问成功了。
再通过curl命令来访问,这里先简单介绍一下curl命令:curl是利用URL语法在命令行方式下工作的开源文件传输工具。它被广泛应用在Unix、多种Linux发行版中,并且有DOS和Win32、Win64下的移植版本。curl命令是一个功能强大的网络工具,它能够通过http、ftp等方式下载文件,也能够上传文件。其实curl远不止前面所说的那些功能,大家可以通过man curl阅读手册页获取更多的信息。类似的工具还有wget。它的用法非常多,这里只介绍一些比较实用的用法,
curl -v(小写的v参数) 会打印发送的请求和返回的信息。在调试脚本的时候特别有用
curl -k 平日上网,遇到证书错误一定要小心。但在工作中,经常需要用自签的假证书搭建开发环境。CURL在遇到证书错误时无法使用,使用 -k 参数就可以让它不做证书校验。
curl -H 测试域名绑定,比如:curl -H "Host: www.kuqin.com" http://192.168.1.11
curl -I 查看头信息,响应头信息中包含了很多东西。除了HTTP版本和响应代码,还有Server、Content-Type、Content-Length等信息,如果有写入Cookie的操作,也会体现在头信息中。

使用cURL的 -I 参数,就可以看到这些头信息。比如淘宝的:

# curl -I http://www.taobao.com/
curl -L 跟踪URL跳转  如果遇到了一个多次跳转的URL,可以先用curl的 -L 参数看看,这个URL最终跳转到了什么地方。-L 参数最好配合 -I 使用,不然cURL会把最后一次请求获得的数据输出到控制台。
curl  -w 可以用来测量TCP握手和SSL握手的具体耗时,以访问支付宝为例。
curl -w "TCP handshake: %{time_connect}, SSL handshake: %{time_appconnect}\n" -so /dev/null https://www.alipay.com
上面命令中的w参数表示指定输出格式,time_connect变量表示TCP握手的耗时,time_appconnect变量表示SSL握手的耗时(更多变量请查看文档和实例),s参数和o参数用来关闭标准输出。

ssl握手的耗时大概是tcp握手耗时的3倍左右。

所以如果 curl https://localhost:1500 由于证书不受信任,所以或连接失败。如果 curl -k https://localhost:1500
就可以成功了。好吧,到现在为止终于成功了,虽然是自己颁发的不受信任的证书。


ssl_protocols和ssl_ciphers指令可以用来强制用户连接只能引入SSL/TLS那些强壮的协议版本和强大的加密算法。
CBC模式的加密算法容易受到一些攻击,尤其是BEAST攻击(参见CVE-2011-3389)。可以通过下面配置调整为优先使用RC4-SHA加密算法:

        ssl_ciphers RC4:HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

SSL操作需要消耗CPU资源,所以在多处理器的系统,需要启动多个工作进程,而且数量需要不少于可用CPU的个数。最消耗CPU资源的SSL操作是SSL握手,有两种方法可以将每个客户端的握手操作数量降到最低:第一种是保持客户端长连接,在一个SSL连接发送多个请求,第二种是在并发的连接或者后续的连接中重用SSL会话参数,这样可以避免SSL握手的操作。会话缓存用于保存SSL会话,这些缓存在工作进程间共享,可以使用ssl_session_cache指令进行配置。1M缓存可以存放大约4000个会话。默认的缓存超时是5分钟,可以使用ssl_session_timeout加大它。

当然了这里只是自己颁发了证书,如果后面需要正规机构颁发,我这儿也储备了一篇文章,见nginx中转的一篇。



HTTPS的工作原理
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:
1.浏览器将自己支持的一套加密规则发送给网站。
2.网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
3.获得网站证书之后浏览器要做以下工作:
a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
c) 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
4.网站接收浏览器发来的数据之后要做以下的操作:
a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
b) 使用密码加密一段握手消息,发送给浏览器。
5.浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。另外,HTTPS一般使用的加密与HASH算法如下:
非对称加密算法:RSA,DSA/DSS
对称加密算法:AES,RC4,3DES
HASH算法:MD5,SHA1,SHA256
其中非对称加密算法用于在握手过程中加密生成的密码,对称加密算法用于对真正传输的数据进行加密,而HASH算法用于验证数据的完整性。由于浏览器生成的密码是整个数据加密的关键,因此在传输的时候使用了非对称加密算法对其加密。非对称加密算法会生成公钥和私钥,公钥只能用于加密数据,因此可以随意传输,而网站的私钥用于对数据进行解密,所以网站都会非常小心的保管自己的私钥,防止泄漏。
TLS握手过程中如果有任何错误,都会使加密连接断开,从而阻止了隐私信息的传输。


find命令
find [起始目录] 寻找条件 查找的字符串 操作
起始目录:
    ~ 表示$HOME目录
       . 表示当前目录
       / 表示根目录

寻找条件(常用的):
    -name:按照名字查找
      -perm:安装权限查找
      -prune:不再当前指定的目录下查找
      -user:文件属主来查找
      -group:文件所属组来查找
      -nogroup:查找无有效所属组的文件
      -nouser:查找无有效属主的文件
      -type:按照文件类型查找
-type x 查找类型为 x 的文件,x 为下列字符之一:

b 块设备文件

c 字符设备文件

d 目录文件

p 命名管道(FIFO)

f 普通文件

l 符号链接文件(symbolic links)

s socket文件

-xtype x 与 -type 基本相同,但只查找符号链接文件。

当你想根据名字来查找一个目录时,命令为:find -name 目录名 -type d,也就是说-type d必须放在要查找的目录名的后面,如果放前面会报错。

寻找条件可以是一个用逻辑运算符 not、and、or 组成的复合条件。逻辑运 算符 and、or、not 的含义为:

(1) and:逻辑与,在命令中用“-a”表示,是系统缺省的选项,表示只有当所给的条 件都满足时,寻找条件才算满足。例如:

find –name ’tmp’ –xtype c -user ’inin’    该命令寻找三个给定条件都满足的所有文件

(2) or:逻辑或,在命令中用“-o”表示。该运算符表示只要所给的条件中有一个满足 时,寻找条件就算满足。例如:

find –name ’tmp’ –o –name ’mina*’  该命令查询文件名为’tmp’或是匹配’mina*’的所有文件。

(3) not:逻辑非,在命令中用“!”表示。该运算符表示查找不满足所给条件的文件 。例如:

find ! –name ’tmp’   该命令查询文件名不是’tmp’的所有文件。

操作:
print:表示将结果输出到标准输出。

exec:对匹配的文件执行该参数所给出的shell命令。
      形式为command {} \;,注意{}与\;之间有空格

ok:与exec作用相同,
      区别在于,在执行命令之前,都会给出提示,让用户确认是否执行


PolarSSL

PolarSSL源码,也许是最小巧的ssl代码库。高效、便于移植和集成。尤其适合嵌入式应用。越来越多的应用已经从只支持OpenSSL到可以支持PolarSSL。PolarSSL 宣布加入 ARM 公司。我很高兴的宣布从今天起 PolarSSL 成为了 ARM 的一部分,作为全世界嵌入式芯片最领先的公司 ARM 将为 PolarSSL 带来充分的支持,可以让 PolarSSL 得到更好的发展。我们将继续支持我们已有的客户,同时构建新的生态系统来将 PolarSSL 扩展到新的领域和客户。

使用PolarSSL对字符串进行AES加密,看了源代码半天,也不是太懂。
那个例子有点复杂(加密文件的)。
我现在就需要加密字符串,不知道怎么做?

哎,后来发现只需要简单的两个函数:

aes_setkey_enc(&aes_ctx, key, keylen);
aes_crypt_ecb(&aes_ctx, AES_ENCRYPT, buffer, buffer);


luasocket

http:

最近在研究https,一直卡,最后才发现都是卡在组装http的问题上,所以我决定要好好对http进行一下研究,以防后面再被绊倒。
简介:
HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写。它定义了浏览器(即万维网客户进程)怎样向万维网服务器请求万维网文档,以及服务器怎样把文档传送给浏览器。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。从层次的角度看,HTTP是面向(transaction-oriented)应用层的传输协议,它是万维网上能够可靠地交换文件(包括文本、声音、图像等各种多媒体文件)的重要基础。

构成:由请求和响应构成,是一个标准的客户端服务器模型。

特点:
1.支持客户/服务器模式。支持基本认证和安全认证。
2.简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
3.灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
4.HTTP 1.0使用非持续连接:限制每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  HTTP 1.1使用持续连接:不必为每个web对象创建一个新的连接,一个连接可以传送多个对象。
5.无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。但是,另一方面,在服务器不需要先前信息时它的应答就较快。有利有弊吧!

内容详述:
前面已经说过了协议由请求和响应构成,所以这里就详述一下请求和响应。先说请求:
    通常HTTP消息包括客户机向服务器的请求消息和服务器向客户机的响应消息。这两种类型的消息由一个起始行,一个或者多个头域,一个只是头域结束的空行和可选的消息体组成。HTTP的头域包括通用头,请求头,响应头和实体头四个部分。每个头域由一个域名,冒号(:)和域值三部分组成。域名是大小写无关的,域值前可以添加任何数量的空格符,头域可以被扩展为多行,在每行开始处,使用至少一个空格或制表符。



一个标准的HTTP请求由以下几个部分组成

    请求行:用来说明请求类型、要访问的资源(URL)以及使用的HTTP版本。格式为:请求类型 + 请求路径(如果只有一个 / ,那说明请求的是该域名的根目录)+ 协议版本。例子: GET / HTTP/1.1  GET /lua HTTP/1.1(请求路径 /lua 下的内容)

请求方法:
HTTP/1.1协议中共定义了八种方法(有时也叫“动作”)来表明Request-URI指定的资源的不同操作方式:

HEAD- 向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
GET - 向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在web app.中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
POST - 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT - 向指定资源位置上传其最新内容。
DELETE - 请求服务器删除Request-URI所标识的资源。
TRACE- 回显服务器收到的请求,主要用于测试或诊断。
CONNECT - HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
PATCH - 用来将局部修改应用于某一资源,添加于规范RFC5789。
方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed);当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。
HTTP服务器至少应该实现GET和POST方法,其他方法都是可选的。当然,所有的方法支持的实现都应当符合下述的方法各自的语义定义。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。

OPTIONS - 返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。(后面需要研究一下)

    多行头部(headers):用来说明服务器要使用的附加信息。根据需要可以有多行,该部分以一个空行结束,以表示首部结束。
 HTTP头域分为四种:通用头域、请求头域、响应头域和实体头域。每个头域由一个域名、冒号和域值三部分组成,域名大小写无关,域值前可以添加任何数量的空格符。
通用头域是指请求和响应都支持的HTTP头域,最常见的有Cache-Control、Connection和Transfer-Encoding等
请求头域是只有在请求头中带有的,用于向服务器传递关于请求或者关于客户端的附件信息。常见的有:Accept、Accept-Encoding、Accept-Language、Accept-Charset、Host、Referer、User-Agent和Cookie等。
响应头域只在HTTP响应中出现。
实体首部提供有关实体及其内容的大量信息,从有关对象类型的信息,到能够对资源使用的各种有效的请求方法。以及对http报文负荷的描述。总之,实体首部可以告知报文的接收者它在对什么进行处理。请求和响应头部均可能包含实体首部。
实体报头
  请求和响应消息都可以传送一个实体。一个实体由实体报头域和实体正文组成,大多数情况下,实体正文就是请求消息中的请求正文或者响应消息中的响应正文。但是在发送时,并不是说实体报头域和实体正文要在一起发送,例如:有些响应可以只包含实体报头域。实体就好象我们写的书信,在信中,我们可以写上标题,加上页号等,这部分就相当于是实体报头域,而我们所写的书信的内容,就相当于实体正文。前面说讲的普通报头、请求报头、响应报头我们可以看成是写在信封上的邮编、接收者,发送者等内容。
 实体报头定义了关于实体正文(例如:有无实体正文)和请求所标识的资源的元信息。
 所谓元信息,是指描述其他信息的信息。
 
 常用的实体报头域:
  Content-Encoding
      Content-Encoding实体报头域被使用作媒体类型的修饰符,它的值指示了已经被应用到实体正文的附加内容编码,因而要获得Content-Type报头域中所引用的媒体类型,必须采用相应的解码机制。Content-Encoding主要用语记录文档的压缩方法,下面是它的一个例子:Content-Encoding: gzip。如果一个实体正文采用了编码方式存储,在使用之前就必须进行解码。
  Content-Language
      Content-Language实体报头域描述了资源所用的自然语言。Content-Language允许用户遵照自身的首选语言来识别和区分实体。如果这个实体内容仅仅打算提供给丹麦的阅读者,那么可以按照如下的方式设置这个实体报头域:Content-Language: da。
如果没有指定Content-Language报头域,那么实体内容将提供给所以语言的阅读者。
  Content-Length
      Content-Length实体报头域用于指明正文的长度,以字节方式存储的十进制数字来表示,也就是一个数字字符占一个字节,用其对应的ASCII码存储传输。
      要注意的是:这个长度仅仅是表示实体正文的长度,没有包括实体报头的长度。
  Content-Type
      Content-Type实体报头域用语指明发送给接收者的实体正文的媒体类型。例如:
   Content-Type: text/html;charset=ISO-8859-1
   Content-Type: text/html;charset=GB2312
  Last-Modified
      Last-Modified实体报头域用于指示资源最后的修改日期及时间。
  Expires
      Expires实体报头域给出响应过期的日期和时间。通常,代理服务器或浏览器会缓存一些页面。当用户再次访问这些页面时,直接从缓存中加载并显示给用户,这样缩短了响应的时间,减少服务器的负载。为了让代理服务器或浏览器在一段时间后更新页面,我们可以使用Expires实体报头域指定页面过期的时间。当用户又一次访问页面时,如果Expires报头域给出的日期和时间比Date普通报头域给出的日期和时间要早(或相同),那么代理服务器或浏览器就不会再使用缓存的页面而是从服务器上请求更新的页面。不过要注意,即使页面过期了,也并不意味着服务器上的原始资源在此时间之前或之后发生了改变。
      Expires实体报头域使用的日期和时间必须是RFC 1123中的日期格式,例如:
   Expires: Thu, 15 Sep 2005 16:00:00 GMT
      HTTP1.1的客户端和缓存必须将其他非法的日期格式(也包括0)看作已过期。例如,为了让浏览器不要缓存页面,我们也可以利用Expires实体报头域,设置它的值为0,如下(JSP):response.setDateHeader("Expires",0);
 HTTP请求和响应中都可以包含实体头域,实体头域包含实体内容的一些信息。常见的实体头域有:Content-Encoding、Content-Length、Content-Type和Expires等。
HTTP头部详解
1、 Accept:告诉WEB服务器自己接受什么介质类型,*/* 表示任何类型,type/* 表示该类型下的所有子类型,type/sub-type。
2、 Accept-Charset: 浏览器申明自己接收的字符集
Accept-Encoding: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate)
Accept-Language::浏览器申明自己接收的语言
语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等。
3、 Accept-Ranges:WEB服务器表明自己是否接受获取其某个实体的一部分(比如文件的一部分)的请求。bytes:表示接受,none:表示不接受。
4、 Age:当代理服务器用自己缓存的实体去响应请求时,用该头部表明该实体从产生到现在经过多长时间了。
5、 Authorization:当客户端接收到来自WEB服务器的 WWW-Authenticate 响应时,用该头部来回应自己的身份验证信息给WEB服务器。
6、 Cache-Control:请求:no-cache(不要缓存的实体,要求现在从WEB服务器去取)
max-age:(只接受 Age 值小于 max-age 值,并且没有过期的对象)
max-stale:(可以接受过去的对象,但是过期时间必须小于 max-stale 值)
min-fresh:(接受其新鲜生命期大于其当前 Age 跟 min-fresh 值之和的缓存对象)
响应:public(可以用 Cached 内容回应任何用户)
private(只能用缓存内容回应先前请求该内容的那个用户)
no-cache(可以缓存,但是只有在跟WEB服务器验证了其有效后,才能返回给客户端)
max-age:(本响应包含的对象的过期时间)
ALL: no-store(不允许缓存)
7、 Connection:请求:close(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,断开连接,不要等待本次连接的后续请求了)。
keepalive(告诉WEB服务器或者代理服务器,在完成本次请求的响应后,保持连接,等待本次连接的后续请求)。
响应:close(连接已经关闭)。
keepalive(连接保持着,在等待本次连接的后续请求)。
Keep-Alive:如果浏览器请求保持连接,则该头部表明希望 WEB 服务器保持连接多长时间(秒)。例如:Keep-Alive:300
8、 Content-Encoding:WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象。例如:Content-Encoding:gzip
9、Content-Language:WEB 服务器告诉浏览器自己响应的对象的语言。
10、Content-Length: WEB 服务器告诉浏览器自己响应的对象的长度。例如:Content-Length: 26012
11、Content-Range: WEB 服务器表明该响应包含的部分对象为整个对象的哪个部分。例如:Content-Range: bytes 21010-47021/47022
12、Content-Type: WEB 服务器告诉浏览器自己响应的对象的类型。例如:Content-Type:application/xml
13、 ETag:就是一个对象(比如URL)的标志值,就一个对象而言,比如一个 html 文件,如果被修改了,其 Etag 也会别修改,所以ETag 的作用跟 Last-Modified 的作用差不多,主要供 WEB 服务器判断一个对象是否改变了。比如前一次请求某个 html 文件时,获得了其 ETag,当这次又请求这个文件时,浏览器就会把先前获得的 ETag 值发送给WEB 服务器,然后 WEB 服务器会把这个 ETag 跟该文件的当前 ETag 进行对比,然后就知道这个文件有没有改变了。
14、 Expired:WEB服务器表明该实体将在什么时候过期,对于过期了的对象,只有在跟WEB服务器验证了其有效性后,才能用来响应客户请求。是 HTTP/1.0 的头部。例如:Expires:Sat, 23 May 2009 10:02:12 GMT
15、 Host:客户端指定自己想访问的WEB服务器的域名/IP 地址和端口号。例如:Host:rss.sina.com.cn
16、 If-Match:如果对象的 ETag 没有改变,其实也就意味著对象没有改变,才执行请求的动作。
17、If-None-Match:如果对象的 ETag 改变了,其实也就意味著对象也改变了,才执行请求的动作。
18、 If-Modified-Since:如果请求的对象在该头部指定的时间之后修改了,才执行请求的动作(比如返回对象),否则返回代码304,告诉浏览器该对象没有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT
19、If-Unmodified-Since:如果请求的对象在该头部指定的时间之后没修改过,才执行请求的动作(比如返回对象)。
20、 If-Range:浏览器告诉 WEB 服务器,如果我请求的对象没有改变,就把我缺少的部分给我,如果对象改变了,就把整个对象给我。浏览器通过发送请求对象的 ETag 或者 自己所知道的最后修改时间给 WEB 服务器,让其判断对象是否改变了。总是跟 Range 头部一起使用。
21、 Last-Modified:WEB 服务器认为对象的最后修改时间,比如文件的最后修改时间,动态页面的最后产生时间等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT
22、 Location:WEB 服务器告诉浏览器,试图访问的对象已经被移到别的位置了,到该头部指定的位置去取。例如:Location:http://i0.sinaimg.cn/dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif
23、 Pramga:主要使用 Pramga: no-cache,相当于 Cache-Control: no-cache。例如:Pragma:no-cache
24、 Proxy-Authenticate: 代理服务器响应浏览器,要求其提供代理身份验证信息。Proxy-Authorization:浏览器响应代理服务器的身份验证请求,提供自己的身份信息。
25、 Range:浏览器(比如 Flashget 多线程下载时)告诉 WEB 服务器自己想取对象的哪部分。例如:Range: bytes=1173546-
26、 Referer:浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得/点击 当前请求中的网址/URL。例如:Referer:http://www.sina.com/
27、 Server: WEB 服务器表明自己是什么软件及版本等信息。例如:Server:Apache/2.0.61 (Unix)
28、 User-Agent: 浏览器表明自己的身份(是哪种浏览器)。例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/2、0、0、14
29、 Transfer-Encoding: WEB 服务器表明自己对本响应消息体(不是消息体里面的对象)作了怎样的编码,比如是否分块(chunked)。例如:Transfer-Encoding: chunked
30、 Vary: WEB服务器用该头部的内容告诉 Cache 服务器,在什么条件下才能用本响应所返回的对象响应后续的请求。假如源WEB服务器在接到第一个请求消息时,其响应消息的头部为:Content-Encoding: gzip; Vary: Content-Encoding那么 Cache 服务器会分析后续请求消息的头部,检查其 Accept-Encoding,是否跟先前响应的 Vary 头部值一致,即是否使用相同的内容编码方法,这样就可以防止 Cache 服务器用自己 Cache 里面压缩后的实体响应给不具备解压能力的浏览器。例如:Vary:Accept-Encoding
31、 Via: 列出从客户端到 OCS 或者相反方向的响应经过了哪些代理服务器,他们用什么协议(和版本)发送的请求。当客户端请求到达第一个代理服务器时,该服务器会在自己发出的请求里面添加 Via 头部,并填上自己的相关信息,当下一个代理服务器收到第一个代理服务器的请求时,会在自己发出的请求里面复制前一个代理服务器的请求的Via 头部,并把自己的相关信息加到后面,以此类推,当 OCS 收到最后一个代理服务器的请求时,检查 Via 头部,就知道该请求所经过的路由。例如:Via:1.0 236.D0707195.sina.com.cn:80 (squid/2.6.STABLE13)


     (空行,显示头部结束)

    主体数据(request-body)(即我们通常所说的body,是可选的)。

    (空行,用于标明body部分结束)

注意:
1.头部信息之后是一个回车换行符(\r\n),用于标明头部信息的结束。
2.主体数据之后是一个回车换行符(\r\n),用于标明主体数据的结束。
3.空行内必须只有而无其他空格。
4.在HTTP/1.1协议中,所有的请求头,除host外,都是可选的。
5.请求行(request-line)中的URL部分必须以application/x-www-form-urlencoded方式编码。
注:application/x-www-form-urlencoded含义是表示客户端提交给服务器文本内容的编码方式 是URL编码,即除了标准字符外,每字节以双字节16进制前加个“%”表示,
6.主体数据(request-body)的编码方式由头部(headers)信息中的Content-Type指定。
7.主体数据(request-body)的长度由头部(headers)信息中的Content-Length指定。


http的请求就先说到这里吧,下面继续说http的响应。

一个http的响应由以下3部分组成:状态行   若干消息头  实体内容

状态行:主要用来返回客户端请求后的服务的返回情况。以HTTP协议版本开头,后面跟着状态码和简单的状态描述,格式如下:

       HTTP-Version  Status-Code Reason-Phrase  CRLF

       其中的Status-Code是一个三个数字组成的返回状态码,Reason-Phrase提供一个简单的状态描述,如对于200成功页面就是“OK”,对于404页面未找到错误就是“Not Found”。

 HTTP应答的状态行根据状态码可以分为五种类型:

(1)1xx:信息,请求收到,继续处理;

(2)2xx:成功,行为被成功地接受、理解和采纳;

(3)3xx:重定向,为了完成请求,必须进一步执行的动作;

(4)4xx:客户端错误,请求包含语法错误或者请求无法实现;

(5)5xx:服务端错误,服务器不能正确执行一个正确的请求。

常见的几种返回状态码为:
状态码        含义
200        正确返回结果
302        页面跳转
304        页面未改动
400        请求错误,不符合协议
404        请求的页面未找到
405        方法不允许
501        未被使用
503        服务不可用

若干消息头:允许服务器传递不能放在状态行中的附件信息,主要用于描述服务器的信息和Request URI的进一步信息,一般在返回中的是响应头,具体上面已经提到过了。

实体内容:实际上就是body部分,一般返回HTML内容,也可返回其他内容。头与实体之间由回车换行的空行(CRLF)分开。



http中的表单:表单在网页中主要负责数据采集功能。一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法。 表单域:包含了文本框、密码框、隐藏域、多行文本框、复选框、单选框、下拉选择框和文件上传框等。 表单按钮:包括提交按钮、复位按钮和一般按钮;用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作。
在使用HTTP协议进行请求时,HTTP协议头部会添加User-Agent,该信息可以标识请求者的一些信息,如什么浏览器类型和版本、操作系统,使用语言等信息。

get和post的最主要区别:其中比较重要的一条,那就是数据传输的位置不同。
GET方式在request-line中传送数据;POST方式在request-line及request-body中均可以传送数据。

json

从结构上看,所有的数据(data)最终都可以分解成三种类型:

    第一种类型是标量(scalar),也就是一个单独的字符串(string)或数字(numbers),比如"北京"这个单独的词。

    第二种类型是序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组(array)或列表(List),比如"北京,上海"。

    第三种类型是映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary),比如"首都:北京"。

我恍然大悟,数据构成的最小单位原来如此简单!难怪在编程语言中,只要有了数组(array)和对象(object)就能够储存一切数据了。(插一句c语言中没有对象数据存储方式,而lua语言中有,我想这也许是催生lua语言的原因吧,另外lua语言可以转换成c语言)

21世纪初,Douglas Crockford寻找一种简便的数据交换格式,能够在服务器之间交换数据。当时通用的数据交换语言是XML,但是Douglas Crockford觉得XML的生成和解析都太麻烦,所以他提出了一种简化格式,也就是Json。

Json的规格非常简单,只用一个页面几百个字就能说清楚,而且Douglas Crockford声称这个规格永远不必升级,因为该规定的都规定了。

    1) 并列的数据之间用逗号(", ")分隔。

    2) 映射用冒号(": ")表示。

    3) 并列数据的集合(数组)用方括号("[]")表示。

    4) 映射的集合(对象)用大括号("{}")表示。

上面四条规则,就是Json格式的所有内容。


URL

URL是Uniform Resource Location的缩写,译为“统一资源定位符”。通俗地说,URL是Internet上用来描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上,特别是著名的Mosaic。采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。
URL的格式URL的格式由下列三部分组成:
第一部分是协议(或称为服务方式);
第二部分是存有该资源的主机IP地址(有时也包括端口号);
第三部分是主机资源的具体地址。,如目录和文件名等。
第一部分和第二部分之间用“://”符号隔开,第二部分和第三部分用“/”符号隔开。第一部分和第二部分是不可缺少的,第三部分有时可以省略。

参数:为了使服务器更好的服务,url中有一个参数组件,这个组件就是url中的kv列表,由字符‘;’将其与url的其余部分(以及各kv对)分隔开来。他们为应用程序提供了访问资源所需的所有附加信息。比如:ftp://prep.ai.mit.edu/pub/gnu;type=d   http url 的路径组件可以分成若干路径段。每段都可以有自己的参数。


nignx oauth http://www.oschina.net/translate/oauth-support-for-nginx-with-lua


nignx lua
终于要考虑在nginx下使用lua啊啦,这里首先不得不提的就是lua-nginx-module了,nginx_lua_module是由淘宝的工程师清无(王晓哲)和春来(章亦春)所开发的nginx第三方模块,它能将lua语言嵌入到nginx配置中,从而使用lua就极大增强了nginx的能力,ngx_lua_module 是一个nginx http模块,它把 lua 解析器内嵌到 nginx,用来解析并执行lua 语言编写的网页后台脚本。这个模块的特性为:特性:

    支持Windows和Linux平台。
    支持高并发高性能。
    HTML网页中内嵌LUA脚本代码,类似于PHP。
    支持非阻塞的数据库操作,目前只支持MYSQL。
    支持异步的文件IO操作。
    支持非阻塞的SOCKET IO操作。

还有一个模块是:echo-nginx-module 这个模块可以用来输出一些简单的信息,这个模块不包含在 Nginx 源码中,需要另外加载安装,该模块是国人 章亦春 开发的。

还有ngx_devel_kit(NDK)模块是一个拓展nginx服务器核心功能的模块,第三方模块开发可以基于它来快速实现。

NDK提供函数和宏处理一些基本任务,减轻第三方模块开发的代码量。

开发者如果要依赖这个模块做开发,需要将这个模块一并参与nginx编译,同时需要在自己的模块配置中声明所需要使用的特性。

PCRE(Perl Compatible Regular Expressions中文含义:perl语言兼容正则表达式)是一个用C语言编写的正则表达式函数库,由菲利普.海泽(Philip Hazel)编写。PCRE是一个轻量级的函数库,比Boost之类的正则表达式库小得多。PCRE十分易用,同时功能也很强大,性能超过了POSIX正则表达式库和一些经典的正则表达式库

zlib是提供数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用DEFLATE算法,最初是为libpng函式库所写的,后来普遍为许多软件所使用。此函式库为自由软件,使用zlib授权。

好了,现在该有的都有了,可以开工研究了:
先来配置一下配置文件增加如下:
        location /lua {                                                         
            default_type  'text/plain';
            content_by_lua  'ngx.say("hello,lua")';
        }   

        location /echo {
            default_type 'text/plain';
            echo "hello echo";
        }

然后你就可以在浏览器或者用curl来返回你的服务器记得加路径哦,然后...,你就看到了。

继续研究,ngx_lua介绍

原理

ngx_lua将Lua嵌入Nginx,可以让Nginx执行Lua脚本,并且高并发、非阻塞的处理各种请求。Lua内建协程,这样就可以很好的将异步回调转换成顺序调用的形式。ngx_lua在Lua中进行的IO操作都会委托给Nginx的事件模型,从而实现非阻塞调用。开发者可以采用串行的方式编写程序,ngx_lua会自动的在进行阻塞的IO操作时中断,保存上下文;然后将IO操作委托给Nginx事件处理机制,在IO操作完成后,ngx_lua会恢复上下文,程序继续执行,这些操作都是对用户程序透明的。

每个NginxWorker进程持有一个Lua解释器或者LuaJIT实例,被这个Worker处理的所有请求共享这个实例。每个请求的Context会被Lua轻量级的协程分割,从而保证各个请求是独立的。

ngx_lua采用“one-coroutine-per-request”的处理模型,对于每个用户请求,ngx_lua会唤醒一个协程用于执行用户代码处理请求,当请求处理完成这个协程会被销毁。每个协程都有一个独立的全局环境(变量空间),继承于全局共享的、只读的“comman data”。所以,被用户代码注入全局空间的任何变量都不会影响其他请求的处理,并且这些变量在请求处理完成后会被释放,这样就保证所有的用户代码都运行在一个“sandbox”(沙箱),这个沙箱与请求具有相同的生命周期。

得益于Lua协程的支持,ngx_lua在处理10000个并发请求时只需要很少的内存。根据测试,ngx_lua处理每个请求只需要2KB的内存,如果使用LuaJIT则会更少。所以ngx_lua非常适合用于实现可扩展的、高并发的服务。

协程

协程类似一种多线程,与多线程的区别有:

    协程并非os线程,所以创建、切换开销比线程相对要小。
    协程与线程一样有自己的栈、局部变量等,但是协程的栈是在用户进程空间模拟的,所以创建、切换开销很小。
    多线程程序是多个线程并发执行,也就是说在一瞬间有多个控制流在执行。而协程强调的是一种多个协程间协作的关系,只有当一个协程主动放弃执行权,另一个协程才能获得执行权,所以在某一瞬间,多个协程间只有一个在运行。
    由于多个协程时只有一个在运行,所以对于临界区的访问不需要加锁,而多线程的情况则必须加锁。
    多线程程序由于有多个控制流,所以程序的行为不可控,而多个协程的执行是由开发者定义的所以是可控的。

Nginx的每个Worker进程都是在epoll或kqueue这样的事件模型之上,封装成协程,每个请求都有一个协程进行处理。这正好与Lua内建协程的模型是一致的,所以即使ngx_lua需要执行Lua,相对C有一定的开销,但依然能保证高并发能力。
二、ngx_lua安装

Nginx中安装ngx_lua需要安装LuaJIT,ngx_devel_kit,ngx_lua等安装文件,我们这里用的OpenResty,内部已经集成ngx_lua,无需再安装任何模块。
三、ngx_lua用法

嵌套lua脚本

使用 content_by_lua 把lua脚本嵌入到Nginx配置里,或者使用 content_by_lua_file 把Lua脚本载入到Nginx配置里.

location /lua {
set $test "hello, world";
content_by_lua '
    ngx.header.content_type = "text/plain";
    ngx.say(ngx.var.test);
';
}

$ curl 'http://134.32.28.134:8888/lua',输出 hello, world。

include lua文件

Nginx中include lua的脚本文件方式,如:

 location /mytest {    
      content_by_lua_file conf/alcache.lua;       
 }

其中在alcache.lua中编写lua脚本即可。

确实是通过这样,便可以在alcache.lua中编写lua脚本,但有几点还是要说明一下,1.在脚本中写print语句是不会返回值的,如果你需要返回“hello world”什么的,需要用ngx.say("hello world")这个函数。我说之前怎么一直不打印hello world呢。另外,这样写了,只能在curl中访问,在浏览器中访问时它会提示你打开这个文件。至于为什么目前也不清楚,后面有时间了再研究吧。还有就是放文件的目录可以在根目录下面随便调,但是我调到家目录它就报错了。应该是只能在根目录下面放吧。

在调试的过程中还遇到了lua_package_path,查了查后才知道它是指定搜索路径的,索性将lua中指定路径的方法总结一下吧:

如果是一个 *.LUA 的文件, 里面用到了自己写的库, 或者第三方写的库, 但是你不想把它放到 lua 的安装目录里, 则在代码里面可以指定require搜索的路径。


    package.path = '/usr/local/share/lua/5.1/?.lua;/home/resty/?.lua;'    --搜索lua模块
    package.cpath = '/usr/local/lib/lua/5.1/?.so;'        --搜索so模块


如果是要在 nginx.conf 文件中引用第三方的库,则需要在 http 段中添加下面的代码

    lua_package_path '/usr/local/share/lua/5.1/?.lua;/home/resty/?.lua;';
    lua_package_cpath '/usr/local/lib/lua/5.1/?.so;';


四、实际运用中通过lua结合分布式缓存对session的处理

这里redis与memcache的支持不是调用Nginx自带redis与memcache模块,都是调用OpenResty内部集成的第三方模块

nginx.conf部分配置

location /login {    
    content_by_lua_file conf/alcache.lua;       
}

alcache.lua配置

local key = tostring(ngx.var.arg_username)
local val = tostring(ngx.var.arg_password)
local passLogin = tostring(ngx.var.arg_passLoginFlag)
local flags = tostring(ngx.var.arg_flags or 0)
local exptime = tostring(ngx.var.arg_exptime or 0)
local sessionId  = tostring(ngx.var.cookie_JSESSIONID)

ngx.say("sessionId:",sessionId)
ngx.say("key:",key)
ngx.say("val:",val)

if (key == nil and val == nil)  then return end
--if (passLogin == nil or sessionId == nil)  then return end

local memcached = require("resty.memcached")
--local redis = require("resty.redis")
local cache,err = memcached:new()
--local cache,err = redis.new()

if not cache then
        ngx.say("failed to instantiate cache: ",err)
        return
end


cache:set_timeout(1000)

local ok,err = cache:connect("134.32.28.134",11211)
--local ok,err = cache:connect("134.32.28.134",6379)
if not ok then
        ngx.say("failed to connect: ",err)
        return
end


local res,flags,err = cache:get(key)
if err then
        ngx.say("failed to get ",key," : ",err)
        return
end
if res and tostring(res) ~= sessionId then
        cache:delete(key)
        cache:set(key,sessionId,exptime,flags)
else
                cache:set(key,sessionId,exptime,flags)
end


local ok, err = cache:close()  
                if not ok then  
            ngx.say("failed to close:", err)  
        return  
end

local url = ngx.var.uri  
local res = ngx.location.capture("/proxy")  

最近在研究https,https就是在http之上增加了ssl层,所以这里需要研究了一下ssl层,经过一段时间的研究后觉得它也不是很难,但也需要总结一下:
对于ssl的一些基本介绍就不多说了,这里只说重点,先说一下ssl的基本过程:
1.客户端:给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
2.服务端:确认版本号是否一致,不一致直接中断。
           一致继续:确认双方要使用的加密方法(我认为是要使用的),并给出数字证书(包含加密公钥)、以及一个服务器生成的随机数(Server random)。
3.客户端:确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数。根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。并且要通知给服务端,下次交流用“交流密钥”进行加密。

4.服务器收到客户端的第三个随机数pre-master key之后,计算生成本次会话所用的"会话密钥"。

至此,整个握手阶段全部结束。接下来,客户端与服务器进入加密通信,就完全是使用普通的HTTP协议,只不过用"会话密钥"加密内容。

三个问题:
1.如何保证公钥不被篡改?

    解决方法:将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。

2.公钥加密计算量太大,如何减少耗用的时间?

    解决方法:每一次对话(session),客户端和服务器端都生成一个"对话密钥"(session key),用它来加密信息。由于"对话密钥"是对称加密,所以运算速度非常快,而服务器公钥只用于加密"对话密钥"本身,这样就减少了加密运算的消耗时间。

3.为什么一定要用三个随机数,来生成"会话密钥",dog250解释得很好:

    "不管是客户端还是服务器,都需要随机数,这样生成的密钥才不会每次都一样。由于SSL协议中证书是静态的,因此十分有必要引入一种随机因素来保证协商出来的密钥的随机性。

    对于RSA密钥交换算法来说,pre-master-key本身就是一个随机数,再加上hello消息中的随机,三个随机数通过一个密钥导出器最终导出一个对称密钥。

    pre master的存在在于SSL协议不信任每个主机都能产生完全随机的随机数,如果随机数不随机,那么pre master secret就有可能被猜出来,那么仅适用pre master secret作为密钥就不合适了,因此必须引入新的随机因素,那么客户端和服务器加上pre master secret三个随机数一同生成的密钥就不容易被猜出了,一个伪随机可能完全不随机,可是是三个伪随机就十分接近随机了,每增加一个自由度,随机性增加的可不是一。"

注意:握手之后的对话使用"对话密钥"加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。

延伸:session的恢复

握手阶段用来建立SSL连接。如果出于某种原因,对话中断,就需要重新握手。



这时有两种方法可以恢复原来的session:一种叫做session ID,另一种叫做session ticket。

session ID的思想很简单,就是每一次对话都有一个编号(session ID)。如果对话中断,下次重连的时候,只要客户端给出这个编号,且服务器有这个编号的记录,双方就可以重新使用已有的"对话密钥",而不必重新生成一把。

session ID是目前所有浏览器都支持的方法,但是它的缺点在于session ID往往只保留在一台服务器上。所以,如果客户端的请求发到另一台服务器,就无法恢复对话。session ticket就是为了解决这个问题而诞生的,目前只有Firefox和Chrome浏览器支持。客户端不再发送session ID,而是发送一个服务器在上一次对话中发送过来的session ticket。这个session ticket是加密的,只有服务器才能解密,其中包括本次对话的主要信息,比如对话密钥和加密方法。当服务器收到session ticket以后,解密后就不必重新生成对话密钥了。


总结:由加密一个“password”引发的“血案”,一开始的时候想得是找一个C或者lua的加密算法实现程序,然后两边加密,最后止于编码问题。转向https,一个系统的密码保护机制是否安全取决于两个方面,即密码传输的安全性和密码存储的安全性。新浪微博和MySQL都没有采用HTTPS/SSL传输密码。为了防止黑客在密码传输过程中窃听密码,它们只能在传输过程中加盐然后用SHA1算法加密。由于密码在传输过程中需要加盐,为了能够正常验证密码,因此在存储密码时只能存储没有加盐的SHA1算法的哈希值。因此密码的存储成为整个机制的短板。

笔者曾写过一篇博客讨论如何安全地存储密码。感兴趣的读者请参考http://blog.csdn.net/cadcisdhht/article/details/19282407。

我们没有必要在抛弃HTTPS/SSL的前提下试图去设计更加复杂的加密算法或者通讯协议。上述提到的两个方案是新浪微博和MySQL的程序员们花了大量精力设计出来的机制,尚且还有明显的漏洞。我不觉得每个程序员都有自信说自己比新浪微博或者MySQL的程序员更加优秀。

HTTPS/SSL在传输过程中用证书加密,不需要加盐来提高传输的安全性。这样在存储密码的时候就可以采用加盐的机制,比如简单地采用加盐的SHA1算法,也可以采用Bcrypt或者PBKDF2。如此以来,在密码的传输和存储两个环节都取得很好的安全性。

如果安全性对一个系统是至关重要的因素,那么就采用HTTPS/SSL吧。虽然部署HTTPS/SSL的系统有些麻烦,申请可信赖的CA的证书还要花钱,但和安全漏洞的潜在风险相比这些代价还是值得的。(业界已经达成共识,在传输用户密码等需要保密的信息时,尽可能采用HTTPS/SSL协议传输。)



什么是TCP/IP模型?

TCP/IP模型是一系列网络协议的总称,这些协议的目的,就是使计算机之间可以进行信息交换。

所谓"协议"可以理解成机器之间交谈的语言,每一种协议都有自己的目的。TCP/IP模型一共包括几百种协议,对互联网上交换信息的各个方面都做了规定。

理解这个结构的关键,在于理解科学家在70年代设计互联网的原始目的,就是为了传输文本。所有协议最初都是为了这个目标而设计的,互联网架构的核心就是文本对话。

当然这个模型包含了5(7)层结构

关于回车和换行

'\r'是回车,'\n'是换行,前者使光标到行首,后者使光标下移一行。通常用的Enter是两个加起来。

回车和换行
今天,我总算搞清楚“回车”(carriage return)和“换行”(line feed)这两个概念的来历和区别了。
在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。

于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。

这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。

后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。

Unix系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<换行><回车>”,即“\n\r”;Mac系统里,每行结尾是“<回车>”。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个^M符号。

c语言编程时(windows系统,linux系统中也是如此,我刚刚测过)\r 就是return 回到 本行 行首 这就会把这一行以前的输出 覆盖掉
如:
int main() {
cout << "hahaha" << "\r" << "xixi" ;
}
最后只显示 xixi 而 hahaha 被覆盖了
\n 是回车+换行 把光标 先移到 行首 然后换到下一行 也就是 下一行的行首拉
int main() {
cout << "hahaha" << "\n" << "xixi" ;
}
则 显示
hahaha
xixi

又遇到一个好东西:
cat > test.txt << EOF  创建文件  test.txt 输入   当输入 EOF时,结束。退出。

今天又遇到linux下的echo命令:
echo命令的功能是在显示器上显示一段文字,一般起到一个提示的作用。
该命令的一般格式为: echo [ -n ] 字符串
其中选项n表示输出文字后不换行;字符串能加引号,也能不加引号。

功能说明:显示文字。
语   法:echo [-ne][字符串]或 echo [--help][--version]
补充说明:echo会将输入的字符串送往标准输出。输出的字符串间以空白字符隔开, 并在最后加上换行号。
参   数:-n 不要在最后自动换行
-e 若字符串中出现以下字符,则特别加以处理,而不会将它当成一般
文字输出:
   \a 发出警告声;
   \b 删除前一个字符;
   \c 最后不加上换行符号;
   \f 换行但光标仍旧停留在原来的位置;
   \n 换行且光标移至行首;
   \r 光标移至行首,但不换行;
   \t 插入tab;
   \v 与\f相同;
   \\ 插入\字符;
   \nnn 插入nnn(八进制)所代表的ASCII字符;

最近在研究数字证书,简单总结一下:数字证书的出现是为了解决为你的公钥找一个公正人,就是说确定这个公钥就是你的,你的数字证书由谁颁发呢,CA(证书授权机构),但是要注意的是这里CA只是个泛称,不是特指某个机构,目前国内的比较出名的CA为GlobalSign。证书的内容包括:电子签证机关的信息、公钥用户信息、公钥、权威机构的签字和有效期等等。目前,证书的格式和验证方法普遍遵循X.509 国际标准。现在就是呢,你的证书是由CA用它的私钥加密后形成的,客户端拥有CA的公钥,收到证书后,你用CA的公钥解密然后取出服务器的公钥。这样就能确定是你请求的服务器的公钥。但是现在有一个问题,CA的公钥从那儿获得呢?答案在根证书内,根证书是一份特殊的证书,是CA认证中心给自己颁发的证书,是信任链的起始点。下载安装根证书意味着对这个CA认证中心的信任,就表明您对该根证书以下所签发的证书都表示信任。

注:因为任何人都可以生成自己的(公钥,私钥)对,所以为了防止有人散布伪造的公钥骗取信任,就需要一个可靠的第三方机构来生成经过认证的(公钥,私钥)对。目前,世界上最主要的数字服务认证商是位于美国加州的Verisign公司,它的主要业务就是分发RSA数字证书。

.pfx文件
pfx(个人信息交换,Personal Information Exchange)的文件。.pfx 文件包含一个证书和与之对应的私钥(PKCS #12 标准对该格式有所说明)。这类文件是高度敏感的,通常用于导入服务器上的密钥对或用于备份目的。在导出密钥对时,Windows 提供用密码加密 .pfx 文件;而在导入密钥对时,您必须再次提供此密码方可导入。
公钥加密技术12号标准(Public Key Cryptography Standards #12,PKCS#12)为存储和传输用户或服务器私钥、公钥和证书指定了一个可移植的格式。它是一种二进制格式,这些文件也称为PFX文件。开发人员通常需要将PFX文件转换为某些不同的格式,如PEM或JKS,以便可以为使用SSL通信的独立Java客户端或WebLogic Server使用。

但是现在还有一个问题,对于不受信任的证书,浏览器是怎么样知道它的公钥,然后获取到里面的信息的呢,我思考了很久,但是没有结果,估计可能是浏览器收录了这个世界上可以提供制作证书的机构的公钥,又或者自己制作的证书的公钥是一样的?总之,我也不清楚,先这样吧,不搞它了,那是浏览器要重点考虑的,我们也许知道的东西还太有限。另外,curl命令好像不具备访问https的功能,反正访问支付宝是没成功,当然加 -k肯定可以啦。

你可能感兴趣的:(niginx)