<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Behind the Code &#187; twisted</title>
	<atom:link href="http://yinwm.com/tag/twisted/feed/" rel="self" type="application/rss+xml" />
	<link>http://yinwm.com</link>
	<description>Thinking in Techique</description>
	<lastBuildDate>Fri, 06 Aug 2010 02:38:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>网络安全通讯（5）&#8212;-支持客户端验证的python web server</title>
		<link>http://yinwm.com/2008/04/%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8%e9%80%9a%e8%ae%af%ef%bc%885%ef%bc%89-%e6%94%af%e6%8c%81%e5%ae%a2%e6%88%b7%e7%ab%af%e9%aa%8c%e8%af%81%e7%9a%84python-web-server/</link>
		<comments>http://yinwm.com/2008/04/%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8%e9%80%9a%e8%ae%af%ef%bc%885%ef%bc%89-%e6%94%af%e6%8c%81%e5%ae%a2%e6%88%b7%e7%ab%af%e9%aa%8c%e8%af%81%e7%9a%84python-web-server/#comments</comments>
		<pubDate>Wed, 02 Apr 2008 12:49:39 +0000</pubDate>
		<dc:creator>yinwm</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://yinwm.cn/wordpress/?p=45</guid>
		<description><![CDATA[前面我们说道很多的场景是需要客户端验证（Client Certificate）的，而python的web server如何支持呢？大多数的python web server都是符合WSGI标准的，也就是他们提供WSGI标准支持的功能，也就是他们几乎都不支持WSGI不支持的功能。很遗憾，客户端验证不在此列。换句话说，Cherrypy，webpy等常用的python web server都无法支持客户端验证。 我终于找到了Twisted（他怎么一下从2.5就蹦到了8.0.1）的web模块可以作为一个单独的web server。而这个web模块是包装的很底层的，使用pyopenssl，并且不是WSGI的一个实现。也就是说，他很可能是支持客户端验证的。经过一番google，发现了支持的办法。如下：首先我们看一下如何让Twisted支持HTTPS，他需要执行reactor.listenSSL方法， class Hello(Resource) :&#160;&#160;&#160; isLeaf = True&#160;&#160;&#160; def render(self, request) :&#160;&#160;&#160;&#160;&#160;&#160;&#160; return &#8216;Hello, SSL&#8217;root = server.Site(Hello())ctxFactory = ssl.DefaultOpenSSLContextFactory(&#160;&#160;&#160; &#8216;/path/to/server.key&#8217;,&#160;&#160;&#160; &#8216;/path/to/server.crt&#8217;&#160;&#160;&#160; )reactor.listenSSL(443, root, contextFactory = ctxFactory)reactor.run() 这是最基本的支持HTTPS的方法，我们看，他需要一个contextFactory，深入到Twisted里面发现这个contextFactory是SSL进行设置。我们想要他支持客户端验证，就要从这里下手了。DefaultOpenSSLContextFactory的cacheContext方法是对context进行的操作。我们重写这个方法。 class SSLClientCertificateFactory(ssl.DefaultOpenSSLContextFactory) : &#160;&#160;&#160; def __init__(self, privateKeyFileName, certificateFileName, sslmethod=SSL.SSLv23_METHOD) :&#160;&#160;&#160;&#160;&#160;&#160;&#160; ssl.DefaultOpenSSLContextFactory.__init__(self, privateKeyFileName, certificateFileName, sslmethod) &#160;&#160;&#160; def _verify(self, connection, x509, errnum, errdepth, [...]]]></description>
			<content:encoded><![CDATA[<p>前面我们说道很多的场景是需要客户端验证（Client Certificate）的，而python的web server如何支持呢？<br />大多数的python web server都是符合WSGI标准的，也就是他们提供WSGI标准支持的功能，也就是他们几乎都不支持WSGI不支持的功能。很遗憾，客户端验证不在此列。换句话说，Cherrypy，webpy等常用的python web server都无法支持客户端验证。</p>
<p>我终于找到了<a href="http://twistedmatrix.com/" target="blank">Twisted</a>（他怎么一下从2.5就蹦到了8.0.1）的web模块可以作为一个单独的web server。而这个web模块是包装的很底层的，使用pyopenssl，并且不是WSGI的一个实现。也就是说，他很可能是支持客户端验证的。<br />经过一番google，发现了支持的办法。如下：<br />首先我们看一下如何让Twisted支持HTTPS，他需要执行reactor.listenSSL方法，</p>
<p>class Hello(Resource) :<br />&nbsp;&nbsp;&nbsp; isLeaf = True<br />&nbsp;&nbsp;&nbsp; def render(self, request) :<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &#8216;Hello, SSL&#8217;<br />root = server.Site(Hello())<br />ctxFactory = ssl.DefaultOpenSSLContextFactory(<br />&nbsp;&nbsp;&nbsp; &#8216;/path/to/server.key&#8217;,<br />&nbsp;&nbsp;&nbsp; &#8216;/path/to/server.crt&#8217;<br />&nbsp;&nbsp;&nbsp; )<br />reactor.listenSSL(443, root, contextFactory = ctxFactory)<br />reactor.run()</p>
<p>这是最基本的支持HTTPS的方法，我们看，他需要一个contextFactory，深入到Twisted里面发现这个contextFactory是SSL进行设置。我们想要他支持客户端验证，就要从这里下手了。<br />DefaultOpenSSLContextFactory的cacheContext方法是对context进行的操作。我们重写这个方法。</p>
<p>class SSLClientCertificateFactory(ssl.DefaultOpenSSLContextFactory) :</p>
<p>&nbsp;&nbsp;&nbsp; def __init__(self, privateKeyFileName, certificateFileName, sslmethod=SSL.SSLv23_METHOD) :<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssl.DefaultOpenSSLContextFactory.__init__(self, privateKeyFileName, certificateFileName, sslmethod)</p>
<p>&nbsp;&nbsp;&nbsp; def _verify(self, connection, x509, errnum, errdepth, ok):<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&#8221;"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print &#8216;_verify (ok=%d):&#8217; % ok<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print &#8216;&nbsp; subject:&#8217;, x509.get_subject()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print &#8216;&nbsp; issuer:&#8217;, x509.get_issuer()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print &#8216;&nbsp; errnum %s, errdepth %d&#8217; % (errnum, errdepth)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;&#8221;"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ok<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; def cacheContext(self) :<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssl.DefaultOpenSSLContextFactory.cacheContext(self)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctx = self._context<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ctx.load_verify_locations(&#8216;/path/to/ca.crt&#8217;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self._verify)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._context = ctx</p>
<p>我们在通过默认的contextFactory生成context之后，执行ctx.set_verify(SSL.VERIFY_PEER|SSL.VERIFY_FAIL_IF_NO_PEER_CERT, self._verify)，这样就加入和客户端验证，并且在self._verify函数里面我们还可以具体的验证证书的情况。<br />改写最上面的程序，<br />class Hello(Resource) :<br />
&nbsp;&nbsp;&nbsp; isLeaf = True<br />
&nbsp;&nbsp;&nbsp; def render(self, request) :<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return &#8216;Hello, SSL&#8217;<br />
root = server.Site(Hello())<br />
ctxFactory = SSLClientCertificateFactory(<br />
&nbsp;&nbsp;&nbsp; &#8216;/path/to/server.key&#8217;,<br />
&nbsp;&nbsp;&nbsp; &#8216;/path/to/server.crt&#8217;<br />
&nbsp;&nbsp;&nbsp; )<br />
reactor.listenSSL(443, root, contextFactory = ctxFactory)<br />reactor.run()</p>
<p>好了，此时我们的python web server已经支持客户端验证了</p>
<p>后记：这里我有一个思考，就是为什么WSGI（暂时）不支持客户端验证？我想应该不是设计者忽视了这个问题。一般的，需要客户端验证这样的应用场景，很难只是假设一个python的web server，前面应该都有一个Apache等纯粹的服务器，那么这些验证之类的工作完全交付给Apache就足够好了，python没必要自己来处理。也许这就是原因吧。<br />那么，从这里我们也能看出，作为一个纯粹的网络应用组件，Twisted至少从功能上还是非常强大的。</p>
]]></content:encoded>
			<wfw:commentRss>http://yinwm.com/2008/04/%e7%bd%91%e7%bb%9c%e5%ae%89%e5%85%a8%e9%80%9a%e8%ae%af%ef%bc%885%ef%bc%89-%e6%94%af%e6%8c%81%e5%ae%a2%e6%88%b7%e7%ab%af%e9%aa%8c%e8%af%81%e7%9a%84python-web-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
