这两天在折腾这个问题,google中英文的介绍都只提到一部分,所以决定写一篇blog讲一下整个配置过程,全当做笔记。

SSL连接(HTTPS)是普遍使用的安全的HTTP连接方式,它通过证书认证的方式来保证访问安全。通常的方式是:在服务器端设置一张证书,证书由具有公信力的数字证书认证机构(CA)办法给网站对应的域名;用户访问网站的时候浏览器首先会检查证书,既检查证书的合法性(签发机构可靠),也检查证书的对象和网站域名是否匹配(比如证书发给www.foo.com但是用的证书是发给www.bar.com的,那证书很可能是偷来的^^)。如果检查出错,浏览器会询问用户是否继续访问,即使继续访问也会在浏览器地址栏显示一个警告。举个例子,12306购票网站的证书就是它们自己生成的,不是CA颁发的,所以访问12306就会看到

除了认证访问站点的合法性,这张证书还会用来对传输的数据进行加密,这样攻击者就没法通过网络抓包的方式轻易得到用户的账户密码等敏感信息。--虽然12306到证书是自己签的,仍然可以用来加密传输数据。

除了上述服务器端证书认证以外,有时候还会有额外的一步称为客户端证书认证。如果某个站点或某些URL并不希望所有的人访问,可以在建立连接的时候要求客户端也提供证书,只有证书在白名单之列的客户才可以建立连接。这种认证方法在前端并不常用,因为网站给每个注册用户发一张证书很困难,用户保存这张证书也很麻烦。但是在后端比较常用,比如网站的web服务器和后台其他服务器之间进行数据通信的时候。

现在就假设在Apache上运行了一个Django的虚拟站点,这个站点提供一些Rest API,我们只希望拥有证书的客户端能够调用这些Rest API,不对外开放。

设置过程分为以下几步:

1. 生成证书

对于服务器端证书,通常需要从CA去申请,申请的证书和域名是绑定的。如果服务器只是内部使用,并不暴露在Internet下供大家访问,也可以自己生成。客户端证书可以自己生成,并只颁发给信任的客户端使用。因此这里略去向CA申请的过程,只讲怎么自己生成:

a.生成一个host key

$ssh-keygen -f foo.com.key

1

$ssh-keygen-ffoo.com.key

b.用这个host key创建一个证书申请

$openssl req -new -key foo.com.key -out foo.com.csr

1

$opensslreq-new-keyfoo.com.key-outfoo.com.csr

c.由前两步得到的key和证书申请产生一张证书

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

1

$opensslx509-req-days365-infoo.com.csr-signkeyfoo.com.key-outfoo.com.crt

二三步也可以合成一个命令

$openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout foo.com.key -out foo.com.key.crt

1

$opensslreq-x509-nodes-days365-newkeyrsa:2048-keyoutfoo.com.key-outfoo.com.key.crt

用同样的方法可以生成另一张客户端证书。如果情况再稍微复杂一点,你有多个客户并且需要一一区分它们,那需要给每个客户单独生成一张证书。这时通常的做法是:先生成一张自己的CA证书(就是自己做自己的权威机构),然后再用这张CA证书分别生成多张不同的客户端证书。关于这一点,我看到一篇很好的reference,可以参考。

2. 在Apache上配置使用SSL

先贴出一个完整的虚拟站点配置文件

Apache

ServerName hwind-linux.cloudapp.net

ServerAdmin webmaster@localhost

DocumentRoot /var/www/pyvideo_project

Alias /static /var/www/pyvideo_project/staticfiles

Order allow,deny

Allow from all

WSGIScriptAlias / /var/www/pyvideo_project/pyvideo/wsgi.py

# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,

# error, crit, alert, emerg.

# It is also possible to configure the loglevel for particular

# modules, e.g.

LogLevel debug

#ssl:warn

ErrorLog ${APACHE_LOG_DIR}/error.log

CustomLog ${APACHE_LOG_DIR}/access.log combined

SSLEngine On

SSLCertificateFile /etc/apache2/ssl/crt/hwind-linux.cloudapp.net.crt

SSLCertificateKeyFile /etc/apache2/ssl/key/hwind-linux.cloudapp.net.key

SSLCACertificateFile /etc/apache2/ssl/crt/dev@hwind-linux.cloudapp.net.crt

RequestHeader set SSL_CLIENT_S_DN ""

RequestHeader set SSL_CLIENT_I_DN ""

RequestHeader set SSL_SERVER_S_DN_OU ""

RequestHeader set SSL_CLIENT_VERIFY ""

RequestHeader set SSL_CLIENT_V_START ""

RequestHeader set SSL_CLIENT_V_END ""

RequestHeader set SSL_CLIENT_M_VERSION ""

RequestHeader set SSL_CLIENT_M_SERIAL ""

