<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="css/rss.xslt"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title> fzcs' blog</title><link>http://www.littlear.com/</link><description></description><generator>RainbowSoft Studio Z-Blog 1.8 Walle Build 100427</generator><language>zh-CN</language><copyright>Copyright © www.littlear.com Some Rights Reserved littlear.com@gmail.com&amp;amp;nbsp;&amp;amp;nbsp;辽ICP备10013361号&amp;amp;nbsp|&amp;amp;nbsp访问速度&amp;amp;nbsp|&amp;amp;nbsp|  var _gaq = _gaq || [];  _gaq.push(['_setAccount', 'UA-16473351-1']);  _gaq.push(['_trackPageview']);  (function() {    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);  })();</copyright><pubDate>Thu, 19 Jan 2012 22:04:22 +0800</pubDate><item><title>一幅图描述Git中有关数据传输的命令</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2012/01/0390/</link><pubDate>Tue, 03 Jan 2012 23:06:30 +0800</pubDate><guid>http://www.littlear.com/post/2012/01/0390/</guid><description><![CDATA[<p style="text-align: center; ">&nbsp;<img onload="ResizeImage(this,650)" alt="" title="" src="http://www.littlear.com/upload/2012/1/201201032308475668.png" /></p><p>图片来源:<a href="http://gitready.com/beginner/2009/01/21/pushing-and-pulling.html">http://gitready.com/beginner/2009/01/21/pushing-and-pulling.html</a></p>]]></description><category>编程学习</category><comments>http://www.littlear.com/post/2012/01/0390/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=90</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=90&amp;key=424f6544</trackback:ping></item><item><title>Java Web开发中验证码的实现(JSP验证码)</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2011/03/1789/</link><pubDate>Thu, 17 Mar 2011 10:35:01 +0800</pubDate><guid>http://www.littlear.com/post/2011/03/1789/</guid><description><![CDATA[<p style="">　　通常的登录注册系统都会要求输入验证码以区别用户行为和计算机程序行为来防止恶意注册、暴力破解密码等。</p><p style="">　　Jsp或者Java Web开发中通常用 Java 的&nbsp;Graphics 绘制验证码图片然后用ImageIO输出为Jpg等格式的图片再通过Session来验证输入内容与验证码内容的一致性。</p><p style="">　　具体代码和步骤如下：</p><p style="">　　1.生成验证码的Servlet</p><div class="codeText" style=""><div class="codeHead"><span class="lantxt">Java Code</span><span class="copyCodeText" style="cursor:pointer" onclick="copyIdText('code_3180')"> </span></div><div id="code_3180"><ol start="1" class="dp-j">    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;servlets;&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.io.IOException;&nbsp;&nbsp;</span></span></li>    <li><span><span class="keyword">import</span><span>&nbsp;javax.servlet.ServletException;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.servlet.http.HttpServlet;&nbsp;&nbsp;</span></span></li>    <li><span><span class="keyword">import</span><span>&nbsp;javax.servlet.http.HttpServletRequest;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.servlet.http.HttpServletResponse;&nbsp;&nbsp;</span></span></li>    <li><span><span class="keyword">import</span><span>&nbsp;javax.servlet.http.HttpSession;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.util.*;&nbsp;&nbsp;</span></span></li>    <li><span><span class="keyword">import</span><span>&nbsp;java.awt.*;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;java.awt.image.*;&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span><span class="keyword">import</span><span>&nbsp;javax.imageio.*;&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span><span class="comment">/**</span>&nbsp;</span></li>    <li><span><span class="comment">&nbsp;*&nbsp;Servlet&nbsp;implementation&nbsp;class&nbsp;test2</span>&nbsp;</span></li>    <li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>    <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;GetCaptcha&nbsp;</span><span class="keyword">extends</span><span>&nbsp;HttpServlet&nbsp;{&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">long</span><span>&nbsp;serialVersionUID&nbsp;=&nbsp;1L;&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li>    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;HttpServlet#HttpServlet()</span>&nbsp;</span></li>    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">public</span><span>&nbsp;GetCaptcha()&nbsp;{&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">super</span><span>();&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;TODO&nbsp;Auto-generated&nbsp;constructor&nbsp;stub</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li>    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;HttpServlet#doGet(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse</span>&nbsp;</span></li>    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response)</span>&nbsp;</span></li>    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;doGet(HttpServletRequest&nbsp;request,&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)&nbsp;<span class="keyword">throws</span><span>&nbsp;ServletException,&nbsp;IOException&nbsp;{&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setContentType(<span class="string">&quot;image/jpeg&quot;</span><span>);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setHeader(<span class="string">&quot;Pragma&quot;</span><span>,&nbsp;</span><span class="string">&quot;No-cache&quot;</span><span>);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setHeader(<span class="string">&quot;Cache-Control&quot;</span><span>,&nbsp;</span><span class="string">&quot;no-cache&quot;</span><span>);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response.setDateHeader(<span class="string">&quot;Expires&quot;</span><span>,&nbsp;</span><span class="number">0</span><span>);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpSession&nbsp;session&nbsp;=&nbsp;request.getSession();&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;在内存中创建图象</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;width&nbsp;=&nbsp;</span><span class="number">75</span><span>,&nbsp;height&nbsp;=&nbsp;</span><span class="number">25</span><span>;&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage&nbsp;image&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;BufferedImage(width,&nbsp;height,&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BufferedImage.TYPE_INT_RGB);&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;获取图形上下文</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Graphics&nbsp;g&nbsp;=&nbsp;image.getGraphics();&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;生成随机类</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Random&nbsp;random&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;Random();&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;设定背景色</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(getRandColor(<span class="number">200</span><span>,&nbsp;</span><span class="number">250</span><span>));&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.fillRect(<span class="number">0</span><span>,&nbsp;</span><span class="number">0</span><span>,&nbsp;width,&nbsp;height);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;设定字体</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setFont(<span class="keyword">new</span><span>&nbsp;Font(</span><span class="string">&quot;Times&nbsp;New&nbsp;Roman&quot;</span><span>,&nbsp;Font.PLAIN,&nbsp;</span><span class="number">24</span><span>));&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;画边框</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(getRandColor(<span class="number">160</span><span>,&nbsp;</span><span class="number">200</span><span>));&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.drawRect(<span class="number">0</span><span>,&nbsp;</span><span class="number">0</span><span>,&nbsp;width&nbsp;-&nbsp;</span><span class="number">1</span><span>,&nbsp;height&nbsp;-&nbsp;</span><span class="number">1</span><span>);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;随机产生155条干扰线，使图象中的认证码不易被其它程序探测到</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(getRandColor(<span class="number">160</span><span>,&nbsp;</span><span class="number">200</span><span>));&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;</span><span class="number">155</span><span>;&nbsp;i++)&nbsp;{&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;x&nbsp;=&nbsp;random.nextInt(width);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;y&nbsp;=&nbsp;random.nextInt(height);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;xl&nbsp;=&nbsp;random.nextInt(</span><span class="number">12</span><span>);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;yl&nbsp;=&nbsp;random.nextInt(</span><span class="number">12</span><span>);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.drawLine(x,&nbsp;y,&nbsp;x&nbsp;+&nbsp;xl,&nbsp;y&nbsp;+&nbsp;yl);&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;取随机产生的认证码(4位数字)</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;sRand&nbsp;=&nbsp;<span class="string">&quot;&quot;</span><span>;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;</span><span class="number">4</span><span>;&nbsp;i++)&nbsp;{&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;rand&nbsp;=&nbsp;String.valueOf(random.nextInt(<span class="number">10</span><span>));&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sRand&nbsp;+=&nbsp;rand;&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;将认证码显示到图象中</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.setColor(<span class="keyword">new</span><span>&nbsp;Color(</span><span class="number">20</span><span>&nbsp;+&nbsp;random.nextInt(</span><span class="number">110</span><span>),&nbsp;</span><span class="number">20</span><span>&nbsp;+&nbsp;random&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.nextInt(<span class="number">110</span><span>),&nbsp;</span><span class="number">20</span><span>&nbsp;+&nbsp;random.nextInt(</span><span class="number">110</span><span>)));&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.drawString(rand,&nbsp;<span class="number">13</span><span>&nbsp;*&nbsp;i&nbsp;+&nbsp;</span><span class="number">14</span><span>,&nbsp;</span><span class="number">20</span><span>);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;将认证码存入SESSION</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.setAttribute(<span class="string">&quot;vcode&quot;</span><span>,&nbsp;sRand);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;图象生效</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;g.dispose();&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;输出图象到页面</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ImageIO.write(image,&nbsp;<span class="string">&quot;JPEG&quot;</span><span>,&nbsp;response.getOutputStream());&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>    <li class="alt"><span>&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">/**</span>&nbsp;</span></li>    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;HttpServlet#doPost(HttpServletRequest&nbsp;request,&nbsp;HttpServletResponse</span>&nbsp;</span></li>    <li><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;response)</span>&nbsp;</span></li>    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;doPost(HttpServletRequest&nbsp;request,&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;response)&nbsp;<span class="keyword">throws</span><span>&nbsp;ServletException,&nbsp;IOException&nbsp;{&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;Color&nbsp;getRandColor(<span class="keyword">int</span><span>&nbsp;fc,&nbsp;</span><span class="keyword">int</span><span>&nbsp;bc)&nbsp;{</span><span class="comment">//&nbsp;给定范围获得随机颜色</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Random&nbsp;random&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;Random();&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(fc&nbsp;&gt;&nbsp;</span><span class="number">255</span><span>)&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fc&nbsp;=&nbsp;<span class="number">255</span><span>;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;(bc&nbsp;&gt;&nbsp;</span><span class="number">255</span><span>)&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bc&nbsp;=&nbsp;<span class="number">255</span><span>;&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;r&nbsp;=&nbsp;fc&nbsp;+&nbsp;random.nextInt(bc&nbsp;-&nbsp;fc);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;g&nbsp;=&nbsp;fc&nbsp;+&nbsp;random.nextInt(bc&nbsp;-&nbsp;fc);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">int</span><span>&nbsp;b&nbsp;=&nbsp;fc&nbsp;+&nbsp;random.nextInt(bc&nbsp;-&nbsp;fc);&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Color(r,&nbsp;g,&nbsp;b);&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li>    <li><span>&nbsp;&nbsp;</span></li>    <li class="alt"><span>}&nbsp;&nbsp;</span></li></ol></div></div><p style="">　　2.web.xml中添加上面Servlet的映射信息</p><div class="codeText" style=""><div class="codeHead"><span class="lantxt">XML/HTML Code</span><span class="copyCodeText" style="cursor:pointer" onclick="copyIdText('code_2509')"> </span></div><div id="code_2509"><ol start="1" class="dp-xml">    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">servlet</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">description</span><span class="tag">&gt;</span><span>用于生成验证码</span><span class="tag">&lt;/</span><span class="tag-name">description</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">display-name</span><span class="tag">&gt;</span><span>生成验证码</span><span class="tag">&lt;/</span><span class="tag-name">display-name</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>GetCaptcha</span><span class="tag">&lt;/</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-class</span><span class="tag">&gt;</span><span>servlets.GetCaptcha</span><span class="tag">&lt;/</span><span class="tag-name">servlet-class</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li><span><span class="tag">&lt;/</span><span class="tag-name">servlet</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li></ol></div></div><div class="codeText" style=""><div class="codeHead"><span class="lantxt">XML/HTML Code</span><span class="copyCodeText" style="cursor:pointer" onclick="copyIdText('code_6532')"> </span></div><div id="code_6532"><ol start="1" class="dp-xml">    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">servlet-mapping</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li><span>&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>GetCaptcha</span><span class="tag">&lt;/</span><span class="tag-name">servlet-name</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li class="alt"><span>&nbsp;&nbsp;<span class="tag">&lt;</span><span class="tag-name">url-pattern</span><span class="tag">&gt;</span><span>/getcaptcha.sl</span><span class="tag">&lt;/</span><span class="tag-name">url-pattern</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li>    <li><span><span class="tag">&lt;/</span><span class="tag-name">servlet-mapping</span><span class="tag">&gt;</span><span>&nbsp;&nbsp;</span></span></li></ol></div></div><p style="">　　3.在前台界面中调用此Servlet</p><div class="codeText" style=""><div class="codeHead"><span class="lantxt">XML/HTML Code</span><span class="copyCodeText" style="cursor:pointer" onclick="copyIdText('code_6466')"> </span></div><div id="code_6466"><ol start="1" class="dp-xml">    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">img</span><span>&nbsp;</span><span class="attribute">src</span><span>=</span><span class="attribute-value">&quot;getcaptcha.sl&quot;</span><span>&nbsp;</span><span class="attribute">alt</span><span>=</span><span class="attribute-value">&quot;验证码&quot;</span><span>&nbsp;</span><span class="attribute">name</span><span>=</span><span class="attribute-value">&quot;checkImg&quot;</span><span>&nbsp;</span><span class="attribute">id</span><span>=</span><span class="attribute-value">&quot;checkImg&quot;</span><span>&nbsp;</span><span class="attribute">style</span><span>=</span><span class="attribute-value">&quot;position:relative;&nbsp;top:5px;&nbsp;left:20px;&nbsp;&quot;</span><span>&nbsp;</span><span class="attribute">onClick</span><span>=</span><span class="attribute-value">&quot;document.getElementById('checkImg').src='getcaptcha.sl?temp='+&nbsp;(new&nbsp;Date().getTime().toString(36));&nbsp;return&nbsp;false&quot;</span><span class="tag">/&gt;</span><span>&nbsp;&nbsp;</span></span></li></ol></div></div><p style="">　　直接点击图片更换验证码。</p><p style="">&nbsp;</p><p style="">（转载请指明出处）</p>]]></description><category>编程学习</category><comments>http://www.littlear.com/post/2011/03/1789/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=89</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=89&amp;key=731a94b3</trackback:ping></item><item><title>OAuth授权的Java实现详解</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2011/01/0285/</link><pubDate>Sun, 02 Jan 2011 22:29:35 +0800</pubDate><guid>http://www.littlear.com/post/2011/01/0285/</guid><description><![CDATA[<p style="">由于最近在开发一个关于微博整合的小应用，于是开始接触各大微博平台的开放平台（新浪、搜狐、网易、QQ）：目前这几大微博的应用开发都采用OAuth授权，要访问大部分API都需要OAuth方式的身份鉴权。</p><h3 style="">OAuth是什么？</h3><p style="">先来简单介绍一下OAuth授权协议：OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。同时，任何第三方都可以使用OAuth认证服务，任何服务提供商都可以实现自身的OAuth认证服务，因而OAUTH是开放的。业界提供了OAuth的多种实现如PHP，JavaScript，Java，Ruby等各种语言开发包，大大节约了程序员的时间，因而OAuth是简易的。目前互联网很多服务如Open API，很多大头公司如Google，Yahoo，Microsoft等都提供了OAuth认证服务，这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。</p><h3 style="">OAuth的授权流程</h3><p style="">你所开发的应用需要流程如下：</p><ol style="">    <li>向应用服务商（新浪、搜狐等微博）请求request_token。</li>    <li>得到request_token后重定向用户到服务商的授权页面。</li>    <li>如果用户选择授权你得应用，用request_token向服务商请求换取access_token。</li>    <li>得到access_token等信息访问受限资源。</li></ol><p style="">而服务商相应的响应如下：</p><ol style="">    <li>创建request_token返回给应用。</li>    <li>询问用户是否授权此应用。如果用户授权重定向用户至应用页面。</li>    <li>创建access_token并返回给应用。</li>    <li>响应受限资源请求并返回相关信息。</li></ol><p style="">通俗点的说法就是&ldquo;你拿着你得身份证明（request_token）向服务商申请进入用户家的门钥匙（access_token），服务商询问用户同不同意，如果用户同意服务商就给你进入用户家门的钥匙（access_token），拿到钥匙后你就可以进到用户家里&rdquo;。</p><h3 style="">OAuth授权的Java实现</h3><p style="">作为一个开放协议目前有很多现成的Oauth库可供开发者使用，可以<a target="_blank" href="http://code.google.com/p/oauth/">点击这里</a>下载。不过有精力有时间的话还是自己去实现一下OAuth授权的流程，可以很好的体会OAuth认证协议的原理。以</p><p style="">下面就是我使用Java实现Oauth的具体步骤，代码很简单，如果有画蛇添足的地方还望高手一笑而过。</p><h3 style="">一、获取Request_token</h3><p style="">首先得准备一下参数及其来源：</p><ol>    <li>oauth_consumer_key &mdash;&mdash; 注册应用后由应用服务商提供</li>    <li>consumer_secret &mdash;&mdash;&nbsp;注册应用后由应用服务商提供</li>    <li>oauth_callback &mdash;&mdash; 用户授权后的返回地址</li>    <li>oauth_nonce &mdash;&mdash; 随机字符串，须保证每次都不同</li>    <li>oauth_timestamp &mdash;&mdash; 时间戳</li>    <li>oauth_signature_method &mdash;&mdash; 签名base string 的方法，目前支持&nbsp;HMAC-SHA1</li>    <li>oauth_version &mdash;&mdash; Oauth协议版本</li></ol><p style="">还需要下面三个请求地址（这些地址任何一个提供OAuth的服务商都会提供给你，看下API文档就会找到）：</p><ol>    <li>requst_token_url &mdash;&mdash; 上面第1步中的请求地址</li>    <li>authorize_url &mdash;&mdash; 上面第2步的请求地址</li>    <li>access_token_url &mdash;&mdash; 上面第3步的请求地址</li></ol><p style="">至于如何注册应用，新浪微博<a target="_blank" href="http://open.t.sina.com.cn/">点此</a>，网易微博<a target="_blank" href="http://open.t.163.com/">点此</a>，腾讯微博<a target="_blank" href="http://open.t.qq.com/">点此</a>，搜狐微博需要你发邮件索取，具体<a target="_blank" href="http://open.t.sohu.com/en/FAQ">看这里</a>。注册成功后就会获得oauth_consumer_key 和&nbsp;consumer_secret 两个参数。</p><p style="">oauth_callback&nbsp;起的作用是当用户授权成功后服务商会把用户重定向到这个网址。</p><p style="">oauth_nonce&nbsp;是一个随机字符串下面是我的生成代码：</p><blockquote style=""><p>public String set_nonce() {<br />String base = &quot;abcdefghijklmnopqrstuvwxyz0123456789&quot;;<br />Random random = new Random();<br />StringBuffer sb = new StringBuffer();<br />for (int i = 0; i &lt; 18; i++) {<br />int number = random.nextInt(base.length());<br />sb.append(base.charAt(number));<br />}<br />return sb.toString();<br />}</p></blockquote><p style="">oauth_timestamp 是请求的时间戳，我的代码如下：</p><blockquote style=""><p>public String set_timestamp() {</p><p>Date date = new Date();<br />long time = date.getTime();<br />return (time + &quot;&quot;).substring(0, 10);<br />}</p></blockquote><p style="">需要说明一下的是这里的时间戳为10位而不是13位，因此截取0-10位置。</p><p style="">其他参数直接指定就行了。</p><p style="">接下来，有了这些参数就可以组装base string了。准备base string的目的就是为了得到&nbsp;oauth_signature 这个参数，这个参数向服务商发送请求的时候需要用到。</p><p style="">组装的方法是用下面8部分</p><ol style="">    <li>POST（也可以是GET，取决于你应用服务商支持哪个）。</li>    <li>Urlencode之后的requst_token_url&nbsp;。</li>    <li>oauth_callback=Urlencode之后你的oauth_callback（Urlencode的参数为&ldquo;utf-8&rdquo;）。</li>    <li>oauth_consumer_key = 你的oauth_consumer_key&nbsp;</li>    <li>oauth_nonce = 你的oauth_nonce&nbsp;</li>    <li>oauth_signature_method = 你的&nbsp;oauth_signature_method&nbsp;</li>    <li>oauth_timestamp = 你的oauth_timestamp&nbsp;</li>    <li>oauth_version = &ldquo;1.0&rdquo;&mdash;&mdash;目前大多数OAuth都采用的是1.0或1.0a版本。</li></ol><div style="">需要注意的是上面除了1跟2外其他参数的格数形如： abc=&ldquo;abc&rdquo; ，然后先将上面1和2部分用&amp;号相连得到串A、3-8部分用&amp;相连得到串B，下面需要将串B再进行一次Urlencode得到串C,最后将A跟C以&amp;号相连就得到了base string。这个过程中&nbsp;oauth_callback 实质上经过了两次&nbsp;Urlencode ，组装base string是非常容易出错的，一不小心丢一个引号或者格式稍有不对就会出错。</div><p style="">下面是我的Java实现代码：</p><blockquote style=""><p>public String set_basestring() throws UnsupportedEncodingException {<br />String bss;<br />bss = oauth_request_method + &quot;&amp;&quot;<br />+ URLEncoder.encode(requst_token_url, &quot;utf-8&quot;) + &quot;&amp;&quot;;<br />String bsss = &quot;oauth_callback=&quot;<br />+ URLEncoder.encode(oauth_callback, &quot;utf-8&quot;)<br />+ &quot;&amp;oauth_consumer_key=&quot; + oauth_consumer_key + &quot;&amp;oauth_nonce=&quot;<br />+ oauth_nonce + &quot;&amp;oauth_signature_method=&quot;<br />+ oauth_signature_method + &quot;&amp;oauth_timestamp=&quot;<br />+ oauth_timestamp + &quot;&amp;oauth_version=&quot; + oauth_version;<br />bsss = URLEncoder.encode(bsss, &quot;utf-8&quot;);<br />return bss + bsss;<br />}</p></blockquote><p style="">有了base string就可以签名生成oauth_signature这个参数，oauth_signature会在请求request_token的时候用到。签名算法是HMAC-SHA1，签名的key就是最开始的consumer_secret后加一个&amp;号，签名算法代码如下：</p><blockquote style=""><p style="">public String hmacsha1(String data, String key) {<br />byte[] byteHMAC = null;<br />try {<br />Mac mac = Mac.getInstance(&quot;HmacSHA1&quot;);<br />SecretKeySpec spec = new SecretKeySpec(key.getBytes(), &quot;HmacSHA1&quot;);<br />mac.init(spec);<br />byteHMAC = mac.doFinal(data.getBytes());<br />} catch (InvalidKeyException e) {<br />e.printStackTrace();<br />} catch (NoSuchAlgorithmException ignore) {<br />}<br />String oauth = new BASE64Encoder().encode(byteHMAC);<br />return oauth;<br />}</p></blockquote><p style="">里面用的的BASE64Encoder这个类可以Google一个。</p><p style="">得到oauth_signature后就要开始向&nbsp;requst_token_url 发送请求了，OAuth规范定义了三种传递OAuth参数方式：</p><ol>    <li>httpheader中</li>    <li>url中</li>    <li>post form中</li></ol><p style="">国内各大微博的支持情况是：新浪Httpheader可用,网易Httpheader可用，腾讯只支持在url，搜狐由于没有appkey所以还没去尝试。</p><p style="">如果使用Httpheader传递参数头名为&ldquo;Authorization&rdquo;，值为下面的格式，将值改为自己应用的。</p><blockquote style=""><p style="">OAuth oauth_nonce=&quot;9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8&quot;, oauth_signature_method=&quot;HMAC-SHA1&quot;, oauth_timestamp=&quot;1272323047&quot;, oauth_consumer_key=&quot;GDdmIQH6jhtmLUypg82g&quot;, oauth_token=&quot;8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&quot;, oauth_verifier=&quot;pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY&quot;, oauth_signature=&quot;PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D&quot;, oauth_version=&quot;1.0&quot;</p></blockquote><p style="">url和post form两种方式的参数名和参数值也即上面的，完全一样。</p><p style="">请求发送成功后就会得到的响应如下：</p><blockquote style=""><p style="">oauth_token=8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc&amp;oauth_token_secret=x6qpRnlEmW9JbQn4PQVVeVG8ZLPEx6A0TOebgwcuA&amp;oauth_callback_confirmed=true</p></blockquote><p style="">可以看到响应里面已经包含oauth_token和oauth_token_secret了，存贮之以备后面使用。</p><h3 style="">二、用户认证</h3><p style="">拿到了oauth_token之后就需要用户对此oauth_token授权，也即对你的应用授权，具体做法就是发送oauth_token到服务商并请求用户对此oauth_token授权：实现方法为以oauth_token和oauth_callback为参数请求oauthorize_url，Servlet中的代码如下：</p><blockquote><p>resp.sendRedirect(oauthorize_url+&quot;?oauth_token=&quot;+oauth_token+&quot;&amp;oauth_callback=&quot;+oauth_callback);</p></blockquote><p>&nbsp;这是用户就被带到了应用授权页面，并可以选择是否对该应用授权。如果用户授权之后就会被带到oauth_callback 地址。同时如果需要服务商会给oauth_callback返会一个名为oauth_verifier的参数（此参数用于无法跳转的桌面应用，不一定每个微博平台都会返回），这时候我们的oauth_token已经获得用户的授权了。</p><h3>三、用oauth_token换取access_token</h3><p>这一步跟第一步&ldquo;获取Request_token&rdquo;基本相同，也是需要准备 base string 对其签名，然后发送请求，可以参考第一步的代码实现：但是相应的参数有所不用，具体来讲就是第一步组装base string 时候8个部分中第二个部分中的url换为access_token_url 并去掉oauth_callback加上oauth_token（如果有oauth_verifier的话也需要一并加上），组装好之后需要签名以得到oauth_signature，本次签名的方法跟上次一样，但是key变为consumer_secret和oauth_token_secret以&amp;连接的串。</p><p>下来需要向access_token_url发送请求，请求参数包括base string 里的除了请求方法（POST或GET）和请求地址外的所有参数及其值和签名后生成的oauth_signature。例子如下：</p><blockquote><p>OAuth oauth_nonce="9zWH6qe0qG7Lc1telCn7FhUbLyVdjEaL3MO5uHxn8", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1272323047", oauth_consumer_key="GDdmIQH6jhtmLUypg82g", oauth_token="8ldIZyxQeVrFZXFOZH5tAwj6vzJYuLQpl0WUEYtWc", oauth_verifier="pDNg57prOHapMbhv25RNf75lVRd6JDsni1AJJIDYoTY", oauth_signature="PUw%2FdHA4fnlJYM6RhXk5IU%2F0fCc%3D", oauth_version="1.0"&quot;</p></blockquote><p>请求成功会服务商就会返回oauth_token和oaut_token_secret，这里的oauth_token和oaut_token_secret就是真正访问资源要用的access_token。</p><p>还需要说明的是以上过程只需要经行一次，就是说你拿到的access_token是不会过期的，除非用户手动将授权收回，因此作为access_token的oauth_token和oaut_token_secret要保存起来，以后访问受限资源的时候可以直接使用。至于如何访问受限资源，等以后有时间了再补上。</p><p>（本文系原创，转载请注明出处）</p>]]></description><category>编程学习</category><comments>http://www.littlear.com/post/2011/01/0285/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=85</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=85&amp;key=22c76c7b</trackback:ping></item><item><title>Google Maps让你横渡太平洋</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/11/2481/</link><pubDate>Wed, 24 Nov 2010 10:32:50 +0800</pubDate><guid>http://www.littlear.com/post/2010/11/2481/</guid><description><![CDATA[<p>在谷歌地图中以Taiwan为起点，China为终点查询路线。</p><p><div style="margin:10px 0 10px 0;text-align:center;"><img onload="ResizeImage(this,650)" alt="" title="" src="http://www.littlear.com/upload/2010/11/201011241033387878.jpg" /></div></p><p>第24步如下：</p><p><div style="margin:10px 0 10px 0;text-align:center;"><img onload="ResizeImage(this,650)" alt="" title="" src="http://www.littlear.com/upload/2010/11/201011241033505234.jpg" /></div></p>]]></description><category>软件技巧</category><comments>http://www.littlear.com/post/2010/11/2481/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=81</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=81&amp;key=87439f13</trackback:ping></item><item><title>Java、PHP、Python与MySQL交互的性能测试</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/10/1976/</link><pubDate>Tue, 19 Oct 2010 08:28:14 +0800</pubDate><guid>http://www.littlear.com/post/2010/10/1976/</guid><description><![CDATA[<p style="text-indent: 2em; ">这几天看源码弄清了一件事：WEB服务器接收浏览器请求、将请求传给PHP/Python进程（FCGI等）、与数据库进行交互都是用socket（套接字）。</p><p style="text-indent: 2em; ">也就是说，这些行为都是进程间通信。一台WEB服务器在硬件、操作系统不变的情况下，它的性能主要取决于socket通信的速度。如果所有进程都在一台服务器上的话，这个速度就取决于通信的效率了。</p><p style="text-indent: 2em; ">例如与MySQL数据库交互时，程序会调用驱动程序来访问数据库，这个驱动程序主要做这几件事：</p><p style="text-indent: 2em; ">&nbsp;1.创建socket，连接到MySQL。<br />2.将程序调用的API翻译成SQL语句，通过socket发送给MySQL；MySQL执行后，将结果发送回来；驱动程序将结果（字符串）传给程序，如有需要，还可以自动翻译成程序能识别的变量类型（如整型）。<br />3.断开连接。</p><p style="text-indent: 2em; ">可见连接的速度、翻译的速度和接受响应的及时性是最主要的3个方面。</p><p style="text-indent: 2em; ">&nbsp;弄明白这点后就不难发现，与数据库的执行时间相比，这些只是很少的一部分；而且PHP和Python使用的都是C实现，而JDBC是用Java实现，所以根本不必担心PHP和Python的性能。不过在翻译方面还存在算法和实现上的差异，客户端还可以缓存一些语句，所以仍然会出现一些性能上的差异。为证明我的想法，我特意去测试了一番。</p><p style="text-indent: 2em; ">首先列出测试平台：</p><blockquote style="text-indent: 2em; "><ul>    <li>CPU：Intel Core2 Duo T9400 @ 2.53GHz</li>    <li>内存：3GB</li>    <li>操作系统：Windows XP Pro SP2</li>    <li>MySQL：5.1.36</li>    <li>Java：1.6.0_17-b04</li>    <li>JDBC：MySQL Connector/J 5.1.10</li>    <li>PHP：5.2.11 (cli)</li>    <li>MySQLi：5.2.11.11</li>    <li>Python：2.6.4</li>    <li>MySQL-Python：1.2.3c1</li></ul></blockquote><p style="text-indent: 2em; ">&nbsp;</p><p style="text-indent: 2em; ">所用的库都是最新版的，也都采用了最为推荐的库。<br />但数据库并没有使用最新的稳定版，因为我懒得重下了。5.4.3-beta测试版也试过，在连续插入时，性能比5.1快1～2个数量级，估计是服务器端缓存和设置的原因。</p><p style="text-indent: 2em; ">测试项目：</p><ul style="text-indent: 2em; ">    <li>创建100万个随机数，并生成插入这些随机数的SQL语句。</li>    <li>连接本地数据库，如不成功，尝试创建数据库。</li>    <li>删除并创建数据库表，引擎类型为InnoDB，主键为自动递增的整数，此外有个浮点型的字段（无索引）。</li>    <li>分成100组，每次插入1万个随机数。（因为每组的执行量都很大，因此启用自动提交事务。）</li>    <li>用SELECT COUNT(*)统计小于0.1的随机数个数。（约10万个）</li>    <li>用SELECT *取出再统计大于0.9的随机数个数。（约10万个）</li>    <li>将所有0.4～0.5之间的随机数加1。（约10万个）</li>    <li>将所有0.5～0.6之间的行删除。（约20万个）</li>    <li>断开数据库连接。</li>    <li>再次连接数据库。</li></ul><p style="text-indent: 2em; ">每种测试3次（等硬盘灯无闪烁后才进行下一次测试），取最好的一次作为测试结果：</p><p style="text-indent: 2em; ">java：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量：1000000</li>    <li>测试引擎：InnoDB</li>    <li>共有99465个小于0.1的随机数</li>    <li>共有99859个大于0.9的随机数</li>    <li>创建随机数：2.367840</li>    <li>初次连接数据库：0.220420</li>    <li>再次连接数据库：0.013174</li>    <li>初始化数据库和表：0.075140</li>    <li>插入：12.139346</li>    <li>选择（COUNT）：1.130345</li>    <li>选择：1.017769</li>    <li>更新：6.173245</li>    <li>删除：9.380070</li>    <li>关闭连接：0.002131</li>    <li>总时间：32.506307</li></ul></blockquote><p style="text-indent: 2em; ">php：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量：1000000</li>    <li>测试引擎：InnoDB</li>    <li>共有99898个小于0.1的随机数</li>    <li>共有100152个大于0.9的随机数</li>    <li>创建随机数：1.506294</li>    <li>初次连接数据库：0.003146</li>    <li>再次连接数据库：0.001808</li>    <li>初始化数据库和表：0.131754</li>    <li>插入：12.046944</li>    <li>选择（COUNT）：1.236742</li>    <li>选择：1.238153</li>    <li>更新：6.115232</li>    <li>删除：8.145547</li>    <li>关闭连接：0.000125</li>    <li>总时间：30.423937</li></ul></blockquote><p style="text-indent: 2em; ">Python（MySQLdb）：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量： 1000000</li>    <li>测试引擎： InnoDB</li>    <li>共有100040个小于0.1的随机数</li>    <li>共有100351个大于0.9的随机数</li>    <li>创建随机数： 1.6822107279</li>    <li>初次连接数据库： 0.0332120423126</li>    <li>再次连接数据库： 0.00221704155137</li>    <li>初始化数据库： 0.131054924578</li>    <li>插入： 11.7999030603</li>    <li>选择（COUNT） 1.27067266929</li>    <li>选择： 1.16714526567</li>    <li>更新： 6.29200638629</li>    <li>删除： 8.13660563005</li>    <li>关闭连接： 0.000131022238861</li>    <li>总时间： 30.5129417286</li></ul></blockquote><p style="text-indent: 2em; ">Python（_mysql）：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量： 1000000</li>    <li>测试引擎： InnoDB</li>    <li>共有99745个小于0.1的随机数</li>    <li>共有99869个大于0.9的随机数</li>    <li>创建随机数： 1.68099074044</li>    <li>初次连接数据库： 0.0112056141213</li>    <li>再次连接数据库： 0.00159293988482</li>    <li>初始化数据库： 0.130169616529</li>    <li>插入： 12.1364623157</li>    <li>选择（COUNT） 1.125517908</li>    <li>选择： 0.968366649951</li>    <li>更新： 6.8042843434</li>    <li>删除： 8.9760508668</li>    <li>关闭连接： 9.61015995031e-05</li>    <li>总时间： 31.8331441566</li></ul></blockquote><p style="text-indent: 2em; ">可以看到，在大批量数据测试中，Java是最慢的，而PHP是最快的。<br />不考虑IO性能的波动的话，Java主要慢在连接和关闭数据库。JDBC 4.0在第一次连接数据库时会动态加载驱动，非常耗时，因此使用Java要记住使用数据库连接池，避免连接浪费大量时间。当然，这也造成了数据库的负担，势必影响内存占用。而创建随机数的算法实现各不相同，所以不具备可比性；令我惊讶的是SELECT的翻译速度，将字符串转换成浮点数居然慢于Python，要知道后者的浮点数可是对象。<br />PHP连接数据库非常快，所以完全无需使用连接池，因为维护连接池会增加复杂性。<br />Python的表现和PHP差不多，但是第一次连接数据库比较慢（仍比Java快1个数量级）。如果不用连接池，则使用FCGI等方式来运行比较合适。_mysql模块的通信很快，但更新和删除操作却不太理想，也许是IO性能波动的原因。此外，我在连接数据库时使用了转换参数，实际上我用的语句都不需要翻译，不使用的话会更快一点。</p><p style="text-indent: 2em; ">接着试试小数据，改成最常用的MyISAM引擎，插入100条（1组）。一般的应用不可能一次插入那么多，所以足够满足平时的应用了；而且由于数据量很小，也基本不受IO影响。</p><p style="text-indent: 2em; ">测试结果：</p><p style="text-indent: 2em; ">java：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量：100</li>    <li>测试引擎：MyISAM</li>    <li>共有9个小于0.1的随机数</li>    <li>共有10个大于0.9的随机数</li>    <li>创建随机数：0.001596</li>    <li>初次连接数据库：0.224135</li>    <li>再次连接数据库：0.018656</li>    <li>初始化数据库和表：0.055601</li>    <li>插入：0.001476</li>    <li>选择（COUNT）：0.000529</li>    <li>选择：0.000433</li>    <li>更新：0.000304</li>    <li>删除：0.000313</li>    <li>关闭连接：0.000927</li>    <li>总时间：0.285314</li></ul></blockquote><p style="text-indent: 2em; ">PHP：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量：测试数据量：100</li>    <li>测试引擎：MyISAM</li>    <li>共有12个小于0.1的随机数</li>    <li>共有9个大于0.9的随机数</li>    <li>创建随机数：0.000649</li>    <li>初次连接数据库：0.008077</li>    <li>再次连接数据库：0.001609</li>    <li>初始化数据库和表：0.060421</li>    <li>插入：0.001860</li>    <li>选择（COUNT）：0.000580</li>    <li>选择：0.000465</li>    <li>更新：0.000326</li>    <li>删除：0.000373</li>    <li>关闭连接：0.000127</li>    <li>总时间：0.072878</li></ul></blockquote><p style="text-indent: 2em; ">&nbsp;</p><p style="text-indent: 2em; ">Python（MySQLdb）：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量： 100</li>    <li>测试引擎： MyISAM</li>    <li>共有14个小于0.1的随机数</li>    <li>共有9个大于0.9的随机数</li>    <li>创建随机数： 0.000198907961766</li>    <li>初次连接数据库： 0.0334640296462</li>    <li>再次连接数据库： 0.00150577796899</li>    <li>初始化数据库： 0.0123194428342</li>    <li>插入： 0.00125211444471</li>    <li>选择（COUNT） 0.000581079438867</li>    <li>选择： 0.000484139744018</li>    <li>更新： 0.000250311142897</li>    <li>删除： 0.000262323842835</li>    <li>关闭连接： 7.98984228442e-05</li>    <li>总时间： 0.0488922474784</li></ul></blockquote><p style="text-indent: 2em; ">&nbsp;</p><p style="text-indent: 2em; ">Python（_mysql）：</p><blockquote style="text-indent: 2em; "><ul>    <li>测试数据量： 100</li>    <li>测试引擎： MyISAM</li>    <li>共有12个小于0.1的随机数</li>    <li>共有10个大于0.9的随机数</li>    <li>创建随机数： 0.000214273043082</li>    <li>初次连接数据库： 0.0118774872225</li>    <li>再次连接数据库： 0.00123702872851</li>    <li>初始化数据库： 0.0315031659052</li>    <li>插入： 0.00120322554962</li>    <li>选择（COUNT） 0.000596165155069</li>    <li>选择： 0.000507327048549</li>    <li>更新： 0.0002447238406</li>    <li>删除： 0.00026148574749</li>    <li>关闭连接： 5.78285787719e-05</li>    <li>总时间： 0.0464656820909</li></ul></blockquote><p style="text-indent: 2em; ">&nbsp;</p><p style="text-indent: 2em; ">从结果可以看出，虽然差距都很小，但Python仍然稍微占优。不过Java的SELECT操作稍微胜出，而这也是实际应用中最常使用的操作。</p><p style="text-indent: 2em; ">再从语言方面来看，Python无疑是写得最欢畅的，生成随机数只用了1行代码；PHP的变量要写个$让我老是出错，不过数据库操作不需要处理异常，这点节省了很多代码；Java的代码量很大，而且不得不使用很多try...catch，我甚至懒得以安全的方式将close()放在finally块里面，因为它也会抛出我根本懒得去管的异常，且会提示我计时变量可能没有初始化。</p><p style="text-indent: 2em; ">总体上来看，Google放弃Python，只采用C++和Java是有点不明智。因为页面响应时间主要在于数据库通信和磁盘文件IO上，语言的影响基本忽略不计。</p><p style="text-indent: 2em; text-align: center; ">本文转自keakon的blog 原文地址：<a href="http://www.keakon.cn/bbs/thread-1858-1-1.html">http://www.keakon.cn/bbs/thread-1858-1-1.html</a></p>]]></description><category>编程学习</category><comments>http://www.littlear.com/post/2010/10/1976/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=76</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=76&amp;key=8d7c4569</trackback:ping></item><item><title>提高WordPress安全性的十个要点(下)</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/07/0372/</link><pubDate>Sat, 03 Jul 2010 20:39:10 +0800</pubDate><guid>http://www.littlear.com/post/2010/07/0372/</guid><description><![CDATA[<p>&nbsp;&nbsp; &nbsp; &nbsp;安全是永恒的话题，在互联网上更是如此，本文将为大家介绍10个小诀窍来提高WordPress博客的安全性。<a href="http://www.littlear.com/post/2010/07/0270/" target="_blank">昨天介绍了前5个</a>，今天继续后5个。</p><p><span style="font-size: large; ">6.防止图片盗链。</span></p><hr /><p>大多数虚拟主机和VPS都是限制流量的，而图片往往会消耗绝大部分流量。我们在希望自己文章被更多人访问和传播的同时又不得不去面对图片链接带来的巨大流量。所以防止图片外链是绝对必要的。</p><p>解决：修改<em>&nbsp;.htaccess </em>文件添加以下代码，之前一定记得备份。</p><blockquote><p>RewriteEngine On<br />#Replace ?mysite\.com/ with your blog url<br />RewriteCond %{HTTP_REFERER} !^http://(.+\.)?mysite\.com/ [NC]<br />RewriteCond %{HTTP_REFERER} !^$<br />#Replace /images/nohotlink.jpg with your &quot;don't hotlink&quot; image url<br />RewriteRule .*\.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]<br />&nbsp;</p></blockquote><p>修改完成之后只有你的网站可以引用图片，而其他外部引用都会被替换为<em>nohotlink.jpg </em>文件。你可以在<em>nohotlink.jpg </em>里展示版权信息。当然你也可以指定替换为一个不存在的文件。</p><p>&nbsp;</p><p><span style="font-size: large; ">7.创建一个插件来阻止恶意请求。</span></p><hr /><p>黑客往往使用恶意查询来修着博客的薄弱点用来攻击，虽然WordPress自身有比较完善的防护机制，但也不是没有提高的余地。</p><p>解决：创建一个文本文件粘贴以下代码，并保存为&nbsp;<em>blockbadqueries.php </em>。上传到你博客的<em>wp-content/plugins</em>文件夹下，进入后台开启这个插件。</p><blockquote><p>&lt;?php<br />/*<br />Plugin Name: Block Bad Queries<br />Plugin URI: http://perishablepress.com/press/2009/12/22/protect-wordpress-against-malicious-url-requests/<br />Description: Protect WordPress Against Malicious URL Requests<br />Author URI: http://perishablepress.com/<br />Author: Perishable Press<br />Version: 1.0<br />*/</p><p>global $user_ID;</p><p>if($user_ID) {<br />if(!current_user_can('level_10')) {<br />if (strlen($_SERVER['REQUEST_URI']) &gt; 255 ||<br />strpos($_SERVER['REQUEST_URI'], &quot;eval(&quot;) ||<br />strpos($_SERVER['REQUEST_URI'], &quot;CONCAT&quot;) ||<br />strpos($_SERVER['REQUEST_URI'], &quot;UNION+SELECT&quot;) ||<br />strpos($_SERVER['REQUEST_URI'], &quot;base64&quot;)) {<br />@header(&quot;HTTP/1.1 414 Request-URI Too Long&quot;);<br />@header(&quot;Status: 414 Request-URI Too Long&quot;);<br />@header(&quot;Connection: Close&quot;);<br />@exit;<br />}<br />}<br />}<br />?&gt;</p></blockquote><p>修改后如果有过长请求（超过255个字符）或者<span class="Apple-style-span" style="font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; line-height: 20px; color: rgb(30, 30, 30); ">URI</span>中存在<span class="Apple-style-span" style="font-family: Verdana, Arial, Geneva, Helvetica, sans-serif; line-height: 20px; color: rgb(30, 30, 30); ">PHP函数就会返回一个414错误。</span></p><p>&nbsp;</p><p><span style="font-size: large; ">8.删除你的WordPress版本号，切记！</span></p><hr /><p>WordPress会在头文件里显示版本号。告诉攻击者你版本号往往意味着他们可以少走很多弯路，为了不让他们长驱直入为什么不隐藏版本号呢？</p><p>解决：粘贴如下代码至&nbsp;<em>functions.php </em>文件，保存并刷新你的博客。</p><blockquote><p>remove_action('wp_head', 'wp_generator');</p></blockquote><p>现在看，是不是没有版本号了。</p><p>&nbsp;</p><p><span style="font-size: large; ">9.修改默认管理员名。</span></p><hr /><p>蛮力攻击是破解一个密码最简单的办法之一。 该方法很简单：尽可能多的尝试不同的密码。如果他们知道的用户名，他们只需要破解密码。 这就是为什么你应该改变默认的&ldquo;管理员&rdquo;用户名&mdash;&mdash;&ldquo;admin&rdquo;的原因。请注意，WordPress的3.0版本会让您选择您想要的默认用户名。 但是这个方法依然适合3.0以前的版本。</p><p>解决：打开数据库执行如下SQL语句，&ldquo;Your New Username&rdquo;为你想修改的用户名。</p><blockquote><p>UPDATE wp_users SET user_login = 'Your New Username' WHERE user_login = 'Admin';</p></blockquote><p>修改后使用新的管理员名户名登陆。</p><p>&nbsp;</p><p><span style="font-size: large; ">10.防止目录浏览。</span></p><hr /><p>默认情况下，大多数主机允许目录列表。 因此，如果在浏览器的地址栏键入www.yourblog.com/wp-includes，就会看到在该目录下的所有文件。 这无疑是一个安全风险，因为黑客可以看到上一次进行了修改的文件并访问它们。</p><p>解决：修改<em>&nbsp;.htaccess&nbsp;</em>文件添加以下代码，之前一定记得备份。</p><blockquote><p>Options -Indexes</p></blockquote><p>注意修改后并不会影响用户正常的访问这些文件。</p><p><span class="Apple-style-span" style="font-family: Arial, sans-serif, 宋体, 黑体; line-height: 20px; font-size: 13px; "><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; ">via:<a target="_blank" href="http://www.smashingmagazine.com/2010/07/01/10-useful-wordpress-security-tweaks/" style="text-decoration: none; color: rgb(9, 92, 131); ">smashing</a></p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; ">&nbsp;</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; text-align: center; ">（本文原创翻译，转载请注明：出自小耳朵博客<a href="http://www.littlear.com/" style="text-decoration: none; color: rgb(9, 92, 131); ">www.littlear.com</a>）</p><p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown" style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; text-align: left; ">&nbsp;<font color="#ff9900">免费天气预报短信？？</font><u><a target="_blank" href="http://www.littlear.com/post/2010/05/2239/" style="text-decoration: none; color: rgb(9, 92, 131); ">去看看</a></u></p></span></p>]]></description><category>建站经验</category><comments>http://www.littlear.com/post/2010/07/0372/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=72</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=72&amp;key=315661ce</trackback:ping></item><item><title>提高WordPress安全性的十个要点(上)</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/07/0270/</link><pubDate>Fri, 02 Jul 2010 17:33:15 +0800</pubDate><guid>http://www.littlear.com/post/2010/07/0270/</guid><description><![CDATA[<p>&nbsp;&nbsp; &nbsp; &nbsp;安全是永恒的话题，在互联网上更是如此，本文将为大家介绍10个小诀窍来提高WordPress博客的安全性。</p><p><span style="font-size: large; ">1.删除错误提示。</span></p><hr /><p>当我们登录WordPress后台失败时会显示错误信息。如果有人想攻击你的博客那么他们会从错误提示里得到很多有用的信息，我们需要做的就是不显示任何信息。</p><p>解决：打开<em> functions.php &nbsp;文件</em>并添加如下代码：</p><blockquote><p>add_filter('login_errors',create_function('$a', &quot;return null;&quot;));</p></blockquote><p>这段代码可以让返回的错误信息为空。</p><p>&nbsp;</p><p><span style="font-size: large; ">2.使用SSL。</span></p><hr /><p>如果你担心数据泄露或被截获，那就使用SSL连接方式吧。但是之前请确保博客主机支持SSL，如果不支持请直接跳过本条。</p><p>解决：打开&nbsp;<em>wp-config.php </em>文件（一般位于根目录）添加以下代码：</p><blockquote><p>define('FORCE_SSL_ADMIN', true);</p></blockquote><p>我们定义了FORCE_SSL_ADMIN常数，其值设置为true。这样就在WordPress里开启了SSL。</p><p>&nbsp;</p><p><span style="font-size: large; ">3.用.htaccess 保护配置文件。</span></p><hr /><p>&nbsp;WordPress用户都知道<em>wp-config.php</em>文件的重要性，它保存了所有的配置信息：用户名、密码等等。所以控制对&nbsp;<em>wp-config.php&nbsp;</em>的访问权限就变得尤为必要。</p><p>解决：在修改<em>.htaccess</em>文件前请先备份，然后打开并粘贴下面代码：</p><blockquote><p>&lt;files wp-config.php&gt;<br />order allow,deny<br />deny from all<br />&lt;/files&gt;</p></blockquote><p style="margin-bottom: 1.15em; ">&nbsp;修改后会拒绝任何对&nbsp;<em>wp-config.php&nbsp;</em>文件的访问。</p><p style="margin-bottom: 1.15em; ">&nbsp;</p><p id="" style="margin-bottom: 1.15em; "><span style="font-size: large; ">4.建立访问黑名单。</span></p><hr /><p>&nbsp;是不是常被一些垃圾评论制造者所烦恼？如果是，需要做的就是屏蔽他们的IP，让他们再也无法访问你的博客。</p><p>解决：修改<em>.htaccess</em>文件添加以下代码，事前别忘备份。</p><blockquote><p>&lt;Limit GET POST PUT&gt;<br />order allow,deny<br />allow from all<br />deny from 123.456.789<br />deny from 93.121.788<br />deny from 223.956.789<br />deny from 128.456.780<br />&lt;/LIMIT&gt;</p></blockquote><p>&nbsp;修改后上面这些IP就会被限制访问。</p><p>&nbsp;</p><p><span style="font-size: large; ">5.防止脚本注入。</span></p><hr /><p>脚本注入往往用来窃取用户信息，如果攻击者一旦得逞大多数情况下造成的损失很难挽回。</p><p>解决：依旧是<em>.htaccess&nbsp;</em>文件添加以下代码，事先备份。</p><blockquote><p>Options +FollowSymLinks<br />RewriteEngine On<br />RewriteCond %{QUERY_STRING} (\&lt;|%3C).*script.*(\&gt;|%3E) [NC,OR]<br />RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]<br />RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})<br />RewriteRule ^(.*)$ index.php [F,L]</p></blockquote><p>修改后所有的请求都会被检查是否包换脚本段，如果包含就会拒绝请求返回403错误。</p><p>后5点请看参阅<a target="_blank" href="http://www.littlear.com/post/2010/07/0372/">下篇文章</a>。</p><p>via:<a target="_blank" href="http://www.smashingmagazine.com/2010/07/01/10-useful-wordpress-security-tweaks/">smashing</a></p><p>&nbsp;</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; text-align: center; ">（本文原创翻译，转载请注明：出自小耳朵博客<a style="text-decoration: none; color: rgb(9, 92, 131); " href="http://www.littlear.com/">www.littlear.com</a>）</p><p id="aeaoofnhgocdbnbeljkmbjdmhbcokfdb-mousedown" style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; text-align: left; ">&nbsp;<font color="#ff9900">免费天气预报短信？？</font><u><a target="_blank" style="text-decoration: none; color: rgb(9, 92, 131); " href="http://www.littlear.com/post/2010/05/2239/">去看看</a></u></p>]]></description><category>建站经验</category><comments>http://www.littlear.com/post/2010/07/0270/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=70</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=70&amp;key=b4c523ec</trackback:ping></item><item><title>Chrome快捷访问网址</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/07/0169/</link><pubDate>Thu, 01 Jul 2010 20:22:29 +0800</pubDate><guid>http://www.littlear.com/post/2010/07/0169/</guid><description><![CDATA[<p>&nbsp;&nbsp; &nbsp;大家知道Chrome浏览器的网址栏可以当搜索框来用，其实Chrome还有一个功能可以用来快速打开想浏览的网址，只需要定义一个对应的关键字，设置方法如下：</p><p>1.菜单&mdash;&mdash;选项&mdash;&mdash;&ldquo;默认搜索引擎&rdquo;后面的管理。</p><p style="text-align: center; "><img title="" style="oldpaddingTop: ; oldborderTopWidth: ; oldpaddingBottom: ; oldborderBottomWidth: ; oldpaddingRight: ; oldborderRightWidth: ; oldpaddingLeft: ; oldborderLeftWidth: " alt="" src="http://www.littlear.com/upload/2010/7/201007012033505535.jpg" /></p><p style="text-align: left; ">2.输入一个名称，关键字，关键字对应的网址。下图以本博客为例：</p><p style="text-align: center; "><img title="" style="oldpaddingTop: ; oldborderTopWidth: ; oldpaddingBottom: ; oldborderBottomWidth: ; oldpaddingRight: ; oldborderRightWidth: ; oldpaddingLeft: ; oldborderLeftWidth: " alt="" src="http://www.littlear.com/upload/2010/7/201007012039005872.jpg" /></p><p style="text-align: left; ">3.确定保存，然后再浏览器地址栏输入123回车就可以直接访问www.littlear.com了。</p><p style="text-align: center; "><img title="" style="oldpaddingTop: ; oldborderTopWidth: ; oldpaddingBottom: ; oldborderBottomWidth: ; oldpaddingRight: ; oldborderRightWidth: ; oldpaddingLeft: ; oldborderLeftWidth: " alt="" src="http://www.littlear.com/upload/2010/7/201007012046558373.jpg" /></p><p style="text-align: left; ">大家可以将自己常用的网址也设置一个比较简短好输入的关键字。这样打开它们就很方便了。</p><p style="text-align: left; ">&nbsp;</p><p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 10px 0px 15px; WORD-BREAK: break-all; PADDING-TOP: 0px; TEXT-ALIGN: center">（本文系原创，转载请注明出处：出自小耳朵博客<a style="COLOR: rgb(9,92,131); TEXT-DECORATION: none" href="http://www.littlear.com/">www.littlear.com</a>）</p><p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 10px 0px 15px; WORD-BREAK: break-all; PADDING-TOP: 0px; TEXT-ALIGN: left">&nbsp;<font color="#ff9900">免费天气预报短信？？</font><u><a style="COLOR: rgb(9,92,131); TEXT-DECORATION: none" target="_blank" href="http://www.littlear.com/post/2010/05/2239/">去看看</a></u></p><p>&nbsp;</p><p style="text-align: left; ">&nbsp;</p>]]></description><category>软件技巧</category><comments>http://www.littlear.com/post/2010/07/0169/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=69</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=69&amp;key=5b94b870</trackback:ping></item><item><title>怎样成为一名优秀的blogger</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/06/2462/</link><pubDate>Thu, 24 Jun 2010 10:07:43 +0800</pubDate><guid>http://www.littlear.com/post/2010/06/2462/</guid><description><![CDATA[<p>&nbsp;&nbsp; &nbsp;<span class="Apple-style-span" style="font-family: Verdana, Tahoma, sans-serif; line-height: 24px; ">相信有很多的博主和我一样都想成为一名优秀的博主，今天我从一个国外博客看到一篇文章专门讲述了这个问题，现在把它的一部分翻译过来与大家分享。作为一个非常出色的博主，应该要做到以下五个方面：</span></p><p><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">1、体现每一篇博文的最大价值</strong><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;作为一名优秀的blogger,你不能仅仅在有时候提供有价值的博文，而是使你写的没一点文字都具有其应有的价值，不管你是为了写作而发表博文，还是为了提高博客的更新频率而去写博文，你必须保证你的每一个字都有价值，而不能是单纯的文字堆砌。当我在写我的博客时，不论是我自己的文章还是读者的投稿，我都会尽全力去展现一篇文章的最好价值。<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />我是一个追求个性的人，渴望与众不同。你是否曾经想过你为什么要去写博客，除了用来赚钱或是有一个业余工作，你还会有什么原因呢？我写博客的目的是因为它是我的一种追求，我可以通过博客与广大的网友交流，可以帮助朋友们解决一些特定的问题。我的每一篇博文都会是以个接触他人生活的机会，如果通过X各文字可以传达一种信息，那么我就写X个文字，日过需要花费X个小时，那么我就会花费X个小时，在文字的质量上没有打折扣的余地。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;当然，不是所有的博主都把写博客当做自己的使命，而且你也鄙视必须那么去做，在这一点上没有对与错，你只需要搞清楚你为什么去写博客，然后按照自己的目的去写好自己的每一篇博文就够了。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;对于一篇博文是否有价值没有严格的定义。它可以长，可以短，可以是列表，摘要或是故事的形式，博文中可以穿插文本、图片、视频文件或是他们的组合，它可以具有娱乐价值、教育目的或是它们的组合。如果你的一片博文能促进别人的生活，那么它就具有价值了。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />这里有几个问题你需要搞清楚：<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />(1)你的博客阅读群体主要是那些人？<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />(2)为什么它们需要从你的博客中获得帮助？<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />(3)你的博客通过什么去留住读者？<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />(4)你怎样写博文才能更好的帮助读者？<br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />(5)我通过什么方式可以使读者在不同的条件下都可以指知道你的博客？</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">2、要比别人更勤奋</strong><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;你开车吗？如果你开车那就好极了。如果你不开车，那么在5分钟之正在内设想你自己在开车，假如你正在一条普通而宽敞的大道上行驶。你连续踩住油门几秒钟，然后你的车就会达到一个你需要的速度。然而当你停止加速时，你的车就会慢慢的停下来。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;使你的博客成为一个顶级的博客就像开车一样。你不能成天只想着自己的读者会增加而不去做任何努力。你需要做的是勤奋的写作，当然是写高质量的博文，去赢得读者对你的信赖。我始终相信自己的努力和结果是成正比的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">3、言行要保持一致</strong><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;爱因斯坦曾经说过：&ldquo;例子不是另外一种的教育方法，它是唯一的教育方法&rdquo;。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;当你成为一名优秀出色的的博主时，你就可能成为了他人的榜样。作为一个博主，你直接或间接的会成为读者的楷模，你所做的或所说的会影响其他的人，也许比你想象中的还要深刻，你的读者追寻你的建议或指导。所以，如果你的言行一致至关重要。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;是一个博客变成个人优秀博客不仅仅是只通过写文章来达到这个水平。你需要做的是与广大的读者进行沟通，去了解他们的生活，指导他们会遇到什么样的问题，然后寻求出解决的办法，帮助别人做的更好，排除别人生活中遇到的种种困难。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">4、博文中不要说&ldquo;请&rdquo;字</strong><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;你的博客是向读者传递信息，而不是要求别人怎么去做。你要知道，不管你写的什么内容，总会有人与你又不同的观点。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;普通的博主一般都会要求读者们去干什么。他们对读者所想知道以及所能接受的东西进行了过度的分析。但是作为一名优秀的博主，你不能那样做。你也许不会避讳的去发表带有争议性的话题，你所写的只是你所认为的，即使有很多的人不同意你的看法。当然，当你发现自己错了的时候，你也没有必要感到害怕。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " /><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">5、揭示事情的真相</strong><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;我见过两种类型的博主：一种是我认为是天才的博主，他们总是写出事情的真正原貌，写的踏踏实实，这些博主比如说有Darren Rowse 和 Leo Babauta等人，我对他们很是欣赏和钦佩。另外一种是喜欢吹嘘的博主，他们总是喜欢夸大事情的真相，歪曲事实，我不知道你对这类人的看法，反正我是对他们敬而远之的。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; " />&nbsp;&nbsp; &nbsp;读者是很睿智的，你在最初也许可以骗取他们的认可，但是时间长了，他们就会发现你所说的有许多都不符合事实，那么他们毫无疑问会对你失去信心。作为一个出色的博主，你不能浮夸，你不能撒谎，你不能过度的宣扬或是过度的承诺。我把这当做是对读者的一种尊敬。你描述事实的本身，你就是很诚实和可信赖的，你的读者就会长期的信任你。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; text-align: center; ">本文转自<a target="_blank" href="http://www.chenlublog.com/">晨露博客</a>，原文地址：<a target="_blank" href="http://www.chenlublog.com/post/how-to-be-an-excellent-blogger.html">点击</a></p>]]></description><category>建站经验</category><comments>http://www.littlear.com/post/2010/06/2462/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=62</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=62&amp;key=b78c9809</trackback:ping></item><item><title>一款优秀的离线RSS阅读器—GreatNews</title><author>fzcs@live.com (fzcs)</author><link>http://www.littlear.com/post/2010/06/2261/</link><pubDate>Tue, 22 Jun 2010 22:46:09 +0800</pubDate><guid>http://www.littlear.com/post/2010/06/2261/</guid><description><![CDATA[<p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 最近<a target="_blank" href="http://www.littlear.com/catalog.asp?tags=Google">Google </a>Reader 打开很慢，而且经常连接失败，无法更新，经过在网上大把的搜索发现了一个很不错的桌面RSS阅读器，用起来还不错，所以推荐给大家。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; 离线RSS是通过客户端直接向新闻网站或其托管RSS服务商请求数据，所以很大程度上避免了在线RSS更新不同步的缺点，并且省去了我们去Google Reader之类在线阅读网站的过程，因而相比在线RSS来的更稳定，就像我就经常打不开Google Reader的条目（可能是我的网速比较烂吧），用离线RSS阅读器就不用这么闹心了。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;不过离线RSS的新闻只能存贮与一台电脑，无法在多台电脑上同步要阅读的信息，当然了你可以用本博推荐过的网络存储软件<a target="_blank" href="http://www.littlear.com/post/2010/06/2059/">SugarSync</a>来实现同步，只需要把离线RSS阅读器的安装目录同步。</p><p>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;<a target="_blank" href="http://www.curiostudio.com/cn_index.html">GreatNews</a>是一款小巧免费的离线RSS阅读器，支持中文。下载地址<a target="_blank" href="http://www.curiostudio.com/dist/GreatNewsSetup.exe">点击</a>。我比较喜欢三栏的界面</p><p>&nbsp;</p><p style="text-align: center; "><img onload="ResizeImage(this,650)" src="http://www.littlear.com/upload/2010/6/201006222328010186.jpg" alt="" title="" /></p><p style="text-align: left; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;第一次GreatNews可以导入从Google Reader导出的OPML文件，完成之后就可以将Google Reader中已经订阅的Feed直接导入GreatNews，避免了重复去添加。过程如下：</p><p style="text-align: left; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;1.Google Reader&mdash;&mdash;阅读器设置&mdash;&mdash;导入/导出&mdash;&mdash;将订阅导出为 OPML 文件 &nbsp;得到 google-reader-subscriptions.xml 文件。</p><p style="text-align: left; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;2.GreatNews&mdash;&mdash;工具&mdash;&mdash;从OPML/XML文件导入频道&mdash;&mdash;选择之前得到的XML文件。</p><p style="text-align: left; ">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;这些步骤完成后既可以将Google Reader中的订阅条目完美复制到GreatNews之中了。GreatNews相比在线RSS还有很多优势：内建浏览器，自动拦截弹出窗口、可订制关键字自动加亮 、可给新闻加标签&nbsp;（GMail的Label）等。如果您的网速不适合在线RSS， GreatNews还是很值得一试的。</p><p style="text-align: left; ">&nbsp;</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; text-align: center; ">（本文系原创，转载请注明出处：出自小耳朵博客<a href="http://www.littlear.com/" style="text-decoration: none; color: rgb(9, 92, 131); ">www.littlear.com</a>）</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; word-break: break-all; text-align: left; ">&nbsp;<font color="#ff9900">免费天气预报短信？？</font><u><a target="_blank" href="http://www.littlear.com/post/2010/05/2239/" style="text-decoration: none; color: rgb(9, 92, 131); ">去看看</a></u></p>]]></description><category>软件技巧</category><comments>http://www.littlear.com/post/2010/06/2261/#comment</comments><wfw:comment>http://www.littlear.com/</wfw:comment><wfw:commentRss>http://www.littlear.com/feed.asp?cmt=61</wfw:commentRss><trackback:ping>http://www.littlear.com/cmd.asp?act=tb&amp;id=61&amp;key=da981f6d</trackback:ping></item></channel></rss>

