<?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>MoDoFo.println(" &#187; openAPI</title>
	<atom:link href="http://zhangv.com/archives/tag/openapi/feed" rel="self" type="application/rss+xml" />
	<link>http://zhangv.com</link>
	<description>Life for Idea - forever young</description>
	<lastBuildDate>Sat, 07 Apr 2012 04:08:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>规划你的WebAPI &#8211; 安全</title>
		<link>http://zhangv.com/archives/1233</link>
		<comments>http://zhangv.com/archives/1233#comments</comments>
		<pubDate>Fri, 28 Aug 2009 02:56:02 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[翻译]]></category>
		<category><![CDATA[openAPI]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[SOAP]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/1233</guid>
		<description><![CDATA[


  

译自“Professional Web APIs with PHP: eBay,Google, PayPal, Amazon, FedEx, Plus Web Feeds” (chapter 12)

你一定听过这样一句话“失败的计划是必定失败（Fail to plan, and you plan to fail.”对WebAPI来说，在开始一切工作之前的规划尤为重要，因为他不仅会影响到实现难度，同时会让那些使用API的开发者痛苦不堪。



通常来说，引入额外的安全层次会更好的保护你的API，但是同时需要很好的平衡这种设计对易用性的影响。时刻记得，安全即是保护你的数据，也是确保开发者的调用过程完整（通常是用“token”）。
完全开放的API
在一个完全没有安全验证机制的开放API里，首先会有一个来自外界的请求，然后系统会尝试完成并响应这个请求。
优点:

最小的使用障碍 – 既没有加密页没有验证机制，任何人都可以访问你的API。
更容易的创建分布式应用 – 登录帐户或者程序员，只要他们使用了你的API，那么程序可以分布到任何地方,而你根本无需考虑他们在哪里调用。
省心 – 如果你没有管理用户账户和开发密钥，那就可以花更多的时间在开发API本身。

缺点:

缺少控制 – 任何人在任何地方都可以调用API，尽管这是web服务的目标，但可能会在潮水般的请求涌来时失去控制。如果这些请求只是来自一部机器，还可以借助防火墙来搞定，但是如果分布很广，处理起来就会很痛苦。
没有加密 – 所有请求端和服务端的请求和响应都是对任何人都可见的。
无法接触到开发者 – 因为API的调用不存在注册过程，也就无法联络到相应的开发者。而你可以通过注册机制建立一个与开发者的一个很好的联系。比如，告知他的应用正在被误用，API有新的改动，征求改进建议等等。
误用 – 很不幸，总有一些人会利用这一点去做一些不好的事，即便你觉得这个可能性很小。

因为这些问题，完全开放的API只适用于用来请求信息，而不是发布信息 – 也就是请求的信息资源产生过程不会占用太多CPU资源。一个很恰当的例子是国家天气服务API，它只接受信息请求，并且这些请求可以全天候的缓存在服务器上。如果是需要发布信息，那么相应的验证机制要被用来识别请求者，当请求需要消耗大量CPU时，远端程序需要被识别出来，从而对发来的请求进行过滤和控制。
HTTP 验证
通过HTTP头包含中验证信息，基于Base64编码，实际上并没有加密，没有信息安全可言。
优点：

简单 — 因为验证信息是在HTTP头里，所以可以被路由器和网关处理。从而可以用硬件过滤和筛查客户端请求。从应用的角度来看，验证实际上是发生在服务器端，因此设计服务器时应该考虑到高性能和高并发的开发和测试。
对应用来说透明     -&#160; 因为是web服务器来处理验证，你可以完全不需要考虑用户登录问题。当然这只适用于请求那些于特定用户无关的信息（每个用户使用相同的请求得到相同的信息）。
易于编码 — 添加一个额外的HTTP头信息对大多数编程语言来说都不在话下。It is also    [...]]]></description>
			<content:encoded><![CDATA[<link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml">
<link rel="themeData" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx">
<link rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml"><!--[if gte mso 9]><xml> <w:WordDocument>  <w:View>Normal</w:View>  <w:Zoom>0</w:Zoom>  <w:TrackMoves/>  <w:TrackFormatting/>  <w:PunctuationKerning/>  <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>  <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>  <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>  <w:ValidateAgainstSchemas/>  <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>  <w:IgnoreMixedContent>false</w:IgnoreMixedContent>  <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>  <w:DoNotPromoteQF/>  <w:LidThemeOther>EN-US</w:LidThemeOther>  <w:LidThemeAsian>ZH-CN</w:LidThemeAsian>  <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>  <w:Compatibility>   <w:SpaceForUL/>   <w:BalanceSingleByteDoubleByteWidth/>   <w:DoNotLeaveBackslashAlone/>   <w:ULTrailSpace/>   <w:DoNotExpandShiftReturn/>   <w:AdjustLineHeightInTable/>   <w:BreakWrappedTables/>   <w:SnapToGridInCell/>   <w:WrapTextWithPunct/>   <w:UseAsianBreakRules/>   <w:DontGrowAutofit/>   <w:SplitPgBreakAndParaMark/>   <w:DontVertAlignCellWithSp/>   <w:DontBreakConstrainedForcedTables/>   <w:DontVertAlignInTxbx/>   <w:Word11KerningPairs/>   <w:CachedColBalance/>   <w:UseFELayout/>  </w:Compatibility>  <m:mathPr>   <m:mathFont m:val="Cambria Math"/>   <m:brkBin m:val="before"/>   <m:brkBinSub m:val="&#45;-"/>   <m:smallFrac m:val="off"/>   <m:dispDef/>   <m:lMargin m:val="0"/>   <m:rMargin m:val="0"/>   <m:defJc m:val="centerGroup"/>   <m:wrapIndent m:val="1440"/>   <m:intLim m:val="subSup"/>   <m:naryLim m:val="undOvr"/>  </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"  DefSemiHidden="true" DefQFormat="false" DefPriority="99"  LatentStyleCount="267">  <w:LsdException Locked="false" Priority="0" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Normal"/>  <w:LsdException Locked="false" Priority="9" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>  <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>  <w:LsdException Locked="false" Priority="39" Name="toc 1"/>  <w:LsdException Locked="false" Priority="39" Name="toc 2"/>  <w:LsdException Locked="false" Priority="39" Name="toc 3"/>  <w:LsdException Locked="false" Priority="39" Name="toc 4"/>  <w:LsdException Locked="false" Priority="39" Name="toc 5"/>  <w:LsdException Locked="false" Priority="39" Name="toc 6"/>  <w:LsdException Locked="false" Priority="39" Name="toc 7"/>  <w:LsdException Locked="false" Priority="39" Name="toc 8"/>  <w:LsdException Locked="false" Priority="39" Name="toc 9"/>  <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>  <w:LsdException Locked="false" Priority="10" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Title"/>  <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>  <w:LsdException Locked="false" Priority="11" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>  <w:LsdException Locked="false" Priority="22" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Strong"/>  <w:LsdException Locked="false" Priority="20" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>  <w:LsdException Locked="false" Priority="59" SemiHidden="false"   UnhideWhenUsed="false" Name="Table Grid"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>  <w:LsdException Locked="false" Priority="1" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 1"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 1"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 1"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>  <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>  <w:LsdException Locked="false" Priority="34" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>  <w:LsdException Locked="false" Priority="29" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Quote"/>  <w:LsdException Locked="false" Priority="30" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 1"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 1"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 2"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 2"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 2"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 2"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 2"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 3"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 3"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 3"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 3"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 3"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 4"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 4"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 4"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 4"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 4"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 5"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 5"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 5"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 5"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 5"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>  <w:LsdException Locked="false" Priority="60" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Shading Accent 6"/>  <w:LsdException Locked="false" Priority="61" SemiHidden="false"   UnhideWhenUsed="false" Name="Light List Accent 6"/>  <w:LsdException Locked="false" Priority="62" SemiHidden="false"   UnhideWhenUsed="false" Name="Light Grid Accent 6"/>  <w:LsdException Locked="false" Priority="63" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>  <w:LsdException Locked="false" Priority="64" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>  <w:LsdException Locked="false" Priority="65" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>  <w:LsdException Locked="false" Priority="66" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>  <w:LsdException Locked="false" Priority="67" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>  <w:LsdException Locked="false" Priority="68" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>  <w:LsdException Locked="false" Priority="69" SemiHidden="false"   UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>  <w:LsdException Locked="false" Priority="70" SemiHidden="false"   UnhideWhenUsed="false" Name="Dark List Accent 6"/>  <w:LsdException Locked="false" Priority="71" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>  <w:LsdException Locked="false" Priority="72" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful List Accent 6"/>  <w:LsdException Locked="false" Priority="73" SemiHidden="false"   UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>  <w:LsdException Locked="false" Priority="19" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>  <w:LsdException Locked="false" Priority="21" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>  <w:LsdException Locked="false" Priority="31" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>  <w:LsdException Locked="false" Priority="32" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>  <w:LsdException Locked="false" Priority="33" SemiHidden="false"   UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>  <w:LsdException Locked="false" Priority="37" Name="Bibliography"/>  <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/> </w:LatentStyles> </xml><![endif]--><br />
<style> <!-- /* Font Definitions */ @font-face 	{font-family:Wingdings; 	panose-1:5 0 0 0 0 0 0 0 0 0; 	mso-font-charset:2; 	mso-generic-font-family:auto; 	mso-font-pitch:variable; 	mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face 	{font-family:宋体; 	panose-1:2 1 6 0 3 1 1 1 1 1; 	mso-font-alt:SimSun; 	mso-font-charset:134; 	mso-generic-font-family:auto; 	mso-font-pitch:variable; 	mso-font-signature:3 135135232 16 0 262145 0;} @font-face 	{font-family:"Cambria Math"; 	panose-1:2 4 5 3 5 4 6 3 2 4; 	mso-font-charset:1; 	mso-generic-font-family:roman; 	mso-font-format:other; 	mso-font-pitch:variable; 	mso-font-signature:0 0 0 0 0 0;} @font-face 	{font-family:Calibri; 	panose-1:2 15 5 2 2 2 4 3 2 4; 	mso-font-charset:0; 	mso-generic-font-family:swiss; 	mso-font-pitch:variable; 	mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face 	{font-family:"\@宋体"; 	panose-1:2 1 6 0 3 1 1 1 1 1; 	mso-font-charset:134; 	mso-generic-font-family:auto; 	mso-font-pitch:variable; 	mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal 	{mso-style-unhide:no; 	mso-style-qformat:yes; 	mso-style-parent:""; 	margin:0cm; 	margin-bottom:.0001pt; 	text-align:justify; 	text-justify:inter-ideograph; 	mso-pagination:none; 	font-size:10.5pt; 	mso-bidi-font-size:11.0pt; 	font-family:"Calibri","sans-serif"; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-fareast-font-family:宋体; 	mso-fareast-theme-font:minor-fareast; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin; 	mso-bidi-font-family:"Times New Roman"; 	mso-bidi-theme-font:minor-bidi; 	mso-font-kerning:1.0pt;} a:link, span.MsoHyperlink 	{mso-style-priority:99; 	color:blue; 	text-decoration:underline; 	text-underline:single;} a:visited, span.MsoHyperlinkFollowed 	{mso-style-noshow:yes; 	mso-style-priority:99; 	color:purple; 	mso-themecolor:followedhyperlink; 	text-decoration:underline; 	text-underline:single;} .MsoChpDefault 	{mso-style-type:export-only; 	mso-default-props:yes; 	mso-bidi-font-family:"Times New Roman"; 	mso-bidi-theme-font:minor-bidi;} /* Page Definitions */ @page 	{mso-page-border-surround-header:no; 	mso-page-border-surround-footer:no;} @page Section1 	{size:612.0pt 792.0pt; 	margin:72.0pt 90.0pt 72.0pt 90.0pt; 	mso-header-margin:36.0pt; 	mso-footer-margin:36.0pt; 	mso-paper-source:0;} div.Section1 	{page:Section1;} /* List Definitions */ @list l0 	{mso-list-id:118303353; 	mso-list-template-ids:1406043308;} @list l0:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l1 	{mso-list-id:352532769; 	mso-list-template-ids:-530546072;} @list l1:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l2 	{mso-list-id:641008087; 	mso-list-template-ids:-1893796460;} @list l2:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l3 	{mso-list-id:834225478; 	mso-list-template-ids:-2028545322;} @list l3:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l4 	{mso-list-id:926228567; 	mso-list-template-ids:-486609992;} @list l4:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l5 	{mso-list-id:965811785; 	mso-list-template-ids:312537776;} @list l5:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l6 	{mso-list-id:1012415445; 	mso-list-template-ids:402574394;} @list l6:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l7 	{mso-list-id:1115368711; 	mso-list-template-ids:1451680916;} @list l7:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l8 	{mso-list-id:1116371370; 	mso-list-template-ids:-1627908980;} @list l9 	{mso-list-id:1193226420; 	mso-list-template-ids:1051742168;} @list l9:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} @list l10 	{mso-list-id:1600068387; 	mso-list-template-ids:-1922687292;} @list l10:level1 	{mso-level-number-format:bullet; 	mso-level-text:; 	mso-level-tab-stop:36.0pt; 	mso-level-number-position:left; 	text-indent:-18.0pt; 	mso-ansi-font-size:10.0pt; 	font-family:Symbol;} ol 	{margin-bottom:0cm;} ul 	{margin-bottom:0cm;} --> </style>
<p><!--[if gte mso 10]><br />
<style> /* Style Definitions */ table.MsoNormalTable 	{mso-style-name:普通表格; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-priority:99; 	mso-style-qformat:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:10.5pt; 	mso-bidi-font-size:11.0pt; 	font-family:"Calibri","sans-serif"; 	mso-ascii-font-family:Calibri; 	mso-ascii-theme-font:minor-latin; 	mso-hansi-font-family:Calibri; 	mso-hansi-theme-font:minor-latin; 	mso-font-kerning:1.0pt;} </style>
<p> <![endif]-->
<p class="MsoNormal" style="text-align: left;" align="left">译自“<a border="0"><span class="b24-booktitle">Professional Web APIs with PHP: eBay,<br />Google, PayPal, Amazon, FedEx, Plus Web Feeds” (chapter 12)<br /></span></a></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;"><br /></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">你一定听过这样一句话“失败的计划是必定失败（<span lang="EN-US">Fail to plan, and you plan to fail.</span>”对<span lang="EN-US">WebAPI</span>来说，在开始一切工作之前的规划尤为重要，因为他不仅会影响到实现难度，同时会让那些使用<span lang="EN-US">API</span>的开发者痛苦不堪。</span></p>
<p class="MsoNormal" style="text-align: left;" align="left">
<p><span id="more-1233"></span><br /><span style="font-size: 12pt; font-family: 宋体;"><span lang="EN-US"><o:p></o:p></span></span>
</p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">通常来说，引入额外的安全层次会更好的保护你的<span lang="EN-US">API</span>，但是同时需要很好的平衡这种设计对易用性的影响。时刻记得，安全即是保护你的数据，也是确保开发者的调用过程完整（通常是用“<span lang="EN-US">token”</span>）。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="648"></a><a name="ch12lev3sec1"></a><b><span style="font-size: 12pt; font-family: 宋体;">完全开放的<span lang="EN-US">API<o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在一个完全没有安全验证机制的开放<span lang="EN-US">API</span>里，首先会有一个来自外界的请求，然后系统会尝试完成并响应这个请求。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">优点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">最小的使用障碍 <span lang="EN-US">– </span>既没有加密页没有验证机制，任何人都可以访问你的<span lang="EN-US">API</span>。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">更容易的创建分布式应用 <span lang="EN-US">– </span>登录帐户或者程序员，只要他们使用了你的<span lang="EN-US">API</span>，那么程序可以分布到任何地方<span lang="EN-US">,</span>而你根本无需考虑他们在哪里调用。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">省心 <span lang="EN-US">– </span>如果你没有管理用户账户和开发密钥，那就可以花更多的时间在开发<span lang="EN-US">API</span>本身。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">缺点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">缺少控制 <span lang="EN-US">– </span>任何人在任何地方都可以调用<span lang="EN-US">API</span>，尽管这是<span lang="EN-US">web</span>服务的目标，但可能会在潮水般的请求涌来时失去控制。如果这些请求只是来自一部机器，还可以借助防火墙来搞定，但是如果分布很广，处理起来就会很痛苦。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">没有加密 <span lang="EN-US">– </span>所有请求端和服务端的请求和响应都是对任何人都可见的。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">无法接触到开发者 <span lang="EN-US">– </span>因为<span lang="EN-US">API</span>的调用不存在注册过程，也就无法联络到相应的开发者。而你可以通过注册机制建立一个与开发者的一个很好的联系。比如，告知他的应用正在被误用，<span lang="EN-US">API</span>有新的改动，征求改进建议等等。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">误用 <span lang="EN-US">– </span>很不幸，总有一些人会利用这一点去做一些不好的事，即便你觉得这个可能性很小。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">因为这些问题，完全开放的<span lang="EN-US">API</span>只适用于用来请求信息，而不是发布信息 <span lang="EN-US">– </span>也就是请求的信息资源产生过程不会占用太多<span lang="EN-US">CPU</span>资源。一个很恰当的例子是国家天气服务<span lang="EN-US">API</span>，它只接受信息请求，并且这些请求可以全天候的缓存在服务器上。如果是需要发布信息，那么相应的验证机制要被用来识别请求者，当请求需要消耗大量<span lang="EN-US">CPU</span>时，远端程序需要被识别出来，从而对发来的请求进行过滤和控制。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="650"></a><a name="ch12lev3sec2"></a><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">HTTP </span></b><b><span style="font-size: 12pt; font-family: 宋体;">验证<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">通过<span lang="EN-US">HTTP</span>头包含中验证信息，基于<span lang="EN-US">Base64</span>编码，实际上并没有加密，没有信息安全可言。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">优点：<span lang="EN-US"><o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">简单<span lang="EN-US"> — </span>因为验证信息是在<span lang="EN-US">HTTP</span>头里，所以可以被路由器和网关处理。从而可以用硬件过滤和筛查客户端请求。从应用的角度来看，验证实际上是发生在服务器端，因此设计服务器时应该考虑到高性能和高并发的开发和测试。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">对应用来说透明<span lang="EN-US">     -<span style="">&nbsp; </span></span>因为是<span lang="EN-US">web</span>服务器来处理验证，你可以完全不需要考虑用户登录问题。当然这只适用于请求那些于特定用户无关的信息（每个用户使用相同的请求得到相同的信息）。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">易于编码<span lang="EN-US"> — </span>添加一个额外的<span lang="EN-US">HTTP</span>头信息对大多数编程语言来说都不在话下。<span lang="EN-US">It is also     pretty universally available even in shared hosting situations (which may     prevent things like SSL requests or external libraries).<o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">缺点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">验证信息是明文传输的 <span lang="EN-US">—     Base 64</span>是可逆算法，任何人都可以从传输的信息中得到用户名和密码，但实际都不需要这样做，只需要修改<span lang="EN-US">HTTP</span>头即可。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">用户名限制 <span lang="EN-US">— </span>当使用<span lang="EN-US">HTTP</span>验证时，冒号<span lang="EN-US">(:) </span>不可以作为用户名的一部分。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">没有加密<span lang="EN-US"> — </span>所有请求和响应都是可见的。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">这种基本的验证方式对大多数<span lang="EN-US">API</span>应用已经足够了，基本的验证允许<span lang="EN-US">API</span>既可以是客户相关也可以是客户无关的，取决于是否需要。同时允许过滤那些有问题的客户端。更好的办法是将用户名和密码组合分开，这样验证信息可以有点保护，合法用户可以使用其他信息去修改<span lang="EN-US">API</span>的使用权限。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="651"></a><a name="IDX-290"></a><a name="652"></a><a name="ch12lev4sec1"></a><b><span style="font-size: 10pt; font-family: 宋体;">服务器端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">大多数工作都是由<span lang="EN-US">web</span>服务器来完成的。<span lang="EN-US">Apache</span>可以使用一个文本文件查找用户帐号，但如果<span lang="EN-US">API</span>允许用户信息修改，那么这不是一个明智的选择。<span lang="EN-US">Apache</span>可以使用<span lang="EN-US">Berkeley</span>数据库（如果你设置了<span lang="EN-US">mode_db</span>或者<span lang="EN-US">mode_dbm</span>模块），<span lang="EN-US">BerkeleyDB</span>在大多数<span lang="EN-US">linux</span>版本里都是标准组件，如果没有安装，可以从</span><span lang="EN-US"><a href="http://www.sleepvcat.com"><span style="font-size: 12pt; font-family: 宋体;">www.sleepvcat.com</span></a></span><span style="font-size: 12pt; font-family: 宋体;">下载。要使用<span lang="EN-US">BerkeleyDB</span>，<span lang="EN-US">PHP</span>需要配置“<span lang="EN-US">-with –db4</span>”选项，相应<span lang="EN-US">Apache</span>必须要使用“<span lang="EN-US">—enable-module=auth_db</span>”选项编译。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Httpdconf</span><span style="font-size: 12pt; font-family: 宋体;">要配置为（<span lang="EN-US">(.htaccess</span>也要类似配置<span lang="EN-US">):<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">&lt;Directory /www/domains/api.example.com &gt;</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>AuthName "API Requires Registration"</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>AuthType Basic</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>AuthDBUserFile /</span><span lang="EN-US"><a href="http://www/basicAuth/api.example.com" target="_top"><span style="font-size: 12pt; font-family: 宋体;">www/basicAuth/api.example.com</span></a></span><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">/passwords.dat</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>require valid-user</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp;</span>&lt;/Directory&gt;</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Directory</span><span style="font-size: 12pt; font-family: 宋体;">参数指定被保护的文件夹<span lang="EN-US"><br />AuthName</span>指定当浏览器访问该目录时显示给用户的消息<span lang="EN-US"><br />AuthType </span>设置为<span lang="EN-US"> basic,</span>即基本<span lang="EN-US">HTTP</span>验证方式<span lang="EN-US"><br />AuthDBUserFile Berkeley</span>数据库的文件路径，它应该是<span lang="EN-US">web</span>文档根目录以外的地方 <span lang="EN-US">– </span>你不想让攻击者可以下载它吧<span lang="EN-US"><br />require </span>指明想要访问目录的用户必须存在于数据库中<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">上面这些的前提是用户可以被添加到数据库中，那么用户如何添加呢？请看下面这个函数：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">function createUser($username, $password)</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">{</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$r1 = rand(1, strlen($chars) - 1);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$r2 = rand(1, strlen($chars) - 1);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$salt = substr($chars, $r1, 1) . substr($chars, $r2, 1);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$saltedPassword = crypt($password, $salt);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$resource = dba_open("</span><span lang="EN-US"><a href="http://www./www/basicAuth/api.example.com/passwords.dat" target="_top"><span style="font-size: 12pt; font-family: 宋体;">/www/basicAuth/api.example.com/passwords.dat</span></a></span><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">", "c", "db4");</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>if (dba_insert($username, $saltedPassword, $resource))</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>{</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>dba_close($resource);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>return true;</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>}else</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>{</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>dba_close($resource);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>return false;</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>}</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">}</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">该函数最重要的部分是用<span lang="EN-US">dba_open()</span>函数打开数据库（第二个参数“<span lang="EN-US">c”</span>指定如果文件不存在则创建他，<span lang="EN-US"> “db4”</span>是数据库类型）<span lang="EN-US">,</span>插入用户名和密码，然后关闭数据库连接。<span lang="EN-US"><o:p></o:p></span></span></p>
<table class="MsoNormalTable" style="" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr style="">
<td style="padding: 0cm;" valign="top"><a name="653"></a><a name="IDX-291"></a></td>
<td style="padding: 0cm; width: 49.35pt;" valign="top" width="82">
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">注意<span lang="EN-US">&nbsp;<o:p></o:p></span></span></p>
</td>
<td style="padding: 0cm; width: 365.65pt;" valign="top" width="609">
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">随机生成的<span lang="EN-US">salt</span>会随同密码发送到<span lang="EN-US">crypt</span>函数得到一个加密的密码从而可以提高字典攻击的难度。密码仍然可以被字典攻破，因为<span lang="EN-US">crypt</span>函数会把<span lang="EN-US">salt</span>添加到加密后的密码前面。<span lang="EN-US"><o:p></o:p></span></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">下面这个函数是删除用户<span lang="EN-US">:<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">function deleteUser($user)</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">{</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$resource = dba_open("</span><span lang="EN-US"><a href="http://www./www/basicAuth/api.example.com/passwords.dat" target="_top"><span style="font-size: 12pt; font-family: 宋体;">/www/basicAuth/api.example.com/passwords.dat</span></a></span><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">", "c", "db4");</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>dba_delete($user, $resource);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>dba_close($resource);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">}</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">最后，你应该想要通过<span lang="EN-US">API</span>脚本访问用户信息：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">$username = $_SERVER['PHP_AUTH_USER'];</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">$password = $_SERVER['PHP_AUTH_PW'];</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">这两个变量都存储与<span lang="EN-US">$_SERVER</span>这个全局数组里，<span lang="EN-US">password</span>是明文存储的，需要记住，用户这时已经通过了验证，因此这些信息只是用来存放基本数据罢了。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="654"></a><a name="ch12lev4sec2"></a><b><span style="font-size: 10pt; font-family: 宋体;">客户端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">要访问<span lang="EN-US">API</span>，客户端程序需要发送一个包含了用户名和密码（<span lang="EN-US">Base64</span>加密过的）的<span lang="EN-US">HTTP</span>头。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">$authorization = base64_encode("username:password");</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">首先用户名和密码必须要用内置函数进行编码，“<span lang="EN-US">username:password</span>”则是<span lang="EN-US">HTTP </span>规范制定的格式。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">fputs($fp, "Authorization: Basic $authorization\r\n");</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在<span lang="EN-US">socket</span>连接过程中，验证头始终都和<span lang="EN-US">HTTP</span>头部一起发送。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="655"></a><a name="ch12lev3sec3"></a><b><span style="font-size: 12pt; font-family: 宋体;">基于消息的验证<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">客户端验证信息也可以和一般的消息一起发送。因为增加一个验证信息对客户端代码来说并不是多大的负担。请记住，即便使用了<span lang="EN-US">SSL</span>，<span lang="EN-US">URL</span>仍然是以明文传输的，也就是说如果验证信息是通过<span lang="EN-US">URL</span>传递的（<span lang="EN-US">REST</span>请求），那么它对传输途中的任何人都是可见的。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">优点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">处理简单 <span lang="EN-US">– </span>每次处理都进行验证，如果一个普通页面。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">容易编码 <span lang="EN-US">– </span>程序员只需要增加一个额外的参数（验证信息）<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">方便跟踪 <span lang="EN-US">– </span>可以容易地配置统计某一段时间里有多少次调用，根据情况进行限流。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="656"></a><a name="IDX-292"></a><span style="font-size: 12pt; font-family: 宋体;">缺点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">验证信息是明文 <span lang="EN-US">–     REST APIs</span>会将验证信息以明文发送无论是否使用了安全的接入点。不安全的接入点也会把验证信息以明文格式发送，无论是<span lang="EN-US">REST</span>还是<span lang="EN-US">SOAP</span>。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">没有加密 <span lang="EN-US">– </span>所有请求和响应都是对可见的。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">基于消息的验证和<span lang="EN-US">HTTP</span>验证很相似，最主要的不同是由谁来处理验证过程，<span lang="EN-US">HTTP</span>是通过服务器，而基于消息的验证则是通过<span lang="EN-US">API</span>本身。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="657"></a><a name="ch12lev4sec3"></a><b><span style="font-size: 10pt; font-family: 宋体;">服务器端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">切记验证信息应该和站内的其他验证信息分开。下面是一个基本的验证函数。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">function checkUser($username, $password)</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">{</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$query = "SELECT `user_level` FROM `users` WHERE `username` = ‘$username' AND</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>`password` = '$password'";</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>$results = getAssoc($query, 1);</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US"><span style="">&nbsp; </span>return $results[‘level'];</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">}</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="658"></a><a name="ch12lev4sec4"></a><b><span style="font-size: 10pt; font-family: 宋体;">客户端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">取决于服务器端使用的是<span lang="EN-US">SOAP</span>还是<span lang="EN-US">REST</span>，这部分在后面的“<span lang="EN-US">REST</span>？还是<span lang="EN-US">SOAP</span>”中有讨论。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="659"></a><a name="ch12lev3sec4"></a><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">SSL </span></b><b><span style="font-size: 12pt; font-family: 宋体;">接入端<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">配置<span lang="EN-US">web</span>服务器支持<span lang="EN-US">SSL</span>连接可以保护请求和响应内容，同时又不需要额外编码。服务器端证书认证只能用来确认服务器而不能用来识别验证客户端。所以仍然需要前面两种验证机制。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">优点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">加密 <span lang="EN-US">– </span>请求和响应内容都被加密，从而不会存在被监听的问题。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">服务器验证 <span lang="EN-US">– </span>客户端可以根据<span lang="EN-US">SSL</span>证书来确认服务端没有改变。使用签名机构的证书同样可以达到这样的目的。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">配置简单 <span lang="EN-US">– </span>没有额外编码，只需要配置<span lang="EN-US">web</span>服务器。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="660"></a><a name="IDX-293"></a><span style="font-size: 12pt; font-family: 宋体;">缺点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">增加了服务器负担 <span lang="EN-US">– </span>加密和解密的过程本身就需要占用较多的<span lang="EN-US">CPU</span>资源，每个请求都会需要一个额外的握手过程来建立安全套接字。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">没有客户端验证 <span lang="EN-US">– </span>使用了<span lang="EN-US">SSL</span>。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">增加了客户端负担 <span lang="EN-US">– </span>处理<span lang="EN-US">SSL</span>对客户端来说通常都会比较繁琐，可能需要安装相应的扩展包才能实现（在共享主机环境下可能会比较麻烦）。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">SSL</span><span style="font-size: 12pt; font-family: 宋体;">对任何<span lang="EN-US">API</span>都是很重要的安全机制。它提供了对请求和响应内容的保护，以及服务器的识别。并且很容易和<span lang="EN-US">HTTP</span>认证或基于消息的认证结合。但是也要根据特定情况决定是否使用<span lang="EN-US">SSL</span>，因为它毕竟会增加一些负担给服务器和客户端。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="661"></a><a name="ch12lev4sec5"></a><b><span style="font-size: 10pt; font-family: 宋体;">服务器端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">不需要代码，只需要配置<span lang="EN-US">web</span>服务器。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="662"></a><a name="ch12lev4sec6"></a><b><span style="font-size: 10pt; font-family: 宋体;">客户端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">要连接<span lang="EN-US">SSL</span>接入端，<span lang="EN-US">PHP</span>需要配置“<span lang="EN-US">--with-openssl</span>”选项。同时要看服务器是否支持<span lang="EN-US">SSL</span>，从<span lang="EN-US">phpinfo()</span>输出中看是否在<span lang="EN-US">Registerd PHP Streams</span>有“<span lang="EN-US">https</span>”。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="663"></a><a name="ch12lev3sec5"></a><b><span style="font-size: 12pt; font-family: 宋体;">客户端证书<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">API</span><span style="font-size: 12pt; font-family: 宋体;">服务器可以为每个客户端生成一个证书来建立安全的信息传输，然后这个证书会被用在验证过程，确认服务器和客户端身份。尽管这种方法提供了最高级别的安全，但它也是要求对服务器端和客户端最严格的：并非所有的工具（比如<span lang="EN-US">NuSOAP</span>）都支持客户端证书。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">优点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">身份确认<span lang="EN-US">- </span>服务器和客户端的身份都得到了确认。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">加密 <span lang="EN-US">– </span>请求和响应内容都被保护，不会被第三方监听。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">缺点<span lang="EN-US">:<o:p></o:p></span></span></p>
<ul type="disc">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">增加了处理 <span lang="EN-US">– </span>因为需要建立安全套件字，额外的工作不可避免。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">服务端额外负担 <span lang="EN-US">– </span>服务器需要为每一个客户端都生成证书，并且要确保这些<span lang="EN-US">API</span>必须要存放安全的地方，通过安全的传输通道。<span lang="EN-US"><o:p></o:p></span></span></li>
</ul>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="664"></a><a name="IDX-294"></a><span style="font-size: 12pt; font-family: 宋体;">客户端证书确保了客户端和服务端的身份，可以一定程度上保证<span lang="EN-US">API</span>的安全，但是它的代价也是很明显的<span lang="EN-US"> - </span>客户端和服务器端的<span lang="EN-US">CPU</span>的负担，并且无法使用一些方便的客户端工具与<span lang="EN-US">API</span>交互。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="665"></a><a name="ch12lev4sec7"></a><b><span style="font-size: 10pt; font-family: 宋体;">服务器端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">设置客户端证书需要一定量的工作，你很难说服所有试图使用<span lang="EN-US">API</span>的客户去花钱申请自己的证书。你也可以提供授权给客户，但这样也有一些不安全的问题 <span lang="EN-US">– </span>你必须要像一个真正的授权机构一样小心。但这仍然是一个相对轻松的解决办法，接下来我们详细介绍一下：<span lang="EN-US"><o:p></o:p></span></span></p>
<ol start="1" type="1">
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">设置证书授权。最好是使用一个独立的服务器来保存<span lang="EN-US">CA</span>的私钥，而不是用<span lang="EN-US">web</span>服务器，理想情况下，这台服务器最好不要接入互联网，而只可以连接请求密钥的机器，因为<span lang="EN-US">API</span>需要不停请求它生成密钥。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">为你的用户生成密钥，同时使用安全的连接分发。如果使用不安全的方式去分发，比如<span lang="EN-US">HTTP</span>，甚至<span lang="EN-US">email</span>，那么还不如不生成。因为完全没有必要去生成。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">配置<span lang="EN-US">web</span>服务器只接受生成的证书，用户必须提供由你签名的证书。<span lang="EN-US"><o:p></o:p></span></span></li>
<li class="MsoNormal" style="text-align: left;"><span style="font-size: 12pt; font-family: 宋体;">配置服务器使用<span lang="EN-US">SSL</span>认证。<span lang="EN-US"><o:p></o:p></span></span></li>
</ol>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="666"></a><a name="ch12lev3sec6"></a><b><span style="font-size: 12pt; font-family: 宋体;">建立你的认证（<span lang="EN-US">CA</span>）<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">OpenSSL</span><span style="font-size: 12pt; font-family: 宋体;">可以很好的完成这项工作，它包含两个很重要的脚本，<span lang="EN-US">CA.pl</span>和<span lang="EN-US">CA.sh</span>，可以自动完成这个过程。其他类似<span lang="EN-US">OpenCA</span>或者<span lang="EN-US">TinyCA</span>提供了界面更友好的方案。 考虑到你只需要做一次，那么太过友好的界面并不是很必要。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">首先需要修改<span lang="EN-US">CA</span>脚本，其中有一行代码：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">$DAYS="-days 365"<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">定义了证书的有效期为一年以内（<span lang="EN-US">365</span>天），如果觉得太短，可以设置一个大一点的值，比如<span lang="EN-US">10</span>年。<span lang="EN-US">.<o:p></o:p></span></span></p>
<p class="MsoNormal" style="margin-left: 6pt; text-align: left; text-indent: -6pt;" align="left"><span style="font-size: 12pt; font-family: 宋体;">其次，运行脚本时需要回答有关于公司的问题，<span lang="EN-US"> common name</span>这一项很重要<span lang="EN-US">- </span>它应该被配置为<span lang="EN-US">API</span>的主机名，记得使用一个健壮的密码。脚本执行时会生成一个<span lang="EN-US">demoCA</span>的文件夹，里面放置了所有生成好的文件。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">最后，生成服务器端证书。分两步，第一步，生成认证签名请求（<span lang="EN-US">Certificate Signing Request, CSR</span>）；第二部，使用<span lang="EN-US">CA</span>对<span lang="EN-US">CSR</span>进行签名。下面是用<span lang="EN-US">openssl</span>生成<span lang="EN-US">CSR</span>的命令：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">openssl req -new –key server.key –out server.csr</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="667"></a><a name="IDX-295"></a><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">openSSL</span><span style="font-size: 12pt; font-family: 宋体;">在生成密钥之前会问一系列问题，这些需要和你创建<span lang="EN-US">CA</span>时的信息匹配，以免增加不必要的额外配置。要为生成的<span lang="EN-US">CSR</span>签名，首先需要把<span lang="EN-US">CSR</span>文件（<span lang="EN-US">server.csr</span>）重命名为<span lang="EN-US">newreq.pem</span>，然后使用下面这条命令：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">CA.sh –signreq</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">它会为请求签名，最后必须要配置<span lang="EN-US">Apache</span>服务器使用证书，需要修改虚拟主机的<span lang="EN-US">httpd.conf</span>文件，增加如下信息：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLEngine On</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLCertificateFile /etc/http/conf/ssl/server.crt</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLCertificateKeyFile /etc/http/conf/ssl/server.key</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLProtocol All –SSLv2</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLCipherSuite ALL:!EXP:!NULL:!ADH:!LOW</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">前三行用来打开<span lang="EN-US">SSL</span>引擎、设置证书路径和服务器私钥路径。最后两行用来阻止<span lang="EN-US">SSL</span>使用不安全的协议。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第四，生成客户端证书：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">CA.sh –newreq</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">CA.sh –signreq</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">记得通过安全的渠道分发给用户。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第五，配置<span lang="EN-US">web</span>服务器要求客户在试图建立连接时提供证书，同时确保证书是由你签名和创建的。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLCACertificateFile /etc/http/conf/ssl/demoCA.crt</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLCARevocationFile /etc/http/conf/ssl/demoCA.crl</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLVerifyClient require</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="background: rgb(217, 217, 217) none repeat scroll 0% 0%; font-size: 12pt; font-family: 宋体; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;" lang="EN-US">SSLVerifyDepth</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">SSLCACertificateFile </span><span style="font-size: 12pt; font-family: 宋体;">要指向你放置<span lang="EN-US">CA</span>证书文件的位置，<span lang="EN-US"> SSLRevocationFile </span>要指向<span lang="EN-US">.crl</span>文件（该文件是和<span lang="EN-US">*.crt</span>文件同时生成的），没有这个文件，你就无法取消非法用户（或者不在使用<span lang="EN-US">API</span>的用户）。<span lang="EN-US">SSLVerifyClient </span>指明所有用户必须提供证书，否则将拒绝连接。最后，<span lang="EN-US"> SSLVerifyDepth 1 </span>指定所有客户端证书必须是由你的<span lang="EN-US">CA</span>直接生成的，这避免了其他用户创建合法的客户端证书。最后要重启<span lang="EN-US">Apache</span>来使这些配置生效。<span lang="EN-US"><o:p></o:p></span></span></p>
<table class="MsoNormalTable" style="" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr style="">
<td style="padding: 0cm;" valign="top"></td>
<td style="padding: 0cm; width: 35.15pt;" valign="top" width="59">
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">注意<span lang="EN-US">&nbsp;<o:p></o:p></span></span></p>
</td>
<td style="padding: 0cm; width: 379.85pt;" valign="top" width="633">
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">建议阅读<span lang="EN-US">Ivan Ristic</span>的《<span lang="EN-US">Apache Security</span>》了解更多的关于<span lang="EN-US">SSL</span>和<span lang="EN-US">Apache</span>相关的安全事宜。<span lang="EN-US"><o:p></o:p></span></span></p>
</td>
</tr>
</tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="668"></a><a name="ch12lev4sec8"></a><b><span style="font-size: 10pt; font-family: 宋体;">客户端代码<span lang="EN-US"><o:p></o:p></span></span></b></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">要连接有安全的接入端，<span lang="EN-US">PHP</span>需要配置“<span lang="EN-US">--with-openssl” </span>选项<span lang="EN-US">,</span>同时要确定<span lang="EN-US">phpinfo()</span>的输出中有<span lang="EN-US">SSL</span>支持（<span lang="EN-US">Registered PHP Stream</span>列表），并且在<span lang="EN-US">Registered Stream Socket Transports </span>中也存在<span lang="EN-US">SSL</span>项。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">因为必须要提供客户端证书，所以还要使用<span lang="EN-US">cURL</span>库。它适合用来调用<span lang="EN-US">SOAP</span>和<span lang="EN-US">REST API</span>，处理请求和响应都很类似：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">function callAPI($endpoint, $requestBody)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">{<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>$ch = curl_init();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>curl_setopt($ch, CURLOPT_URL, $endpoint);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>curl_setopt($ch, CURLOPT_SSLCERT, "../certs/cert_key_pem-1.txt");<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>curl_setopt($ch, CURLOPT_POST, TRUE);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>ob_start();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>curl_exec($ch);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>$response = ob_get_clean();<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp; </span>if (curl_error($ch))<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;</span>{<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp; </span>file_put_contents("/tmp/curl_error_log.txt", curl_errno($ch) . ": ".<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>curl_error($ch), "a+");<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp; </span>curl_close($ch);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp; </span>return null;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;</span>}else<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;</span>{<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>curl_close($ch);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;&nbsp;&nbsp; </span>return $response;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><span style="">&nbsp;</span>}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></p>
<p>  <span style="font-size: 12pt; font-family: 宋体;">这个函数使用客户端证书来建立连接，然后使用输出缓冲来获取响应内容（<span lang="EN-US">cURL</span>把输出直接发送给浏览器）。如果出现错误，响应出错信息会记录到文件；如果成功，响应结果会返回给调用函数。客户端证书切记要存放到安全的地方（<span lang="EN-US">web</span>文档根目录之外的位置）。</span></p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=64c8497f-7024-8dc7-b4c9-56eeca99948f" /></div>

	Tags: <a href="http://zhangv.com/archives/tag/%e7%bf%bb%e8%af%91" title="翻译" rel="tag">翻译</a>, <a href="http://zhangv.com/archives/tag/openapi" title="openAPI" rel="tag">openAPI</a>, <a href="http://zhangv.com/archives/tag/rest" title="REST" rel="tag">REST</a>, <a href="http://zhangv.com/archives/tag/security" title="security" rel="tag">security</a>, <a href="http://zhangv.com/archives/tag/soap" title="SOAP" rel="tag">SOAP</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/1233/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOA 就是 OpenAPI</title>
		<link>http://zhangv.com/archives/1169</link>
		<comments>http://zhangv.com/archives/1169#comments</comments>
		<pubDate>Wed, 29 Jul 2009 14:47:16 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[openAPI]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[yy]]></category>
		<category><![CDATA[互联网]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/1169</guid>
		<description><![CDATA[两个时髦的玩意，原来就是一回事。并不是很难理解，只是大家习惯了接受各种各样新名词，而又惯性的没有去把二者联系起来。知道在wikipedia的SOA词条里看到这句话：
A mature rollout of SOA effectively defines the API of the organization.
任何系统无论是复杂的商用系统还是简单的个人博客，都在提供或多或少的服务。将这些服务分割成独立的，无状态的服务单元，然后通过HTTP（webservice）或者是其他的连接方式连起来。接下来，如何compose这些服务单元又是新的问题，ESB和BPM就大行其道了。将来有一天，用网站提供的OpenAPI进行网站之间的整合，互操作，信息交换一定会催生出更多有趣的东西。
中心思想：互联网和企业应用同样都需要整合，而且整合方向和方法应该都是一样的。
纯属YY


	Tags: openAPI, SOA, yy, 互联网
]]></description>
			<content:encoded><![CDATA[<p>两个时髦的玩意，原来就是一回事。并不是很难理解，只是大家习惯了接受各种各样新名词，而又惯性的没有去把二者联系起来。知道在<a target="_blank" href="http://en.wikipedia.org/wiki/Service-oriented_architecture">wikipedia的SOA词条</a>里看到这句话：</p>
<p>A mature rollout of SOA effectively defines the API of the organization.</p>
<p>任何系统无论是复杂的商用系统还是简单的个人博客，都在提供或多或少的服务。将这些服务分割成独立的，无状态的服务单元，然后通过HTTP（webservice）或者是其他的连接方式连起来。接下来，如何compose这些服务单元又是新的问题，ESB和BPM就大行其道了。将来有一天，用网站提供的OpenAPI进行网站之间的整合，互操作，信息交换一定会催生出更多有趣的东西。</p>
<p>中心思想：互联网和企业应用同样都需要整合，而且整合方向和方法应该都是一样的。</p>
<p>纯属YY</p>
<div class="zemanta-pixie"><img class="zemanta-pixie-img" alt="" src="http://img.zemanta.com/pixy.gif?x-id=a6fb446b-4cb5-8787-af24-ab5fabbff4de" /></div>

	Tags: <a href="http://zhangv.com/archives/tag/openapi" title="openAPI" rel="tag">openAPI</a>, <a href="http://zhangv.com/archives/tag/soa" title="SOA" rel="tag">SOA</a>, <a href="http://zhangv.com/archives/tag/yy" title="yy" rel="tag">yy</a>, <a href="http://zhangv.com/archives/tag/%e4%ba%92%e8%81%94%e7%bd%91" title="互联网" rel="tag">互联网</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/1169/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>facebook-java-api验证问题</title>
		<link>http://zhangv.com/archives/1093</link>
		<comments>http://zhangv.com/archives/1093#comments</comments>
		<pubDate>Sat, 20 Jun 2009 15:56:28 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[openAPI]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/1093</guid>
		<description><![CDATA[想要用facebook-java-api做一个简单的登录验证并获取用户信息，可是：
用facebook的login页面验证后，居然是自动跳转到app的中定义的callbackUrl（也就是app host的url）。这样就给本地调试带来很大的麻烦，难不成每次做了修改都要发布到host上然后再测试？

	Tags: facebook, Java, openAPI
]]></description>
			<content:encoded><![CDATA[<p>想要用facebook-java-api做一个简单的登录验证并获取用户信息，可是：<br />
用facebook的login页面验证后，居然是自动跳转到app的中定义的callbackUrl（也就是app host的url）。这样就给本地调试带来很大的麻烦，难不成每次做了修改都要发布到host上然后再测试？</p>

	Tags: <a href="http://zhangv.com/archives/tag/facebook" title="facebook" rel="tag">facebook</a>, <a href="http://zhangv.com/archives/tag/java" title="Java" rel="tag">Java</a>, <a href="http://zhangv.com/archives/tag/openapi" title="openAPI" rel="tag">openAPI</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/1093/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>REST API vs. SOAP API</title>
		<link>http://zhangv.com/archives/1067</link>
		<comments>http://zhangv.com/archives/1067#comments</comments>
		<pubDate>Sun, 07 Jun 2009 02:45:00 +0000</pubDate>
		<dc:creator>zhangv</dc:creator>
				<category><![CDATA[技术(Tech)]]></category>
		<category><![CDATA[翻译]]></category>
		<category><![CDATA[openAPI]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[SOAP]]></category>

		<guid isPermaLink="false">http://zhangv.com/archives/1067</guid>
		<description><![CDATA[译自“Professional Web APIs with PHP: eBay,
Google, PayPal, Amazon, FedEx, Plus Web Feeds”
REST API当处理REST请求时，因为信息是通过GET，所以，信息在传输过程中会进行URL编码(URL-encoded)；当需要进一步处理时，首先要进行解码（唯一例外是用户名和密码）。不同的请求类型应该使用不同的endpoints(URLs)；如果要以单独的脚本程序来处理所有的请求，你可以让所有的请求都指向同一个endpoint，或者配置web服务器来映射许多endpoints到同一个脚本。我建议用后一种方式；它符合规范同时允许你以后在不需要影响外部接口的情况下做修改。
允许程序员使用web接口来请求API - 在调试程序时将变得非常有用；程序员可以快速的判断问题源于请求本身还是代码。你可以提供给程序员的调试工具越多，你的网站也就越容易开发。
SOAP APIs当处理SOAP请求时，首先要检查请求是否符合WSDL指定的格式。如果你使用诸如NuSOAP的工具，他可以帮你做到这一点。事实上，大多数SOAP API使用一个框架来处理许多低级的工作。 SOAP API使用单一endpoint接收所有请求（作为一个通用规则，一些大的API会根据功能来拆分到不同的endpoint），因此，或者是你有一个很大的脚本文件，或者是在每个功能点都调用很多required()方法。
允许程序员在使用web接口时可以粘贴整个请求文档到一个表单，然后发送到你的服务器。从直接的经验来看，有这样一个工具对程序员调试程序时是非常有用的。提供脚本或者函数从而让程序员可以手动创建请求对那些没有使用SOAP框架的程序员是很有帮助的。

	Tags: 翻译, openAPI, REST, SOAP
]]></description>
			<content:encoded><![CDATA[<p>译自“<a border="0"><span class="b24-booktitle">Professional Web APIs with PHP: eBay,<br />
Google, PayPal, Amazon, FedEx, Plus Web Feeds”</span></a></p>
<p>REST API<br />当处理REST请求时，因为信息是通过GET，所以，信息在传输过程中会进行URL编码(URL-encoded)；当需要进一步处理时，首先要进行解码（唯一例外是用户名和密码）。不同的请求类型应该使用不同的endpoints(URLs)；如果要以单独的脚本程序来处理所有的请求，你可以让所有的请求都指向同一个endpoint，或者配置web服务器来映射许多endpoints到同一个脚本。我建议用后一种方式；它符合规范同时允许你以后在不需要影响外部接口的情况下做修改。</p>
<p>允许程序员使用web接口来请求API - 在调试程序时将变得非常有用；程序员可以快速的判断问题源于请求本身还是代码。你可以提供给程序员的调试工具越多，你的网站也就越容易开发。</p>
<p>SOAP APIs<br />当处理SOAP请求时，首先要检查请求是否符合WSDL指定的格式。如果你使用诸如NuSOAP的工具，他可以帮你做到这一点。事实上，大多数SOAP API使用一个框架来处理许多低级的工作。 SOAP API使用单一endpoint接收所有请求（作为一个通用规则，一些大的API会根据功能来拆分到不同的endpoint），因此，或者是你有一个很大的脚本文件，或者是在每个功能点都调用很多required()方法。</p>
<p>允许程序员在使用web接口时可以粘贴整个请求文档到一个表单，然后发送到你的服务器。从直接的经验来看，有这样一个工具对程序员调试程序时是非常有用的。提供脚本或者函数从而让程序员可以手动创建请求对那些没有使用SOAP框架的程序员是很有帮助的。</p>

	Tags: <a href="http://zhangv.com/archives/tag/%e7%bf%bb%e8%af%91" title="翻译" rel="tag">翻译</a>, <a href="http://zhangv.com/archives/tag/openapi" title="openAPI" rel="tag">openAPI</a>, <a href="http://zhangv.com/archives/tag/rest" title="REST" rel="tag">REST</a>, <a href="http://zhangv.com/archives/tag/soap" title="SOAP" rel="tag">SOAP</a><br />
]]></content:encoded>
			<wfw:commentRss>http://zhangv.com/archives/1067/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