RequestHeader set SSL_CLIENT_CERT ""

RequestHeader set SSL_CLIENT_VERIFY ""

RequestHeader set SSL_SERVER_M_SERIAL ""

RequestHeader set SSL_SERVER_M_VERSION ""

RequestHeader set SSL_SERVER_I_DN ""

RequestHeader set SSL_SERVER_CERT ""

SSLVerifyClient Require

SSLVerifyDepth 1

SSLOptions +StdEnvVars

RequestHeader set SSL_CLIENT_S_DN "%{SSL_CLIENT_S_DN}s"

RequestHeader set SSL_CLIENT_I_DN "%{SSL_CLIENT_I_DN}s"

RequestHeader set SSL_SERVER_S_DN_OU "%{SSL_SERVER_S_DN_OU}s"

RequestHeader set SSL_CLIENT_VERIFY "%{SSL_CLIENT_VERIFY}s"

RequestHeader set SSL_CLIENT_V_START "%{SSL_CLIENT_V_START}s"

RequestHeader set SSL_CLIENT_V_END "%{SSL_CLIENT_V_END}s"

RequestHeader set SSL_CLIENT_M_VERSION "%{SSL_CLIENT_M_VERSION}s"

RequestHeader set SSL_CLIENT_M_SERIAL "%{SSL_CLIENT_M_SERIAL}s"

RequestHeader set SSL_CLIENT_CERT "%{SSL_CLIENT_CERT}s"

RequestHeader set SSL_CLIENT_VERIFY "%{SSL_CLIENT_VERIFY}s"

RequestHeader set SSL_SERVER_M_VERSION "%{SSL_SERVER_M_VERSION}s"

RequestHeader set SSL_SERVER_I_DN "%{SSL_SERVER_I_DN}s"

RequestHeader set SSL_SERVER_CERT "%{SSL_SERVER_CERT}s"

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

ServerNamehwind-linux.cloudapp.net

ServerAdminwebmaster@localhost

DocumentRoot/var/www/pyvideo_project

Alias/static/var/www/pyvideo_project/staticfiles

Orderallow,deny

Allowfromall

WSGIScriptAlias//var/www/pyvideo_project/pyvideo/wsgi.py

# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,

# error, crit, alert, emerg.

# It is also possible to configure the loglevel for particular

# modules, e.g.

LogLeveldebug

#ssl:warn

ErrorLog${APACHE_LOG_DIR}/error.log

CustomLog${APACHE_LOG_DIR}/access.logcombined

SSLEngineOn

SSLCertificateFile/etc/apache2/ssl/crt/hwind-linux.cloudapp.net.crt

SSLCertificateKeyFile/etc/apache2/ssl/key/hwind-linux.cloudapp.net.key

SSLCACertificateFile/etc/apache2/ssl/crt/dev@hwind-linux.cloudapp.net.crt

RequestHeadersetSSL_CLIENT_S_DN""

RequestHeadersetSSL_CLIENT_I_DN""

RequestHeadersetSSL_SERVER_S_DN_OU""

RequestHeadersetSSL_CLIENT_VERIFY""

RequestHeadersetSSL_CLIENT_V_START""

RequestHeadersetSSL_CLIENT_V_END""

RequestHeadersetSSL_CLIENT_M_VERSION""

RequestHeadersetSSL_CLIENT_M_SERIAL""

RequestHeadersetSSL_CLIENT_CERT""

RequestHeadersetSSL_CLIENT_VERIFY""

RequestHeadersetSSL_SERVER_M_SERIAL""

RequestHeadersetSSL_SERVER_M_VERSION""

RequestHeadersetSSL_SERVER_I_DN""

RequestHeadersetSSL_SERVER_CERT""

SSLVerifyClientRequire

SSLVerifyDepth1

SSLOptions+StdEnvVars

RequestHeadersetSSL_CLIENT_S_DN"%{SSL_CLIENT_S_DN}s"

RequestHeadersetSSL_CLIENT_I_DN"%{SSL_CLIENT_I_DN}s"

RequestHeadersetSSL_SERVER_S_DN_OU"%{SSL_SERVER_S_DN_OU}s"

RequestHeadersetSSL_CLIENT_VERIFY"%{SSL_CLIENT_VERIFY}s"

RequestHeadersetSSL_CLIENT_V_START"%{SSL_CLIENT_V_START}s"

RequestHeadersetSSL_CLIENT_V_END"%{SSL_CLIENT_V_END}s"

RequestHeadersetSSL_CLIENT_M_VERSION"%{SSL_CLIENT_M_VERSION}s"

RequestHeadersetSSL_CLIENT_M_SERIAL"%{SSL_CLIENT_M_SERIAL}s"

RequestHeadersetSSL_CLIENT_CERT"%{SSL_CLIENT_CERT}s"

RequestHeadersetSSL_CLIENT_VERIFY"%{SSL_CLIENT_VERIFY}s"

RequestHeadersetSSL_SERVER_M_VERSION"%{SSL_SERVER_M_VERSION}s"

RequestHeadersetSSL_SERVER_I_DN"%{SSL_SERVER_I_DN}s"

RequestHeadersetSSL_SERVER_CERT"%{SSL_SERVER_CERT}s"

a.服务器端SSL

打开服务器端SSL主要由这几行配置指定:

SSLEngine On

SSLCertificateFile /etc/apache2/ssl/crt/hwind-linux.cloudapp.net.crt

SSLCertificateKeyFile /etc/apache2/ssl/key/hwind-linux.cloudapp.net.key

1

2

3

SSLEngineOn

SSLCertificateFile/etc/apache2/ssl/crt/hwind-linux.cloudapp.net.crt

SSLCertificateKeyFile/etc/apache2/ssl/key/hwind-linux.cloudapp.net.key

b.客户端SSL

客户端SSL认证主要由这几行配置指定:

SSLVerifyClient Require

SSLVerifyDepth 1

1

2

SSLVerifyClientRequire

SSLVerifyDepth1

其中SSLVerifyDepth的含义是在证书链中检查的深度。证书是层层签发的,最顶层是CA,因为这里使用的证书都是直接由CA签发,因此是1就可以了。

c.设置Apache把证书信息传给Django应用程序

通常除了在Apache上设置,我们很可能还需要在Django应用程序里根据证书信息做更细致多处理。例如根据证书签名判断访问来自哪个客户,每个客户可能会有不同的权限,看到不同的东西。有两种方案:一个是通过SSLOptions +StdEnvVars的设置把证书信息放进环境变量,再在Apache调用wsgi.py的时候传递过去。这个方案在网上看到有人提到,但是我不知道怎么在wsgi.py中修改request object;如果通过全局变量或者环境变量的方法传递信息,那只能处理单个证书的情形,因为全局变量只能hold一份信息;另一个方案是通过RequestHeader的设置把证书信息加到HTTP request header中去。这个方案经过尝试很好用,示例如下:

在view收到post请求的时候,通过检查存放在request.META中的header信息就可以知道证书是颁发给谁的,之后就可以针对不同的人做不同的响应。

Python

def post(self, request, format=None):

if 'SSL_CLIENT_S_DN_CN' in request.META:

cn = request.META['SSL_CLIENT_S_DN_CN']

1

2

3

defpost(self,request,format=None):

if'SSL_CLIENT_S_DN_CN'inrequest.META:

cn=request.META['SSL_CLIENT_S_DN_CN']

3. 浏览器访问

当Apache,Django设置好之后,就可以通过浏览器进行访问了。首先需要在客户端的电脑上安装客户端证书,然后在访问的时候浏览器会弹出窗口,这时选择对应的证书就可以打开网站了。例如,在Chrome中,选择settings-show advanced settings就可以看到

然后在访问的时候选择刚才安装的证书

安装证书的时候需要提供同时包含公钥和私钥的文件,pfx或者p12格式。之前我们提到生成证书的过程生成的是独立的公钥和私钥文件。可以通过以下命令做转换

$openssl pkcs12 -export -out foo.name.pfx -inkey foo.name.key -in foo.name.crt

1

$opensslpkcs12-export-outfoo.name.pfx-inkeyfoo.name.key-infoo.name.crt

4.Python访问需要客户端证书认证的Rest API

Python跟http相关的模块比较混乱, urllib2, httplib2, requests, pycurl都可以用来访问RestAPI,但是使用起来的复杂程度各不相同。有兴趣可以参考这篇blog,它对这几个模块访问RestAPI的方式做了详细的比较。总之,结论是requests用起来很方面。

requests天然提供对客户端证书认证的支持,直接这发送请求到时候带上证书的路径作为参数就可以:

Python

def _post(self, url, data):

cert_path = config.get_client_cert_path()

return requests.post(url, verify=False, cert=cert_path, data=data)

1

2

3

def_post(self,url,data):

cert_path=config.get_client_cert_path()

returnrequests.post(url,verify=False,cert=cert_path,data=data)

上面的cert参数可以是一个指向pem格式证书的字符串,也可以是一个tuple,分别包含cert和key的路径。

requests的一个缺点是它只支持pem格式的证书(不包含密码),但是通常我们得到的都是倒出时包含密码的证书,比如pfx。把pem放在机器里看起来不是很安全。Github上这个open issue也有讨论。

可以通过以下命令把pfx转成pem格式:

$openssl pkcs12 -in foo.com.pfx -out foo.com.pem -nodes

1

$opensslpkcs12-infoo.com.pfx-outfoo.com.pem-nodes

这就是end-to-end全过程,大功告成。

python 列表比较不同物质的吸热能力_飘着雪花的冬天相关推荐

  1. python 列表比较不同物质的吸热能力_比较不同物质吸热能力实验专项

    6 ( 1 )在此实验中,为比较水和煤油吸热能力的大小,我们可以加热相同的时间,观察 的不同:也 可以 . ( 2 )分析上表中的实验数据可知:质量相同的水和煤油,升高相同的温度时, 吸收的热量多,表 ...

  2. python 列表比较不同物质的吸热能力_python列表里面根据一定的条件挑选元素

    update: 之前一版是错的,忽略了两层栈深还必须ticket.spce连续的要求 换个解法,代码有些冗长 #!/usr/bin/env python # -*- coding: utf-8 -*- ...

  3. python 列表嵌套字典 添加修改删除_【Python】列表嵌套字典修改字典里面的一个值却把全部的值都修改了。...

    具体问题就是:当我往空列表里面添加字典,需要修改其中的一个键的值的时候,出现把其他同类的值也修改了. 下面就是出现问题的代码: aliens = [] new_alien = {"color ...

  4. python列表转化为元组、集合_如何在Python中将元组列表更改为集合?

    我在Python中创建了一个函数,它返回抛出2个骰子的所有可能结果的列表. 元组列表:[(1,1),(1,2),-,(6,6)].在 然后我写了一个函数来找出两个值之和为偶数的所有元素(a),另一个函 ...

  5. python列表前加星号是什么_元组的reference前加个星号是什么意思?

    pixbuf = Gdk.pixbuf_get_from_window(rootwin, 0, 0, screen.width(), screen.height()) 调用(caller) func( ...

  6. python列表某项与数字乘_如何将列表中的每个元素乘以一个数字?

    一种非常快速的方法是以矢量化的方式进行乘法,而不是在列表上循环.Numpy已经提供了一种非常简单和方便的方法,您可以使用它.>>> import numpy as np >&g ...

  7. python列表是顺序表还是链表_顺序表与链表

    Python中的顺序表 Python中的list和tuple两种类型采用了顺序表的实现技术,具有前面讨论的顺序表的所有性质. tuple是不可变类型,即不变的顺序表,因此不支持改变其内部状态的任何操作 ...

  8. python列表求平均值是什么函数_用Python计算列表中列的平均值

    假设你有你的清单table = [[1, 2, 3], [10, 20, 30], [100, 200, 300]] 您可以使用zip转置它,并将原始列表作为参数列表传递(星号做什么):transpo ...

  9. python列表输出学生姓名学号链表_建立一个链表,记录学生的姓名,学号和成绩,

    展开全部 public class StudentPerson { /// /// 实例化一个新的学生e69da5e887aa3231313335323631343130323136353331333 ...

最新文章

  1. 1.8 Remove
  2. 幅度响应怎么计算_广播百科 频率响应
  3. 在QT的LineEdit框中输入特定字符(正则表达式的使用)
  4. 制作空镜像与一个run的共享文件错误解决
  5. iOS QQ分享图片无反应问题
  6. 前端学习(668):分支导读
  7. EBOOT跳转到NK的过程
  8. PDX模型不靠谱,土豪来发resource;细菌帮助癌转移,诺奖发现被推翻
  9. 取二维数组最大值_学习Java,你必需要知道这些——Java数组
  10. 程序清单 8-8 exec函数实例,a.out是程序8-9产生的可执行程序
  11. L1-037 A除以B (10 分)—团体程序设计天梯赛
  12. Https之SSL原理
  13. Springboot入门到精通(超详细文档)
  14. python 两点曲线_ECC椭圆曲线加密算法:ECDH 和 ECDSA
  15. Java智能卡基础篇
  16. 原子化服务的官方解析来啦~
  17. win10服务器权限修改时间,Win10没有权限修改系统时间如何解决?
  18. 51单片机c语言除法符号,51单片机之C语言-4.4运算符及表达式
  19. 【mongodb】比较符及修改器
  20. 盒子模型之京东快报页面

热门文章

  1. HDR:为用户打造的视觉盛宴
  2. 倒计时5天:5G还是6G?
  3. RTMP之后,SRT与QUIC
  4. SRS流媒体服务器——Forward集群搭建和源码分析
  5. JVM之强引用、软引用、弱引用、虚引用
  6. 一文搞懂 SQL:基础知识和业务实践总结
  7. 鹅厂程序员最喜欢用什么编程语言?Leader写代码么?
  8. MySQL性能基准测试对比:MySQL 5.7与MySQL 8.0
  9. uimsbf和 bslbf的含义
  10. ../configure: /bin/sh^M: bad interpreter: No such file or directory