﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><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>BlogJava-　　　　　　　　　　　　　彬 ^_^ -随笔分类-CA</title><link>http://www.blogjava.net/libin2722/category/29421.html</link><description>快乐学习，快乐工作</description><language>zh-cn</language><lastBuildDate>Wed, 13 Feb 2008 17:53:12 GMT</lastBuildDate><pubDate>Wed, 13 Feb 2008 17:53:12 GMT</pubDate><ttl>60</ttl><item><title>对google个性主页的拖拽效果的js的完整注释－1</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:51:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179851.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179851.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179851.html</trackback:ping><description><![CDATA[<span style="color: #008000;">//</span> <span style="color: #008000;">工具类，使用Util的命名空间，方便管理</span> <span style="color: #008000;"><br />
</span><span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;Util&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #0000ff;">new</span> <span style="color: #000000;">&nbsp;Object();<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">获取http&nbsp;header里面的UserAgent，浏览器信息</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.getUserAgent&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;navigator.userAgent;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">是否是Gecko核心的Browser，比如Mozila、Firefox</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.isGecko&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getUserAgent.indexOf(</span> <span style="color: #000000;">"</span> <span style="color: #000000;">Gecko</span> <span style="color: #000000;">"</span> <span style="color: #000000;">)&nbsp;</span> <span style="color: #000000;">!=</span> &nbsp; <span style="color: #000000;">-</span> <span style="color: #000000;">1</span> <span style="color: #000000;">;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">是否是Opera</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.isOpera&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getUserAgent.indexOf(</span> <span style="color: #000000;">"</span> <span style="color: #000000;">Opera</span> <span style="color: #000000;">"</span> <span style="color: #000000;">)&nbsp;</span> <span style="color: #000000;">!=</span> &nbsp; <span style="color: #000000;">-</span> <span style="color: #000000;">1</span> <span style="color: #000000;">;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">获取一个element的offset信息，其实就是相对于Body的padding以内的绝对坐标</span> <span style="color: #008000;"><br />
//</span> <span style="color: #008000;">后面一个参数如果是true则获取offsetLeft，false则是offsetTop</span> <span style="color: #008000;"><br />
//</span> <span style="color: #008000;">关于offset、style、client等坐标的定义参考dindin的这个帖子：http://www.jroller.com/page/dindin/?anchor=pro_java_12</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.getOffset&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;(el,&nbsp;isLeft)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;ret&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">0</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">while</span> <span style="color: #000000;">&nbsp;(el&nbsp;</span> <span style="color: #000000;">!=</span> &nbsp; <span style="color: #0000ff;">null</span> <span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span> <span style="color: #000000;">+=</span> <span style="color: #000000;">&nbsp;el[</span> <span style="color: #000000;">"</span> <span style="color: #000000;">offset</span> <span style="color: #000000;">"</span> &nbsp; <span style="color: #000000;">+</span> <span style="color: #000000;">&nbsp;(isLeft&nbsp;</span> <span style="color: #000000;">?</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">Left</span> <span style="color: #000000;">"</span> <span style="color: #000000;">&nbsp;:&nbsp;</span> <span style="color: #000000;">"</span> <span style="color: #000000;">Top</span> <span style="color: #000000;">"</span> <span style="color: #000000;">)];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;el&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;el.offsetParent;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> <span style="color: #000000;">&nbsp;ret;<br />
};<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">将一个（参数中的funcName是这个fuction的名字）绑定到一个element上，并且以这个element的上下文运行，其实是一种继承，这个可以google些文章看看</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.bind&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;(el,&nbsp;fucName)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> <span style="color: #000000;">&nbsp;el[fucName].apply(el,&nbsp;arguments);<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
};<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">重新计算所有的可以拖拽的element的坐标，对同一个column下面的可拖拽图层重新计算它们的高度而得出新的坐标，防止遮叠</span> <span style="color: #008000;"><br />
//</span> <span style="color: #008000;">计算出来的坐标记录在pagePosLeft和pagePosTop两个属性里面</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.re_calcOff&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;(el)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">for</span> <span style="color: #000000;">&nbsp;(</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;i&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">0</span> <span style="color: #000000;">;&nbsp;i&nbsp;</span> <span style="color: #000000;">&lt;</span> <span style="color: #000000;">&nbsp;Util.dragArray.length;&nbsp;i</span> <span style="color: #000000;">++</span> <span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;ele&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.dragArray[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ele.elm.pagePosLeft&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getOffset(ele.elm,&nbsp;</span> <span style="color: #0000ff;">true</span> <span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ele.elm.pagePosTop&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getOffset(ele.elm,&nbsp;</span> <span style="color: #0000ff;">false</span> <span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;nextSib&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;el.elm.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">while</span> <span style="color: #000000;">&nbsp;(nextSib)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nextSib.pagePosTop&nbsp;</span> <span style="color: #000000;">-=</span> <span style="color: #000000;">&nbsp;el.elm.offsetHeight;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nextSib&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;nextSib.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
};<br />
<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">隐藏Google&nbsp;Ig中间那个table，也就是拖拽的容器，配合show一般就是刷新用，解决一些浏览器的怪癖</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.hide&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Util.rootElement.style.display&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">none</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
};<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">显示Google&nbsp;Ig中间那个table，解释同上</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.show&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Util.rootElement.style.display&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">""</span> <span style="color: #000000;">;<br />
};<br />
<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">移动时显示的占位虚线框</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">ghostElement&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #0000ff;">null</span> <span style="color: #000000;">;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">获取这个虚线框，通过dom动态生成</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">getGhostElement&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">if</span> <span style="color: #000000;">&nbsp;(</span> <span style="color: #000000;">!</span> <span style="color: #000000;">ghostElement)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;createElement(</span> <span style="color: #000000;">"</span> <span style="color: #000000;">DIV</span> <span style="color: #000000;">"</span> <span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.className&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">modbox</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.backgroundColor&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">""</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.style.border&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">2px&nbsp;dashed&nbsp;#aaa</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.innerHTML&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">&amp;nbsp;</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> <span style="color: #000000;">&nbsp;ghostElement;<br />
};<br />
</span>
<p>// 初始化可以拖拽的Element的函数，与拖拽无关的我去掉了 <br />
&nbsp; draggable(el) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的开始拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragStart&nbsp; =&nbsp; start_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的正在拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._drag&nbsp; =&nbsp; when_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的拖拽结束的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragEnd&nbsp; =&nbsp; end_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这个函数主要用来进行拖拽结束后的dom处理 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._afterDrag&nbsp; =&nbsp; after_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 是否正在被拖动，一开始当然没有被拖动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将这个Element的this指针注册在elm这个变量里面，方便在自己的上下文以外调用自己的函数等，很常用的方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm&nbsp; =&nbsp; el;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 触发拖拽的Element，在这里就是这个div上显示标题的那个div <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .header&nbsp; =&nbsp; getElementById(el.id&nbsp; +&nbsp;&nbsp; " _h " );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 对于有i的element拖拽不同，这里检测一下并记录 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .hasI&nbsp; =&nbsp;&nbsp; this .elm.getElementsByTagName( " I " ).length&nbsp; &gt;&nbsp;&nbsp; 0 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果找到了header就绑定drag相关的event <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( this .header) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽时的叉子鼠标指针 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .header.style.cursor&nbsp; =&nbsp;&nbsp; " move " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将函数绑定到header和element的this上，参照那个函数的说明 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Drag.init( this .header,&nbsp; this .elm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 下面三个语句将写好的三个函数绑定给这个elemnt的三个函数钩子上，也就实现了element从draggable继承可拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragStart&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragStart " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDrag&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _drag " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragEnd&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragEnd " );<br />
&nbsp;&nbsp;&nbsp; }<br />
};</p>
// 下面就是draggable里面用到的那4个 <br />
// 公用的开始拖拽的函数 <br />
&nbsp; start_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 重置坐标，实现拖拽以后自己的位置马上会被填充的效果 <br />
&nbsp;&nbsp;&nbsp; Util.re_calcOff( this );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 记录原先的邻居节点，用来对比是否被移动到新的位置 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .origNextSibling&nbsp; =&nbsp;&nbsp; this .elm.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取移动的时候那个灰色的虚线框 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _ghostElement&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的高度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offH&nbsp; =&nbsp;&nbsp; this .elm.offsetHeight;<br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isGecko) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 修正gecko引擎的怪癖吧 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offH&nbsp; -=&nbsp; parseInt(_ghostElement.style.borderTopWidth)&nbsp; *&nbsp;&nbsp; 2 ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的宽度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offW&nbsp; =&nbsp;&nbsp; this .elm.offsetWidth;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取left和top的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offLeft&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; true );<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offTop&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; false );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 防止闪烁，现隐藏 <br />
&nbsp;&nbsp;&nbsp; Util.hide();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将自己的宽度记录在style属性里面 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.width&nbsp; =&nbsp; offW&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将那个灰框设定得与正在拖动的对象一样高，比较形象 <br />
&nbsp;&nbsp;&nbsp; _ghostElement.style.height&nbsp; =&nbsp; offH&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 把灰框放到这个对象原先的位置上 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.parentNode.insertBefore(_ghostElement,&nbsp; this .elm.nextSibling);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于要拖动必须将被拖动的对象从原先的盒子模型里面抽出来，所以设定position为absolute，这个可以参考一下css布局方面的知识 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.position&nbsp; =&nbsp;&nbsp; " absolute " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 设置zIndex，让它处在最前面一层，当然其实zIndex=100是让它很靠前，如果页面里有zIndex&gt;100的，那&#8230;&#8230; <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.zIndex&nbsp; =&nbsp;&nbsp; 100 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于position=absolute了，所以left和top实现绝对坐标定位，这就是先前计算坐标的作用，不让这个模型乱跑，要从开始拖动的地方开始移动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.left&nbsp; =&nbsp; offLeft&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.top&nbsp; =&nbsp; offTop&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 坐标设定完毕，可以显示了，这样就不会闪烁了 <br />
&nbsp;&nbsp;&nbsp; Util.show();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这里本来有个ig_d.G，没搞明白干什么用的，不过没有也可以用，谁知道麻烦告诉我一声，不好意思 <br />
&nbsp;&nbsp;&nbsp;&nbsp; // 还没有开始拖拽，这里做个记号 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
};<br />
<br />
<div><span style="color: #008000;">// 初始化可以拖拽的Element的函数，与拖拽无关的我去掉了 <br />
&nbsp; draggable(el) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的开始拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragStart&nbsp; =&nbsp; start_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的正在拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._drag&nbsp; =&nbsp; when_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的拖拽结束的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragEnd&nbsp; =&nbsp; end_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这个函数主要用来进行拖拽结束后的dom处理 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._afterDrag&nbsp; =&nbsp; after_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 是否正在被拖动，一开始当然没有被拖动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将这个Element的this指针注册在elm这个变量里面，方便在自己的上下文以外调用自己的函数等，很常用的方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm&nbsp; =&nbsp; el;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 触发拖拽的Element，在这里就是这个div上显示标题的那个div <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .header&nbsp; =&nbsp; getElementById(el.id&nbsp; +&nbsp;&nbsp; " _h " );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 对于有i的element拖拽不同，这里检测一下并记录 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .hasI&nbsp; =&nbsp;&nbsp; this .elm.getElementsByTagName( " I " ).length&nbsp; &gt;&nbsp;&nbsp; 0 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果找到了header就绑定drag相关的event <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( this .header) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽时的叉子鼠标指针 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .header.style.cursor&nbsp; =&nbsp;&nbsp; " move " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将函数绑定到header和element的this上，参照那个函数的说明 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Drag.init( this .header,&nbsp; this .elm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 下面三个语句将写好的三个函数绑定给这个elemnt的三个函数钩子上，也就实现了element从draggable继承可拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragStart&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragStart " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDrag&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _drag " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragEnd&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragEnd " );<br />
&nbsp;&nbsp;&nbsp; }<br />
};</span></div>
<span style="color: #008000;">// 下面就是draggable里面用到的那4个 <br />
// 公用的开始拖拽的函数 <br />
&nbsp; start_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 重置坐标，实现拖拽以后自己的位置马上会被填充的效果 <br />
&nbsp;&nbsp;&nbsp; Util.re_calcOff( this );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 记录原先的邻居节点，用来对比是否被移动到新的位置 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .origNextSibling&nbsp; =&nbsp;&nbsp; this .elm.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取移动的时候那个灰色的虚线框 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _ghostElement&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的高度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offH&nbsp; =&nbsp;&nbsp; this .elm.offsetHeight;<br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isGecko) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 修正gecko引擎的怪癖吧 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offH&nbsp; -=&nbsp; parseInt(_ghostElement.style.borderTopWidth)&nbsp; *&nbsp;&nbsp; 2 ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的宽度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offW&nbsp; =&nbsp;&nbsp; this .elm.offsetWidth;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取left和top的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offLeft&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; true );<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offTop&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; false );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 防止闪烁，现隐藏 <br />
&nbsp;&nbsp;&nbsp; Util.hide();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将自己的宽度记录在style属性里面 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.width&nbsp; =&nbsp; offW&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将那个灰框设定得与正在拖动的对象一样高，比较形象 <br />
&nbsp;&nbsp;&nbsp; _ghostElement.style.height&nbsp; =&nbsp; offH&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 把灰框放到这个对象原先的位置上 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.parentNode.insertBefore(_ghostElement,&nbsp; this .elm.nextSibling);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于要拖动必须将被拖动的对象从原先的盒子模型里面抽出来，所以设定position为absolute，这个可以参考一下css布局方面的知识 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.position&nbsp; =&nbsp;&nbsp; " absolute " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 设置zIndex，让它处在最前面一层，当然其实zIndex=100是让它很靠前，如果页面里有zIndex&gt;100的，那&#8230;&#8230; <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.zIndex&nbsp; =&nbsp;&nbsp; 100 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于position=absolute了，所以left和top实现绝对坐标定位，这就是先前计算坐标的作用，不让这个模型乱跑，要从开始拖动的地方开始移动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.left&nbsp; =&nbsp; offLeft&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.top&nbsp; =&nbsp; offTop&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 坐标设定完毕，可以显示了，这样就不会闪烁了 <br />
&nbsp;&nbsp;&nbsp; Util.show();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这里本来有个ig_d.G，没搞明白干什么用的，不过没有也可以用，谁知道麻烦告诉我一声，不好意思 <br />
&nbsp;&nbsp;&nbsp;&nbsp; // 还没有开始拖拽，这里做个记号 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
};<br />
</span><span style="color: #000000;">// 在拖拽时的相应函数，由于绑定到鼠标的move这个event上，所以会传入鼠标的坐标clientX, clientY <br />
&nbsp; when_Drag(clientX, clientY) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 刚开始拖拽的时候将图层变透明，并标记为正在被拖拽 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( ! this .isDragging) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.filter&nbsp; =&nbsp;&nbsp; " alpha(opacity=70) " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.opacity&nbsp; =&nbsp;&nbsp; 0.7 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; true ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 被拖拽到的新的column（当然也可以是原来那个） <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; found&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 最大的距离，可能是防止溢出或者什么bug <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; max_distance&nbsp; =&nbsp;&nbsp; 100000000 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 遍历所有的可拖拽的element，寻找离当前鼠标坐标最近的那个可拖拽元素，以便后面插入 <br />
&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp; ( var&nbsp; i&nbsp; =&nbsp;&nbsp; 0 ; i&nbsp; &lt;&nbsp; Util.dragArray.length; i ++ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele&nbsp; =&nbsp; Util.dragArray[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 利用勾股定理计算鼠标到遍历到的这个元素的距离 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
var&nbsp; distance&nbsp; =&nbsp; Math.sqrt(Math.pow(clientX&nbsp; -&nbsp; ele.elm.pagePosLeft,&nbsp;
2 )&nbsp; +&nbsp; Math.pow(clientY&nbsp; -&nbsp; ele.elm.pagePosTop,&nbsp; 2 ));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 自己已经浮动了，所以不计算自己的 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (ele&nbsp; ==&nbsp;&nbsp; this ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果计算失败继续循环 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (isNaN(distance)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果更小，记录下这个距离，并将它作为found <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (distance&nbsp; &lt;&nbsp; max_distance) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_distance&nbsp; =&nbsp; distance;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; found&nbsp; =&nbsp; ele;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 准备让灰框落脚 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _ghostElement&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果找到了另外的落脚点 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (found&nbsp; !=&nbsp;&nbsp; null&nbsp;&nbsp; &amp;&amp;&nbsp; _ghostElement.nextSibling&nbsp; !=&nbsp; found.elm) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 找到落脚点就先把灰框插进去，这就是我们看到的那个灰框停靠的特效，有点像吸附的感觉，哈哈 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; found.elm.parentNode.insertBefore(_ghostElement, found.elm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isOpera) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Opera的现实问题，要隐藏/显示后才能刷新出变化 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; " none " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
};<br />
// 拖拽完毕 <br />
&nbsp; end_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽完毕后执行后面的钩子，执行after_Drag()，如果布局发生了变动了就记录到远程服务器，保存你拖拽后新的布局顺序 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( this ._afterDrag()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // remote call to save the change <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; true ;<br />
};<br />
// 拖拽后的执行钩子 <br />
&nbsp; after_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; return&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 防止闪烁 <br />
&nbsp;&nbsp;&nbsp; Util.hide();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 把拖拽时的position=absolute和相关的那些style都消除 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.position&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.width&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.zIndex&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.filter&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.opacity&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取灰框 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果现在的邻居不是原来的邻居了 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (ele.nextSibling&nbsp; !=&nbsp;&nbsp; this .origNextSibling) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 把被拖拽的这个节点插到灰框的前面 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ele.parentNode.insertBefore( this .elm, ele.nextSibling);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 标明被拖拽了新的地方 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; =&nbsp;&nbsp; true ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 移除灰框，这是这个灰框的生命周期应该就结束了 <br />
&nbsp;&nbsp;&nbsp; ele.parentNode.removeChild(ele);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 修改完毕，显示 <br />
&nbsp;&nbsp;&nbsp; Util.show();<br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isOpera) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Opera的现实问题，要隐藏/显示后才能刷新出变化 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; " none " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; return;<br />
};<br />
</span><span style="color: #000000;"><br />
<br />
</span>
<p><span style="color: #008000;">// 可拖拽Element的原形，用来将event绑定到各个钩子，这部分市比较通用的，netvibes也是基本完全相同的实现 <br />
// 这部分推荐看dindin的这个，也会帮助理解，<a href="http://www.jroller.com/page/dindin/?anchor=pro_java_12">http://www.jroller.com/page/dindin/?anchor=pro_java_12</a> <br />
var&nbsp; Drag&nbsp; =&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 对这个element的引用，一次只能拖拽一个Element <br />
&nbsp;&nbsp;&nbsp; obj: null , <br />
&nbsp;&nbsp;&nbsp;&nbsp; // element是被拖拽的对象的引用，elementHeader就是鼠标可以拖拽的区域 <br />
&nbsp;&nbsp;&nbsp; init: &nbsp; (elementHeader, element) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将start绑定到down事件，按下鼠标触发start <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elementHeader.down&nbsp; =&nbsp; Drag.start;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将element存到header的obj里面，方便header拖拽的时候引用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elementHeader.obj&nbsp; =&nbsp; element;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 初始化绝对的坐标，因为不是position=absolute所以不会起什么作用，但是防止后面onDrag的时候parse出错了 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (isNaN(parseInt(element.style.left))) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.left&nbsp; =&nbsp;&nbsp; " 0px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (isNaN(parseInt(element.style.top))) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.top&nbsp; =&nbsp;&nbsp; " 0px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 挂上空，初始化这几个成员，在Drag.init被调用后才帮定到实际的函数，可以参照draggable里面的内容 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDragStart&nbsp; =&nbsp;&nbsp; new&nbsp; ();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDragEnd&nbsp; =&nbsp;&nbsp; new&nbsp; ();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDrag&nbsp; =&nbsp;&nbsp; new&nbsp; ();<br />
&nbsp;&nbsp;&nbsp; },<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 开始拖拽的绑定，绑定到鼠标的移动的event上 <br />
&nbsp;&nbsp;&nbsp; start: &nbsp; (event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; element&nbsp; =&nbsp; Drag.obj&nbsp; =&nbsp;&nbsp; this .obj;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event&nbsp; =&nbsp; Drag.fixE(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 看看是不是左键点击 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (event.which&nbsp; !=&nbsp;&nbsp; 1 ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 除了左键都不起作用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; true ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 参照这个函数的解释，挂上开始拖拽的钩子 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDragStart();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录鼠标坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseX&nbsp; =&nbsp; event.clientX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseY&nbsp; =&nbsp; event.clientY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将Global的event绑定到被拖动的element上面来 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; up&nbsp; =&nbsp; Drag.end;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; move&nbsp; =&nbsp; Drag.drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp; }, <br />
&nbsp;&nbsp;&nbsp;&nbsp; // Element正在被拖动的函数 <br />
&nbsp;&nbsp;&nbsp; drag: &nbsp; (event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event&nbsp; =&nbsp; Drag.fixE(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 看看是不是左键点击 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (event.which&nbsp; ==&nbsp;&nbsp; 0 ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 除了左键都不起作用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; Drag.end();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 正在被拖动的Element <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; element&nbsp; =&nbsp; Drag.obj;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 鼠标坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _clientX&nbsp; =&nbsp; event.clientY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _clientY&nbsp; =&nbsp; event.clientX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果鼠标没动就什么都不作 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (element.lastMouseX&nbsp; ==&nbsp; _clientY&nbsp; &amp;&amp;&nbsp; element.lastMouseY&nbsp; ==&nbsp; _clientX) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 刚才Element的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _lastX&nbsp; =&nbsp; parseInt(element.style.top);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _lastY&nbsp; =&nbsp; parseInt(element.style.left);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 新的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; newX, newY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 计算新的坐标：原先的坐标+鼠标移动的值差 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newX&nbsp; =&nbsp; _lastY&nbsp; +&nbsp; _clientY&nbsp; -&nbsp; element.lastMouseX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newY&nbsp; =&nbsp; _lastX&nbsp; +&nbsp; _clientX&nbsp; -&nbsp; element.lastMouseY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 修改element的显示坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.left&nbsp; =&nbsp; newX&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.top&nbsp; =&nbsp; newY&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录element现在的坐标供下一次移动使用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseX&nbsp; =&nbsp; _clientY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseY&nbsp; =&nbsp; _clientX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 参照这个函数的解释，挂接上Drag时的钩子 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDrag(newX, newY);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp; },<br />
&nbsp;&nbsp;&nbsp;&nbsp; // Element正在被释放的函数，停止拖拽 <br />
&nbsp;&nbsp;&nbsp; end: &nbsp; (event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event&nbsp; =&nbsp; Drag.fixE(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解除对Global的event的绑定 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; move&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; up&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 先记录下onDragEnd的钩子，好移除obj <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _onDragEndFuc&nbsp; =&nbsp; Drag.obj.onDragEnd();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽完毕，obj清空 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Drag.obj&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; _onDragEndFuc;<br />
&nbsp;&nbsp;&nbsp; }, <br />
&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp; fixE: &nbsp; (ig_) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_&nbsp; =&nbsp; event;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_.layerX&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_.layerX&nbsp; =&nbsp; ig_.offsetX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_.layerY&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_.layerY&nbsp; =&nbsp; ig_.offsetY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_.which&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_.which&nbsp; =&nbsp; ig_.button;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; ig_;<br />
&nbsp;&nbsp;&nbsp; }<br />
};</span></p>
<p><span style="color: #008000;">// 下面是初始化的函数了，看看上面这些东西怎么被调用 <br />
var&nbsp; _IG_initDrag&nbsp; =&nbsp;&nbsp; &nbsp; (el) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // column那个容器，在google里面就是那个table布局的tbody，netvibes用的&lt;div&gt; <br />
&nbsp;&nbsp;&nbsp; Util.rootElement&nbsp; =&nbsp; el;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这个tbody的行 <br />
&nbsp;&nbsp;&nbsp; Util._rows&nbsp; =&nbsp; Util.rootElement.tBodies[ 0 ].rows[ 0 ];<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 列，google是3列，其实也可以更多 <br />
&nbsp;&nbsp;&nbsp; Util.column&nbsp; =&nbsp; Util._rows.cells;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 用来存取可拖拽的对象 <br />
&nbsp;&nbsp;&nbsp; Util.dragArray&nbsp; =&nbsp;&nbsp; new&nbsp; Array();<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; counter&nbsp; =&nbsp;&nbsp; 0 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp; ( var&nbsp; i&nbsp; =&nbsp;&nbsp; 0 ; i&nbsp; &lt;&nbsp; Util.column.length; i ++ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 搜索所有的column <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele&nbsp; =&nbsp; Util.column[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp; ( var&nbsp; j&nbsp; =&nbsp;&nbsp; 0 ; j&nbsp; &lt;&nbsp; ele.childNodes.length; j ++ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 搜索每一column里面的所有element <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele1&nbsp; =&nbsp; ele.childNodes[j];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果是div就把它初始化为一个draggable对象 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (ele1.tagName&nbsp; ==&nbsp;&nbsp; " DIV " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Util.dragArray[counter]&nbsp; =&nbsp;&nbsp; new&nbsp; draggable(ele1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; counter ++ ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
};</span></p>
<p><span style="color: #008000;">// google的页面里可以拖动的部分的id是"t_1" <br />
// 挂载到，载入完毕执行。不过实际上google没有用。 <br />
// 而是写在页面最下面，异曲同工吧，也许直接写在页面是种怪癖，或者也有可能是兼容性考虑。 </span></p>
<p><span style="color: #008000;">// 请将下面两条被注释掉的代码加，到你自己下载的一个google ig页面里面，把里面的所有其余删除，挂上这个js也可以拖拽了，哈哈 <br />
// _table=getElementById("t_1"); <br />
//  = _IG_initDrag(_table); </span></p>
<span style="color: #008000;">// 其实看懂这些代码对学习java很有益，希望对大家能有帮助</span><br />
<img src ="http://www.blogjava.net/libin2722/aggbug/179851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:51 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google“爬虫”主动“送食”（转载）</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179850.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179850.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179850.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">如果希望自己的网站能够更快的被<span style="font-family: Times New Roman;">google</span>收录，抓取更多的内容（甚至抓取所有网页），可以使用<span style="font-family: Times New Roman;">google</span>提供的<span style="font-family: Times New Roman;">google&nbsp;Sitemap</span>服务（<span style="font-family: Times New Roman;">&nbsp;<a href="https://www.google.com/webmasters/tools/docs/zh_CN/sitemap-generator.html">https://www.google.com/webmasters/tools/docs/zh_CN/sitemap-generator.html</a></span>）</p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">使搜索引搜索蜘蛛的收录由被动变为主动，<span style="font-family: Times New Roman;">google&nbsp;Sitemap</span>服务目前尚不提供在线创建<span style="font-family: Times New Roman;">Sitemap</span>的功能，但是我们可以借助第三方网站提供的此类服务，打开网站（<a href="http://www.xml-sitemaps.com/"><span style="font-family: Times New Roman;">http://www.xml-sitemaps.com</span></a>）（如图<span style="font-family: Times New Roman;">1</span>）&nbsp;</p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">在&#8220;<span style="font-family: Times New Roman;">Starting&nbsp;URL</span>&#8221;栏中输入你自己的网站地址，在&#8220;<span style="font-family: Times New Roman;">Change&nbsp;frequency</span>&#8221;下拉列表选择网站的更新频率（经常&nbsp;每天&nbsp;每年等不同的时段），在&#8220;<span style="font-family: Times New Roman;">Last&nbsp;modification</span>&#8221;选择最后修改时间（建议选择<span style="font-size: 8.5pt;">Use&nbsp;server's&nbsp;response</span>服务器反映时间&nbsp;），在&#8220;Priority&#8221;栏中速入跟新的优先权，最后点击&#8220;Start&#8221;按钮创建网站地图&nbsp;（如图0）<img src="http://www.6b9g.com/sitemap0.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" /></p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">完成操作后，我们将在显示的结果中看到各式各样的网站生成地图Sitemap文件，将&#8220;Sitemap.xml&#8221;下载到本地然后再传到服务器主目录下，下面用Gmail帐户登陆到google&nbsp;Sitemap,添加自己的网站sitemap文件（如图2）<img src="http://www.6b9g.com/sitemap.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" />，再选在添加该站点的sitemap，注意在选择分类的时候选择添加常规网络(如图3)<img src="http://www.6b9g.com/sitemap3.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" />sitemap然后输入刚才上传得那个sitemap.xml地址，各式<a href="http://www.6b9g.com/sitemap.xml">http://www.6b9g.com/sitemap.xml</a>&nbsp;&nbsp;再点击&#8220;添加普通sitemap&#8221;&nbsp;按钮</p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">首发&nbsp;高峰&nbsp;站长互动信息网&nbsp;&nbsp;&nbsp;<a href="http://www.6b9g.com/">http://www.6b9g.com</a></p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179850.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:44 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>论坛灌水机 -- HTTPClient</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:37:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179849.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179849.html</trackback:ping><description><![CDATA[ 这篇文章是讲如何做一个论坛灌水机，针对某个大型房地产论坛测试通过，那是一个基于jive3的论坛，假如论坛加入了图片认证登陆，本程序将失去作用。<br />
<br />
本程序使用了HTTPClient包，下载地址：<br />
<a href="http://www.innovation.ch/java/HTTPClient/" target="_blank"><span style="color: #800080;">http://www.innovation.ch/java/HTTPClient/</span></a><br />
<br />
灌水机原理很简单，就是分析论坛的表单，用自己的程序模拟提交就可以了，<br />
本文的目的在于介绍HTTPClient这个开源工具，比jdk的.net包强何止百倍，<br />
HTTPClient的特点是多个操作可以复用同一个连接，设置连接超时(基于socket)，使用代理验证。具体可以到innovation网站看看对比数据。<br />
<br />
如下是灌水程序的简单程序，仅供参考<br />
import java.net.*;<br />
import java.io.*;<br />
import java.util.*;<br />
import HTTPClient.*;<br />
<br />
class WebRequester{<br />
private static InputStream istr = null;<br />
private static OutputStream ostr = null;<br />
private static NVPair form_data[];<br />
private static HTTPConnection httpCon;<br />
private static HTTPResponse rsp;<br />
private static String host;<br />
private static WebRequester instance;<br />
private WebRequester(){<br />
}<br />
public static WebRequester getInstance(){<br />
&nbsp;&nbsp;if(instance==null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;instance = new WebRequester();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return instance;<br />
}<br />
public static String request(HTTPConnection connection,String pathName,String method,NVPair form_data[]) {<br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;httpCon = connection;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(method.toLowerCase().equals("get")){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(form_data!=null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Get(pathName, form_data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Get(pathName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(form_data!=null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Post(pathName, form_data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Post(pathName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;istr = rsp.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader reader = new BufferedReader(new InputStreamReader(istr));<br />
&nbsp;&nbsp;&nbsp;&nbsp;String line;<br />
&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer result = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;while ((line = reader.readLine()) != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;result.append(line + System.getProperty("line.separator"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return result.toString();<br />
&nbsp;&nbsp;} catch(Exception e){<br />
&nbsp;&nbsp;}<br />
return "";<br />
}<br />
}<br />
<br />
<br />
public class Flood<br />
{<br />
private HTTPConnection connection;<br />
public Flood(){<br />
<br />
&nbsp;&nbsp;getConnection("sitename.com",80);<br />
}<br />
public void releaseConnection(){<br />
&nbsp;&nbsp;if(connection!=null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;connection.stop();<br />
&nbsp;&nbsp;&nbsp;&nbsp;connection = null;<br />
&nbsp;&nbsp;}<br />
}<br />
public HTTPClient.HTTPConnection getConnection(String hostName,int port){<br />
&nbsp;&nbsp;if(connection==null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection = new HTTPClient.HTTPConnection(hostName,port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HTTPClient.Module.setPolicyHandler(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.addDefaultModule(Class.forName("HTTPClient.Module"), 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.addModule(Class.forName("HTTPClient.RedirectionModule"),2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}catch(Exception e){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return connection;<br />
}<br />
<br />
public void post(String subject,String body){<br />
&nbsp;&nbsp;NVPair[] form_data = new NVPair[5];<br />
&nbsp;&nbsp;form_data[0] = new NVPair("forumID","87");<br />
&nbsp;&nbsp;form_data[1] = new NVPair("subject",subject);<br />
&nbsp;&nbsp;form_data[2] = new NVPair("classifier","-1");<br />
&nbsp;&nbsp;form_data[3] = new NVPair("body",body);<br />
&nbsp;&nbsp;form_data[4] = new NVPair("doPost"," 发 表 ");<br />
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);<br />
<br />
}<br />
public void reply(String thread,String subject,String body){<br />
&nbsp;&nbsp;//提交表单需要多少项，查看回复页面表单可以获得<br />
&nbsp;&nbsp;NVPair[] form_data = new NVPair[7];<br />
&nbsp;&nbsp;form_data[0] = new NVPair("forumID","87");<br />
&nbsp;&nbsp;form_data[1] = new NVPair("subject",subject);<br />
&nbsp;&nbsp;form_data[2] = new NVPair("classifier","-1");<br />
&nbsp;&nbsp;form_data[3] = new NVPair("body",body);<br />
&nbsp;&nbsp;form_data[4] = new NVPair("reply","true");<br />
&nbsp;&nbsp;form_data[5] = new NVPair("threadID",thread);<br />
&nbsp;&nbsp;form_data[6] = new NVPair("doPost"," 发 表 ");<br />
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);<br />
<br />
}<br />
public void finish(){<br />
&nbsp;&nbsp;releaseConnection();<br />
}<br />
public void login(){<br />
<br />
&nbsp;&nbsp;WebRequester wr = WebRequester.getInstance();<br />
&nbsp;&nbsp;NVPair[] form_data = new NVPair[4];<br />
&nbsp;&nbsp;//对应登陆需要的表单字段填写<br />
&nbsp;&nbsp;form_data[0] = new NVPair("formUsername","user");<br />
&nbsp;&nbsp;form_data[1] = new NVPair("formPassword","pass");<br />
&nbsp;&nbsp;form_data[2] = new NVPair("formLogins cript","sitename.com/loginuser.jsp");<br />
&nbsp;&nbsp;form_data[3] = new NVPair("forumLogin","Y");<br />
&nbsp;&nbsp;//提交到指定登陆页面<br />
&nbsp;&nbsp;wr.request(connection,"cgi-bin/gzhome/registration/LoginUser1.jsp","post",form_data);<br />
&nbsp;&nbsp;//假如重定向，必须用该链接再次请求新的页面<br />
&nbsp;&nbsp;wr.request(connection,"loginuser.jsp","get",null);<br />
&nbsp;&nbsp;wr.request(connection,"index.jspa","get",null);<br />
}<br />
<br />
<br />
public static void main(String[] args)<br />
{&nbsp;&nbsp; <br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;Flood f=new Flood();<br />
&nbsp;&nbsp;f.login();<br />
&nbsp;&nbsp;//post一个新主题，id由系统自己产生<br />
&nbsp;&nbsp;//f.post("friends","剧本");<br />
&nbsp;&nbsp;//得到某个主题id，进行指定数量的跟帖<br />
&nbsp;&nbsp;for(int i=0;i&lt;50;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;f.reply("67145","Re: 警告：在线朋友发言又少了，望奔走相告","洪水来了");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;/*如下是读取某个文件每一行文字作为回帖进行灌水<br />
&nbsp;&nbsp;BufferedReader
br = new BufferedReader(new FileReader("E:""movie""101-105""Friends -
1x04 - TOW George Stephanopoulos.CHN.srt"));<br />
&nbsp;&nbsp;StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;String t = null;<br />
&nbsp;&nbsp;int counter=0;<br />
&nbsp;&nbsp;while((t=br.readLine())!=null){<br />
&nbsp;&nbsp;if(t.length()==0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;//System.out.println(sb.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//System.out.println("====");<br />
&nbsp;&nbsp;counter++;<br />
&nbsp;&nbsp;f.reply("66617","" + counter,sb.toString());<br />
&nbsp;&nbsp;sb.delete(0,sb.length());<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;sb.append(t + ""n");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;}*/<br />
&nbsp;&nbsp;f.finish();<br />
}catch(Exception e){<br />
&nbsp;&nbsp;e.printStackTrace();<br />
}<br />
}<br />
}<br />
<br />
<br />
OKOK~大家自己研究<br />
我做好了
<img src ="http://www.blogjava.net/libin2722/aggbug/179849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:37 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>httpclient中MultipartPostMethod类上传文件</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179848.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179848.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179848.html</trackback:ping><description><![CDATA[<p>在文件上传过程中碰到很多问题，首先是搞错了类，刚开始时我用的是PostodMethod,以为一个
setrequestbody（）方法就可以搞定，结果改过来改过去也没改出来什么名堂，最后改用的是MultipartPostMethod类，呵呵，
问题解决了，关键点是MultipartPostMethod类里的addParameter()和addPart()两个方法都要用到，而且要注意顺
序。不过马上又出现了新的问题，httpclient不支持中文名的文件上传，晕了。又在这上面浪费了一段时间。解决的途径是。找到
httpclient3.0"rc"java"org"apache"commons"httpclient"util目录下的
EncodingUtil.java,打开，找到文件里面这个地方：<br />
public static byte[] getAsciiBytes(final String data) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
if (data == null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
throw new IllegalArgumentException("Parameter may not be null");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return data.getBytes("US-ASCII");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
catch (UnsupportedEncodingException e) {throw new HttpClientError("HttpClient requires ASCII support");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;<br />
}<br />
看
到了没有，return
data.getBytes("US-ASCII");它的编码方式是US-ASCII，问题就出在这里了，把这个取掉，换成"GBK"或者
"GB2312"保存以后编译，重新运行程序，goooooooooooood。中文名文件现在可以上传了，呵呵</p>
<p>Introducing FileUpload<br />
The FileUpload component has the
capability of simplifying the handling of files uploaded to a server.
Note that the FileUpload component is meant for use on the server side;
in other words, it handles where the files are being uploaded to—not
the client side where the files are uploaded from. Uploading files from
an HTML form is pretty simple; however, handling these files when they
get to the server is not that simple. If you want to apply any rules
and store these files based on those rules, things get more difficult.</p>
<p>The FileUpload component remedies this situation, and in very few
lines of code you can easily manage the files uploaded and store them
in appropriate locations. You will now see an example where you upload
some files first using a standard HTML form and then using HttpClient
code.</p>
<p>Using HTML File Upload<br />
The commonly used methodology to upload
files is to have an HTML form where you define the files you want to
upload. A common example of this HTML interface is the Web page you
encounter when you want to attach files to an email while using any of
the popular Web mail services.</p>
<p>In this example, you will create a simple HTML page where you
provide for three files to be uploaded. Listing 1-1 shows the HTML for
this page. Note that the enctype attribute for the form has the
multipart/form-data, and the input tag used is of type file. Based on
the of the action attribute, on form submission, the data is sent to
ProcessFileUpload.jsp.</p>
<p>Listing 1-1. UploadFiles.html<br />
&lt;HTML&gt;<br />
&nbsp;&nbsp;&lt;HEAD&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt; HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;TITLE&gt;File Upload Page&lt;/TITLE&gt;<br />
&nbsp;&nbsp;&lt;/HEAD&gt;<br />
&nbsp;&nbsp;&lt;BODY&gt;Upload Files<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;FORM name="filesForm" action="ProcessFileUpload.jsp"<br />
&nbsp;&nbsp;&nbsp;&nbsp;method="post" enctype="multipart/form-data"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File 1:&lt;input type="file" name="file1"/&gt;&lt;br/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File 2:&lt;input type="file" name="file2"/&gt;&lt;br/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File 3:&lt;input type="file" name="file3"/&gt;&lt;br/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input type="submit" name="Submit" ="Upload Files"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/FORM&gt;<br />
&nbsp;&nbsp;&lt;/BODY&gt;<br />
&lt;/HTML&gt;</p>
<p>You can use a servlet to handle the file upload. I have used JSP to
minimize the code you need to write. The task that the JSP has to
accomplish is to pick up the files that are sent as part of the request
and store these files on the server. In the JSP, instead of displaying
the result of the upload in the Web browser, I have chosen to print
messages on the server console so that you can use this same JSP when
it is not invoked through an HTML form but by using HttpClient-based
code.</p>
<p>Listing 1-2 shows the JSP code. Note the code that checks whether
the item is a form field. This check is required because the Submit
button contents are also sent as part of the request, and you want to
distinguish between this data and the files that are part of the
request. You have set the maximum file size to 1,000,000 bytes using
the setSizeMax method.</p>
<p>Listing 1-2. ProcessFileUpload.jsp<br />
&lt;%@ page contentType="text/html;charset=windows-1252"%&gt;<br />
&lt;%@ page import="org.apache.commons.fileupload.DiskFileUpload"%&gt;<br />
&lt;%@ page import="org.apache.commons.fileupload.FileItem"%&gt;<br />
&lt;%@ page import="jsp servlet ejb .util.List"%&gt;<br />
&lt;%@ page import="jsp servlet ejb .util.Iterator"%&gt;<br />
&lt;%@ page import="jsp servlet ejb .io.File"%&gt;<br />
html&gt;<br />
&lt;head&gt;<br />
&lt; http-equiv="Content-Type" content="text/html; charset=windows-1252"&gt;<br />
&lt;title&gt;Process File Upload&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;%<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Content Type ="+request.getContentType());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DiskFileUpload fu = new DiskFileUpload();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// If file size exceeds, a FileUploadException will be thrown<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fu.setSizeMax(1000000);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List fileItems = fu.parseRequest(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator itr = fileItems.iterator();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(itr.hasNext()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileItem fi = (FileItem)itr.next();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Check if not form field so as to only handle the file inputs<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//else condition handles the submit button input<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!fi.isFormField()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(""nNAME: "+fi.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("SIZE: "+fi.getSize());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//System.out.println(fi.getOutputStream().toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File fNew= new File(application.getRealPath("/"), fi.getName());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(fNew.getAbsolutePath());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi.write(fNew);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Field ="+fi.getFieldName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
%&gt;<br />
&lt;body&gt;<br />
Upload Successful!!<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>CAUTION With FileUpload 1.0 I found that when the form was submitted
using Opera version 7.11, the getName method of the class FileItem
returns just the name of the file. However, if the form is submitted
using Internet Explorer 5.5, the filename along with its entire path is
returned by the same method. This can cause some problems.</p>
<p>To run this example, you can use any three files, as the contents of
the files are not important. Upon submitting the form using Opera and
uploading three random XML files, the output I got on the Tomcat server
console was as follows:</p>
<p>Content Type =multipart/form-data; boundary=----------rz7ZNYDVpN1To8L73sZ6OE</p>
<p>NAME: academy.xml<br />
SIZE: 951<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academy.xml</p>
<p>NAME: academyRules.xml<br />
SIZE: 1211<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academyRules.xml</p>
<p>NAME: students.xml<br />
SIZE: 279<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"students.xml<br />
Field =Submit<br />
However, when submitting this same form using Internet Explorer 5.5, the output on the server console was as follows:<br />
Content Type =multipart/form-data; boundary=---------------------------7d3bb1de0<br />
2e4</p>
<p>NAME: D:"temp"academy.xml<br />
SIZE: 951<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"D:"temp"academy.xml</p>
<p>The browser displayed the following message: &#8220;The requested resource
(D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"D:"temp"academy.xml
(The filename, directory name, or volume label syntax is incorrect)) is
not available.&#8221;</p>
<p>This contrasting behavior on different browsers can cause problems. One workaround that I found in an article at <a href="http://www.onjava.com/pub/a/onjava/2003/06/25/commons.html" target="_blank"><span style="color: #000000;">http://www.onjava.com/pub/a/onjava/2003/06/25/commons.html</span></a>
is to first create a file reference with whatever is supplied by the
getName method and then create a new file reference using the name
returned by the earlier file reference. Therefore, you can insert the
following code to have your code work with both browsers (I wonder who
the guilty party is&#8230;blaming Microsoft is always the easy way out) </p>
<p>File tempFileRef&nbsp;&nbsp;= new File(fi.getName());<br />
File fNew = new File(application.getRealPath("/"),tempFileRef.getName());</p>
<p>In this section, you uploaded files using a standard HTML form
mechanism. However, often a need arises to be able to upload files from
within your jsp servlet ejb code, without any browser or form coming
into the picture. In the next section, you will look at
HttpClient-based file upload.</p>
<p>Using HttpClient-Based FileUpload<br />
Earlier in the article you saw
some of the capabilities of the HttpClient component. One capability I
did not cover was its ability to send multipart requests. In this
section, you will use this capability to upload a few files to the same
JSP that you used for uploads using HTML.</p>
<p>The class org.apache.commons.httpclient.methods.MultipartPostMethod
provides the multipart method capability to send multipart-encoded
forms, and the package org.apache.commons.httpclient.methods.multipart
has the support classes required. Sending a multipart form using
HttpClient is quite simple. In the code in Listing 1-3, you send three
files to ProcessFileUpload.jsp.</p>
<p>Listing 1-3. HttpMultiPartFileUpload.java<br />
package com.commonsbook.chap9;<br />
import jsp servlet ejb .io.File;<br />
import jsp servlet ejb .io.IOException;</p>
<p>import org.apache.commons.httpclient.HttpClient;<br />
import org.apache.commons.httpclient.methods.MultipartPostMethod;</p>
<p>public class HttpMultiPartFileUpload {<br />
&nbsp;&nbsp;&nbsp;&nbsp;private static String url =<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"http://localhost/yaoliang/ProcessFileUpload.jsp";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws IOException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient client = new HttpClient();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MultipartPostMethod mPost = new MultipartPostMethod(url);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.setConnectionTimeout(8000);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Send any XML file as the body of the POST request<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File f1 = new File("D:/students.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File f2 = new File("D:/demy.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File f3 = new File("D:/demyRules.xml");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File1 Length = " + f1.length());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File2 Length = " + f2.length());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File3 Length = " + f3.length());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.addParameter(f1.getName(),f1.getName(),&nbsp;&nbsp;f1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.addParameter(f2.getName(), f2.getName(), f2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.addParameter(f3.getName(), f3.getName(),f3);</p>
<p>FilePart part1 = new FilePart("file1",file);<br />
FilePart part2 = new FilePart("file2",file);<br />
FilePart part3 = new FilePart("file3",file);<br />
mPost.addPart(part1);<br />
mPost.addPart(part2);<br />
mPost.addPart(part3);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int statusCode1 = client.executeMethod(mPost);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("statusLine&gt;&gt;&gt;" + mPost.getStatusLine());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.releaseConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>In this code, you just add the files as parameters and execute the
method. The ProcessFileUpload.jsp file gets invoked, and the output is
as follows:</p>
<p>Content Type =multipart/form-data; boundary=----------------31415926535897932384<br />
6</p>
<p>NAME: students.xml<br />
SIZE: 279<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"students.xml</p>
<p>NAME: academy.xml<br />
SIZE: 951<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academy.xml</p>
<p>NAME: academyRules.xml<br />
SIZE: 1211<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academyRules.xml</p>
<p>Thus, file uploads on the server side become quite a simple task if you are using the Commons FileUpload component.</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:35 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用HttpClient来对付各种顽固的WEB服务器</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:34:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179847.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179847.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179847.html</trackback:ping><description><![CDATA[<p>一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器，用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面
有的仅仅是一些普通的页面，有的需要用户登录后方可使用，或者需要认证以及是一些通过加密方式传输，例如HTTPS。目前我们使用的浏览器处理这些情况都
不会构成问题。不过你可能在某些时候需要通过程序来访问这样的一些页面，比如从别人的网页中&#8220;偷&#8221;一些数据；利用某些站点提供的页面来完成某种功能，例如
说我们想知道某个手机号码的归属地而我们自己又没有这样的数据，因此只好借助其他公司已有的网站来完成这个功能，这个时候我们需要向网页提交手机号码并从
返回的页面中解析出我们想要的数据来。如果对方仅仅是一个很简单的页面，那我们的程序会很简单，本文也就没有必要大张旗鼓的在这里浪费口舌。但是考虑到一
些服务授权的问题，很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的，而必须经过注册然后登录后方可使用提供服务的页面，这个时候就涉
及到问题的处理。我们知道目前流行的动态网页技术例如ASP、JSP无不是通过来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面，就要求程
序首先登录后再访问服务页面，这过程就需要自行处理，想想当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情
啊！况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的&#8220;顽固&#8221;！再有如通过HTTP来上传文件呢？不需要头疼，这些问题有了&#8220;它&#8221;就很容易解决
了！ <br />
</p>
<p><span style="font-size: 10pt; font-family: Courier New;">我们不可能列举所
有可能的顽固，我们会针对几种最常见的问题进行处理。当然了，正如前面说到的，如果我们自己使用java.net.HttpURLConnection来
搞定这些问题是很恐怖的事情，因此在开始之前我们先要介绍一下一个开放源码的项目，这个项目就是Apache开源组织中的httpclient，它隶属于
Jakarta的commons项目，目前的版本是2.0RC2。commons下本来已经有一个net的子项目，但是又把httpclient单独提出
来，可见http服务器的访问绝非易事。</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">Commons-httpclient
项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决，例如你不再管是HTTP或者HTTPS的
通讯方式，告诉它你想使用HTTPS方式，剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进
行分别介绍如何使用httpclient来解决它们，为了让读者更快的熟悉这个项目我们最开始先给出一个简单的例子来读取一个网页的内容，然后循序渐进解
决掉前进中的所有问题。</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">1． 读取网页(HTTP/HTTPS)内容</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">下面是我们给出的一个简单的例子用来访问某个页面</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">/*</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">* Created on 2003-12-14 by Liudong</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">*/</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">package http.demo;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">import java.io.IOException;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">import org.apache.commons.httpclient.*;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">import org.apache.commons.httpclient.methods.*;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">/**</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">* 最简单的HTTP客户端,用来演示通过GET或者POST方式访问某个页面</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">* @author Liudong</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">*/</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">public class SimpleClient {</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws IOException</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;{</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient client = new HttpClient();&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置代理服务器地址和端口&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//使用GET方法，如果服务器需要通过HTTPS连接，那只需要将下面URL中的http换成https</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpMethod method = new GetMethod("<a href="http://java.sun.com/" target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//使用POST方法</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//HttpMethod method = new PostMethod("<a href="http://java.sun.com/" target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.executeMethod(method);</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印服务器返回的状态</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(method.getStatusLine());</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印返回的信息</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(method.getResponseBodyAsString());</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//释放连接</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.releaseConnection();</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">在这个例子中首先创建一个
HTTP客户端(HttpClient)的实例，然后选择提交的方法是GET或者POST，最后在HttpClient实例上执行提交的方法，最后从所选
择的提交方法中读取服务器反馈回来的结果。这就是使用HttpClient的基本流程。其实用一行代码也就可以搞定整个请求的过程，非常的简单！</span></p>
<span style="font-size: 10pt; font-family: Courier New;">
<p><br />
2． 以GET或者POST方式向网页提交参数</p>
<p>其实前面一个最简单的示例中我们已经介绍了如何使用GET或者POST方式来请求一个页面，本小节与之不同的是多了提交时设定页面所需的参数，我们
知道如果是GET的请求方式，那么所有参数都直接放到页面的URL后面用问号与页面地址隔开，每个参数用&amp;隔开，例如：<a href="http://java.sun.com/?name=liudong&amp;mobile=123456" target="_blank"><span style="color: #000000;">http://java.sun.com?name=liudong&amp;mobile=123456</span></a>，但是当使用POST方法时就会稍微有一点点麻烦。本小节的例子演示向如何查询手机号码所在的城市，代码如下：</p>
<p>/*</p>
<p>* Created on 2003-12-7 by Liudong</p>
<p>*/</p>
<p>package http.demo;</p>
<p>import java.io.IOException;</p>
<p>import org.apache.commons.httpclient.*;</p>
<p>import org.apache.commons.httpclient.methods.*;</p>
<p>/**</p>
<p>* 提交参数演示</p>
<p>* 该程序连接到一个用于查询手机号码所属地的页面</p>
<p>* 以便查询号码段1330227所在的省份以及城市</p>
<p>* @author Liudong</p>
<p>*/</p>
<p>public class SimpleHttpClient {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws IOException</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient client = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.getHostConfiguration().setHost("<a href="http://www.imobile.com.cn/" target="_blank"><span style="color: #000000;">www.imobile.com.cn</span></a>", 80, "http");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpMethod method = getPostMethod();//使用POST方式提交数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.executeMethod(method);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印服务器返回的状态</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(method.getStatusLine());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印结果页面</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String response =</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new String(method.getResponseBodyAsString().getBytes("8859_1"));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印返回的信息</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(response);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.releaseConnection();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/**</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * 使用GET方式提交数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @return</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;private static HttpMethod getGetMethod(){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new GetMethod("/simcard.php?simcard=1330227");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/**</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * 使用POST方式提交数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @return</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;private static HttpMethod getPostMethod(){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PostMethod post = new PostMethod("/simcard.php");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NamePair simcard = new NamePair("simcard","1330227");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;post.setRequestBody(new NamePair[] { simcard});</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return post;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>}</p>
<p>在上面的例子中页面<a href="http://www.imobile.com.cn/simcard.php" target="_blank"><span style="color: #000000;">http://www.imobile.com.cn/simcard.php</span></a>需要一个参数是simcard，这个参数值为手机号码段，即手机号码的前七位，服务器会返回提交的手机号码对应的省份、城市以及其他详细信息。GET的提交方法只需要在URL后加入参数信息，而POST则需要通过NamePair类来设置参数名称和它所对应的值</p>
<p>3． 处理页面重定向</p>
<p>在JSP/Servlet编程中response.sendRedirect方法就是使用HTTP协议中的重定向机制。它与JSP中的&lt;
jsp:forward
&#8230;&gt;的区别在于后者是在服务器中实现页面的跳转，也就是说应用容器加载了所要跳转的页面的内容并返回给客户端；而前者是返回一个状态码，这些状态码
的可能值见下表，然后客户端读取需要跳转到的页面的URL并重新加载新的页面。就是这样一个过程，所以我们编程的时候就要通过
HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认需要进行页面跳转了，那么可
以通过读取HTTP头中的location属性来获取新的地址。</p>
</span>
<img src ="http://www.blogjava.net/libin2722/aggbug/179847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:34 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA对数字证书的常用操作</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179844.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:16:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179844.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179844.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179844.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179844.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179844.html</trackback:ping><description><![CDATA[<p><strong>一需要包含的包</strong></p>
<p>import java.security.*;<br />
<br />
import java.io.*;<br />
<br />
import java.util.*;<br />
<br />
import java.security.*;<br />
<br />
import java.security.cert.*;<br />
<br />
import sun.security.x509.*<br />
<br />
import java.security.cert.Certificate;<br />
<br />
import java.security.cert.CertificateFactory; </p>
<p><strong>二 从文件中读取证书</strong></p>
<p>用keytool将.keystore中的证书写入文件中，然后从该文件中读取证书信息<br />
<br />
CertificateFactory cf=CertificateFactory.getInstance("X.509");<br />
<br />
FileInputStream in=new FileInputStream("out.csr");<br />
<br />
Certificate c=cf.generateCertificate(in); String s=c.toString();</p>
<p><strong>三 从密钥库中直接读取证书</strong></p>
<p>String pass="123456";<br />
<br />
FileInputStream in=new FileInputStream(".keystore");<br />
<br />
KeyStore ks=KeyStore.getInstance("JKS");<br />
<br />
ks.load(in,pass.toCharArray());<br />
<br />
java.security.cert.Certificate c=ks.getCertificate(alias);//alias为条目的别名</p>
<p><strong>四 JAVA程序中显示证书指定信息</strong></p>
<p>System.out.println("输出证书信息:"n"+c.toString());<br />
<br />
System.out.println("版本号:"+t.getVersion());<br />
<br />
System.out.println("序列号:"+t.getSerialNumber().toString(16));<br />
<br />
System.out.println("主体名："+t.getSubjectDN());<br />
<br />
System.out.println("签发者："+t.getIssuerDN());<br />
<br />
System.out.println("有效期："+t.getNotBefore());<br />
<br />
System.out.println("签名算法："+t.getSigAlgName());<br />
<br />
byte [] sig=t.getSignature();//签名值<br />
<br />
PublicKey pk=t.getPublicKey();<br />
<br />
byte [] pkenc=pk.getEncoded();<br />
<br />
System.out.println("公钥");<br />
<br />
for(int i=0;i&lt;pkenc.length;i++)System.out.print(pkenc[i]+","); </p>
<p><strong>五 JAVA程序列出密钥库所有条目</strong></p>
<p>String pass="123456";<br />
<br />
FileInputStream in=new FileInputStream(".keystore");<br />
<br />
KeyStore ks=KeyStore.getInstance("JKS");<br />
<br />
ks.load(in,pass.toCharArray());<br />
<br />
Enumeration e=ks.aliases();<br />
<br />
while(e.hasMoreElements())<br />
<br />
java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());</p>
<p><strong>六 JAVA程序修改密钥库口令</strong></p>
<p>String oldpass="123456";<br />
<br />
String newpass="654321";<br />
<br />
FileInputStream in=new FileInputStream(".keystore");<br />
<br />
KeyStore ks=KeyStore.getInstance("JKS");<br />
<br />
ks.load(in,oldpass.toCharArray());<br />
<br />
in.close();<br />
<br />
FileOutputStream output=new FileOutputStream(".keystore");<br />
<br />
ks.store(output,newpass.toCharArray());<br />
<br />
output.close();</p>
<p><strong>七 JAVA程序修改密钥库条目的口令及添加条目</strong></p>
<p>FileInputStream in=new FileInputStream(".keystore");<br />
<br />
KeyStore ks=KeyStore.getInstance("JKS");<br />
<br />
ks.load(in,storepass.toCharArray());<br />
<br />
Certificate [] cchain=ks.getCertificate(alias);获取别名对应条目的证书链<br />
<br />
PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());获取别名对应条目的私钥<br />
<br />
ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密钥库中添加条目<br />
<br />
第一个参数指定所添加条目的别名，假如使用已存在别名将覆盖已存在条目，使用新别名将增加一个新条目，第二个参数为条目的私钥，第三个为设置的新口令，第四个为该私钥的公钥的证书链<br />
<br />
FileOutputStream output=new FileOutputStream("another");<br />
<br />
ks.store(output,storepass.toCharArray())将keystore对象内容写入新文件</p>
<p><strong>八 JAVA程序检验别名和删除条目</strong></p>
<p>FileInputStream in=new FileInputStream(".keystore");<br />
<br />
KeyStore ks=KeyStore.getInstance("JKS");<br />
<br />
ks.load(in,storepass.toCharArray());<br />
<br />
ks.containsAlias("sage");检验条目是否在密钥库中，存在返回true<br />
<br />
ks.deleteEntry("sage");删除别名对应的条目<br />
<br />
FileOutputStream output=new FileOutputStream(".keystore");<br />
<br />
ks.store(output,storepass.toCharArray())将keystore对象内容写入文件,条目删除成功</p>
<p><strong>九 JAVA程序签发数字证书</strong></p>
<p>（1）从密钥库中读取CA的证书<br />
<br />
FileInputStream in=new FileInputStream(".keystore");<br />
<br />
KeyStore ks=KeyStore.getInstance("JKS");<br />
<br />
ks.load(in,storepass.toCharArray());<br />
<br />
java.security.cert.Certificate c1=ks.getCertificate("caroot");<br />
<br />
（2）从密钥库中读取CA的私钥<br />
<br />
PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());<br />
<br />
（3）从CA的证书中提取签发者的信息<br />
<br />
byte[] encod1=c1.getEncoded(); 提取CA证书的编码<br />
<br />
X509CertImpl cimp1=new X509CertImpl(encod1); 用该编码创建X509CertImpl类型对象<br />
<br />
X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象<br />
<br />
X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 获取X509Name类型的签发者信息<br />
<br />
（4）获取待签发的证书<br />
<br />
CertificateFactory cf=CertificateFactory.getInstance("X.509");<br />
<br />
FileInputStream in2=new FileInputStream("user.csr");<br />
<br />
java.security.cert.Certificate c2=cf.generateCertificate(in);<br />
<br />
（5）从待签发的证书中提取证书信息<br />
<br />
byte [] encod2=c2.getEncoded();<br />
<br />
X509CertImpl cimp2=new X509CertImpl(encod2); 用该编码创建X509CertImpl类型对象<br />
<br />
X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象<br />
<br />
（6）设置新证书有效期<br />
<br />
Date begindate=new Date(); 获取当前时间<br />
<br />
Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期为3000天<br />
<br />
CertificateValidity cv=new CertificateValidity(begindate,enddate); 创建对象<br />
<br />
cinfo2.set(X509CertInfo.VALIDITY,cv); 设置有效期<br />
<br />
（7）设置新证书序列号<br />
<br />
int sn=(int)(begindate.getTime()/1000); 以当前时间为序列号<br />
<br />
CertificateSerialNumber csn=new CertificateSerialNumber(sn);<br />
<br />
cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);<br />
<br />
（8）设置新证书签发者<br />
<br />
cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);应用第三步的结果<br />
<br />
（9）设置新证书签名算法信息<br />
<br />
AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);<br />
<br />
cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);<br />
<br />
（10）创建证书并使用CA的私钥对其签名<br />
<br />
X509CertImpl newcert=new X509CertImpl(cinfo2);<br />
<br />
newcert.sign(caprk,"MD5WithRSA"); 使用CA私钥对其签名<br />
<br />
（11）将新证书写入密钥库<br />
<br />
ks.setCertificateEntry("lf_signed",newcert);<br />
<br />
FileOutputStream out=new FileOutputStream("newstore");<br />
<br />
ks.store(out,"newpass".toCharArray()); 这里是写入了新的密钥库，也可以使用第七条来增加条目</p>
<p><strong>十 数字证书的检验</strong></p>
<p>（1）验证证书的有效期<br />
<br />
（a）获取X509Certificate类型对象<br />
<br />
CertificateFactory cf=CertificateFactory.getInstance("X.509");<br />
<br />
FileInputStream in1=new FileInputStream("aa.crt");<br />
<br />
java.security.cert.Certificate c1=cf.generateCertificate(in1);<br />
<br />
X509Certificate t=(X509Certificate)c1;<br />
<br />
in2.close();<br />
<br />
（b）获取日期<br />
<br />
Date TimeNow=new Date();<br />
<br />
（c）检验有效性<br />
<br />
try{<br />
<br />
t.checkValidity(TimeNow);<br />
<br />
System.out.println("OK");<br />
<br />
}catch(CertificateExpiredException e){ //过期<br />
<br />
System.out.println("Expired");<br />
<br />
System.out.println(e.getMessage());<br />
<br />
}catch((CertificateNotYetValidException e){ //尚未生效<br />
<br />
System.out.println("Too early");<br />
<br />
System.out.println(e.getMessage());}<br />
<br />
（2）验证证书签名的有效性<br />
<br />
（a）获取CA证书<br />
<br />
CertificateFactory cf=CertificateFactory.getInstance("X.509");<br />
<br />
FileInputStream in2=new FileInputStream("caroot.crt");</p>
<p> java.security.cert.Certificate cac=cf.generateCertificate(in2);<br />
<br />
in2.close();<br />
<br />
（c）获取CA的公钥<br />
<br />
PublicKey pbk=cac.getPublicKey();<br />
<br />
（b）获取待检验的证书（上步已经获取了，就是C1）<br />
<br />
（c）检验证书<br />
<br />
boolean pass=false;<br />
<br />
try{<br />
<br />
c1.verify(pbk);<br />
<br />
pass=true;<br />
<br />
}catch(Exception e){<br />
<br />
pass=false;<br />
<br />
System.out.println(e);<br />
<br />
}</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:16 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java实现CA(四)</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179843.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:14:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179843.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179843.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179843.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179843.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179843.html</trackback:ping><description><![CDATA[前面几篇文章已经把如何用Java实现一个CA基本上讲完了.但是他们都有一个特点,就是用户的信息都是在现场获取的,不能做申请和签发相分离.今天我们要讲述的是PKCS#10证书请求文件.它的作用就是可以使申请和签发相分离.
<p>&nbsp;&nbsp;&nbsp;&nbsp;PKCS#10证书请求结构中的主要信息包含了被签发者(证书申请者)的主体名称(DN)和他的公钥.因此一个CA在获取到一个PKCS#10证书请求后,就可以从中获取到任何和签发证书有关的信息,然后用它自己的私钥签发证书.</p>
<p>&nbsp;&nbsp;&nbsp; 使用BC Provider在Java中构造一个证书请求格式的对象调用其构造函数即可,这个函数如下:</p>
<p>&nbsp;&nbsp;&nbsp; PKCS10CertificationRequest(java.lang.String signatureAlgorithm,
X509Name subject, java.security.PublicKey key, ASN1Set attributes,
java.security.PrivateKey signingKey)</p>
<p>&nbsp;&nbsp;&nbsp; 它的参数是自签名算法,证书申请者的DN,证书申请者的公钥,额外的属性集(就是要申请的证书的扩展信息),申请证书者的私钥.申请证书者的私钥仅仅是用来进行一下自签名,并不出现在证书请求中,需要自签名的目的是保证该公钥确实为申请者所有.</p>
<p>&nbsp;&nbsp;&nbsp; 调用该对象的getEncoded()方法可以将其进行DER编码,然后储存起来,该对象还有另一个构造函数:<br />
&nbsp;&nbsp;&nbsp; PKCS10CertificationRequest(byte[] bytes)<br />
&nbsp;&nbsp;&nbsp; 这个构造函数的作用就是直接从储存的DER编码中把这个对象还原出来.</p>
<p>&nbsp;&nbsp;&nbsp; 利用证书请求结构进行证书签发的代码如下,这里假设CSR是一个已经获取出来的PKCS10CertificationRequest结构:</p>
<p>&nbsp;&nbsp;&nbsp; PublicKey SubjectPublicKey = CSR.getPublicKey();<br />
&nbsp;&nbsp;&nbsp; CertificationRequestInfo CSRInfo = CSR.getCertificationRequestInfo();<br />
&nbsp;&nbsp;&nbsp; X509Name SubjectDN = CSRInfo.getSubject();<br />
&nbsp;&nbsp;&nbsp; ASN1Set Attributes = CSRInfo.getAttributes();</p>
<p>&nbsp;&nbsp;&nbsp;
这样,申请者的主体DN,申请者的公钥,申请者希望在证书扩展信息中填写的属性都得到了,剩下的事情就和用户在现场输入时一样了,其它的信息一般是申请者
不能决定的.另外证书请求格式中有一样信息没有明确给出来,那就是证书的有效期,这个应该单独询问用户,或者用其它的方法保存起来.</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179843.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:14 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179843.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java实现CA(二)</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179841.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:12:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179841.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179841.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179841.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179841.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179841.html</trackback:ping><description><![CDATA[上次我们讲到如何生成密钥对,以及如何将诸如公钥,私钥,证书等这一类安全对象在文件系统和内存之间来回转换.这些是准备开CA的基本功,今天我们讲一下CA的基本原理以及如何使用主体名称结构DN(Distinguish Name)来表示每一个证书中的主体.
<p>&nbsp;&nbsp;&nbsp;
一份证书就是一个权威机构对一个主体的身份的确认的证明.即一份证书表示一个权威机构确认了一个主体就是它自己,而不是其它的冒名顶替者.主体可以是一个
个人,也可以不是,例如,在需要安全服务的时候,需要为一台网站的服务器颁发证书,这种证书的主体就是一台服务器.签署证书的权威机构就叫做CA,该权威
机构本身也是一个主体.权威机构通过对包含有待认证的主体的一系列信息的待签名证书"(TBS,to be
signed)进行数字签名来表示该机构对它的认可.一份包含了待认证的主体的相关信息的TBS再加上CA使用自己的私钥进行签名产生的字节流放在一起,
就构成了一份标准的X509证书.</p>
<p>&nbsp;&nbsp;&nbsp; 一个TBS中包含了以下这些主要信息:</p>
<p>&nbsp;&nbsp;&nbsp; 证书的版本,通常是3(X509v3)</p>
<p>&nbsp;&nbsp;&nbsp; 证书的序列号,RFC3280中规定,每个CA必须确保它颁发的每一份证书的序列号都是唯一的,并且序列号只能使用非负整数.</p>
<p>&nbsp;&nbsp;&nbsp; 签发者(CA)的主体名称,一个DN对象.</p>
<p>&nbsp;&nbsp;&nbsp; 证书的有效期,表示方法是两个时间值,表示了该证书从何时开始生效,何时开始作废.</p>
<p>&nbsp;&nbsp;&nbsp; 待认证的主体的主体名称,也是一个DN对象.</p>
<p>&nbsp;&nbsp;&nbsp; 待认证的主体的公钥,任何安全应用在确认完证书的有效性后,就可以开始使用该主体的公钥与之进行安全通信.</p>
<p>&nbsp;&nbsp;&nbsp; 如果是X509v3证书,即版本号是3的话,后面还有一个证书扩展信息字段,可以在证书里面添加一些其它的信息.</p>
<p>&nbsp;&nbsp;&nbsp; 下面我们来看一下表示主体的主体名称结构:DN.这个结就构是一个属性的集合.每个属性有属性名称和属性值.它的作用就是用来表示"我是谁",也就是说,这个证书到底是谁颁发给谁的,这个证书对应的公钥是谁拥有的.</p>
<p>&nbsp;&nbsp;&nbsp; 通常使用一个字符串来表示DN结构,这种字符串说明了这种结构中的各个属性的类型和值:</p>
<p>&nbsp;&nbsp;&nbsp; C=CN;S=BeiJing;L=BeiJing;O=PKU;OU=ICST;CN=wolfenstein</p>
<p align="left">&nbsp;&nbsp;&nbsp;
这里C是国家和地区代码,S和L都是地区代码,S相当于省或者州这样的级别,L相当于城市级别,O是组织机构名称,OU是次级组织机构名称,CN是主体的
通用名(common
name).在这里,C,S,L等等属性的类型都是相对固定的,例如C一般就是用来表示国家和地区代码,在DN结构中还可以添加一些其它类型的信息,一般
也都是以"xxx=xxx"这样来表示的.</p>
<p align="left">&nbsp;&nbsp;&nbsp; 下面我们来说明如何在Java语言中构造出一个主体名称对象.</p>
<p align="left">&nbsp;&nbsp;&nbsp; BC Provider中使用X509Name对象来表示DN,构造一个X509Name的步骤大体如下:</p>
<p align="left">&nbsp;&nbsp;&nbsp; 先构造两个vector对象,用来表示属性名称和属性值:</p>
<p align="left">&nbsp;&nbsp;&nbsp; Vector oids = new Vector();<br />
&nbsp;&nbsp;&nbsp; Vector attributes = new Vector();</p>
<p align="left">&nbsp;&nbsp;&nbsp; 然后在oids这个用来表示属性名称的vector对象中将属性名称一个一个添加进去:</p>
<p align="left">&nbsp;&nbsp;&nbsp; oids.addElement(X509Name.C);</p>
<p align="left">&nbsp;&nbsp;&nbsp; ......</p>
<p align="left">&nbsp;&nbsp;&nbsp; oids.addElement(X509Name.CN);</p>
<p align="left">&nbsp;&nbsp;&nbsp; X509Name对象里面有若干常量,例如上面的X509Name.C.还有X509Name.ST等等,都可以和上面举的例子对应起来.</p>
<p align="left">&nbsp;&nbsp;&nbsp; 然后将属性值添加到attributes对象中:</p>
<p align="left">&nbsp;&nbsp;&nbsp; attributes.addElement("CN");</p>
<p align="left">&nbsp;&nbsp;&nbsp; ......</p>
<p align="left">&nbsp;&nbsp;&nbsp; attributes.addElement("Wolfenstein");</p>
<p align="left">&nbsp;&nbsp;&nbsp; 最后就可以构造出一个X509Name对象:</p>
<p align="left">&nbsp;&nbsp;&nbsp; X509Name SubjectDN = new X509Name(oids, attributes);</p>
<p align="left">&nbsp;&nbsp;&nbsp; 这样,我们的主体名称结构就确立起来了.</p>
<p align="left">&nbsp;&nbsp;&nbsp; 下次我们就可以讲关键的部分了,那就是如何用Java程序完成CA最重要的功能,签署证书.</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179841.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:12 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179841.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java实现CA(一)</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179839.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:11:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179839.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179839.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179839.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179839.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179839.html</trackback:ping><description><![CDATA[通过我昨天的文章大家应该已经清楚了,用Java写信息安全方面的程序需要做的准备工作.好了,现在假设你已经是一个对Java语言本身比较熟悉,能够用Java写一些程序的人,并且这些该下载的jar包已经下载好了,可以正式开工了.
<p>&nbsp;&nbsp;&nbsp;
在所有的此类程序的开头(无论是在类的构造函数中也好,在初始化函数中也好),都要先来上这么一句:Security.addProvider(new
BouncyCastleProvider());将BouncyCaslte的Provider添加到系统中,这样以后系统在运行相关程序的时候调用的
就是这个Provider中的加密算法.</p>
<p>&nbsp;&nbsp;&nbsp;
然后我们就可以开始开CA了.首先,作为一个CA要有自己的一对公钥和私钥,我们先要生成这么一对.使用KeyPairGenerator对象就可以了,
调用KeyPairGenerator.getInstance方法可以根据要生成的密钥类型来产生一个合适的实例,例如常用的RSA,DSA等.然后调
用该对象的initialize方法和generateKeyPair方法就可以产生一个KeyPair对象了.然后调用KeyPair对象中的相应方法
就可以获取生成的密钥对中的公钥和私钥了.</p>
<p>&nbsp;&nbsp;&nbsp;
有了公钥和私钥对以后,下面的一个很现实问题就是如何把它们储存起来.通常我们要对这些安全对象,如公钥,私钥,证书等先进行编码.编码的目的是为了把结
构复杂的安全对象变成字节流以便存储和读取,如DER编码.另外,通常还把DER编码后的字节流再次进行base64编码,以便使字节流中所有的字节都变
成可打印的字节.</p>
<p>&nbsp;&nbsp;&nbsp; 在Java语言中,这些安全对象基本上都有getEncoded()方法.例如:</p>
<p>&nbsp;&nbsp;&nbsp; byte[] keyBytes = privateKey.getEncoded();</p>
<p>&nbsp;&nbsp;&nbsp; 这样就把一个私钥进行了DER编码后的结果保存到一个byte数组中了.然后就可以把这个byte数组保存到任何介质中.如果有必要的话,可以使用BC Provider中的Base64编码解码器类进行编码,就像这样:</p>
<p>&nbsp;&nbsp;&nbsp; byte data[] = Base64.encode(keyBytes);</p>
<p>&nbsp;&nbsp;&nbsp; 要从文件中读取私钥则应该这样:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyData);<br />
&nbsp;&nbsp;&nbsp;&nbsp;KeyFactory kfac = KeyFactory.getInstance("RSA");<br />
&nbsp;&nbsp;&nbsp;&nbsp;privateKey = kfac.generatePrivate(spec);</p>
<p>&nbsp;&nbsp;&nbsp;
这里说明一下,对RSA私钥进行编码就会自动地按照PKCS8进行.因此读取的时候将包含编码的字节数组作为PKCS8EncodedKeySpec对象
的构造函数的参数就可以生成一个该类型的对象.然后创建一个密钥工厂对象就可以按照要求生成一个RSA私钥了.很显然这里的keyData应该是和上面的
keyBytes内容相同.</p>
<p>&nbsp;&nbsp;&nbsp; 为了提高系统的安全性,通常私钥在经过DER编码后,还会使用一个口令进行加密,然后再储存在文件系统中.在使用私钥的时候,如果没有正确的口令,是无法把私钥还原出来的.</p>
<p>&nbsp;&nbsp;&nbsp; 保存证书和保存私钥类似.Certificate对象中也有一个getEncoded的方法.</p>
&nbsp;&nbsp;&nbsp; 这次就讲这些.大家应该可以把这些安全对象很熟练地从文件系统和内存之间来回地折腾了吧.这对以后实现CA是很重要的.下次我会讲一下证书中表示主体的方法:DN.
<img src ="http://www.blogjava.net/libin2722/aggbug/179839.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:11 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179839.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Java开发和信息安全相关的程序</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179838.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:10:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179838.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179838.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179838.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179838.html</trackback:ping><description><![CDATA[这里说的信息安全是相对于系统安全而言的,它更侧重于加密,解密,数字签名,验证,证书等等.而系统安全主要侧重于系统本身是否有安全漏洞,如常见的由于软件设计的不完善而导致的满天飞的缓冲区溢出等等.
<p>&nbsp;&nbsp;&nbsp; Java语言中负责加密功能的部件是JCE(Java Crypto
Extenstion),它使用开放式的思想,可以允许用户自己编写加密算法的具体实现的模块等.这些东西被称为JCE
Provider,JCE的提供者.SUN公司本身提供了一些Provider.不过我推荐使用Bouncy
Castle的Provider.原因是它实现的加密算法多,连比较新的椭圆曲线(ECC)算法都有了.去<a href="http://www.bouncycastle.org/">http://www.bouncycastle.org/</a>可
以找到你所希望的.Bouncy Castle除了提供Provider本身以外,还包括了一个S/MIME和一个open
pgp&nbsp;的jar包只有Provider本身是必要的,后两个包是方便你编程而提供的.例如有了S/MIME包后,你就不再需要为诸如"加密一个字符串或
者一片文章然后签名"之类的很现实的应用程序写上一大堆代码了,只要引用S/MIME包中的某几个类,很快就可以搞定.而open
pgp的存在,使你在用Java编写和PGP/GPG交互的程序时方便多了.</p>
<p>&nbsp;&nbsp;&nbsp; 这次先写这么多了,下次开始具体讲把这些东西搞下来后怎么开始干活吧.我以我现在手头上正在做的事情告诉大家,如何做一个CA.</p>
<p>&nbsp;&nbsp;&nbsp; 有了BC Provider,开CA,真的就是这么简单!</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:10 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中SSL证书认证通讯-Server</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179836.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:08:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179836.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179836.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179836.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179836.html</trackback:ping><description><![CDATA[<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">/**</span><span style="color: #008000;">******************************************************************<br />
&nbsp;*&nbsp;项目名称&nbsp;&nbsp;&nbsp;&nbsp;：rochoc&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;包名称&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;：rochoc.net.security&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;文件名称&nbsp;&nbsp;&nbsp;&nbsp;：SSLServer&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;编写者&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;LuckyStar&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;编写日期&nbsp;&nbsp;&nbsp;&nbsp;：2008-2-13&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;程序功能（类）描述&nbsp;：用于安全通讯的服务Socket，采用java中的SSLServerSocket&lt;p&gt;<br />
&nbsp;*<br />
&nbsp;*&nbsp;程序变更日期&nbsp;&nbsp;&nbsp;：<br />
&nbsp;*&nbsp;变更作者&nbsp;&nbsp;&nbsp;&nbsp;：<br />
&nbsp;*&nbsp;变更说明&nbsp;&nbsp;&nbsp;&nbsp;：<br />
*******************************************************************</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;rochoc.net.security;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.FileInputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.IOException;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.InputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.OutputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.net.Socket;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.security.KeyStore;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.security.SecureRandom;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.KeyManagerFactory;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.SSLContext;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.SSLServerSocket;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.TrustManagerFactory;<br />
<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;类名：SSLServer&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;类描述：安全通讯的服务端&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;编写者&nbsp;：luoc&lt;p&gt;<br />
&nbsp;*&nbsp;编写日期&nbsp;：2005-6-30&lt;p&gt;<br />
&nbsp;*&nbsp;主要public成员变量：&lt;p&gt;<br />
&nbsp;*&nbsp;主要public方法：&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SSLServer&nbsp;</span><span style="color: #0000ff;">implements</span><span style="color: #000000;">&nbsp;Runnable<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*构造函数说明：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*参数说明：&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;SSLServer()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法名称：init&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法功能：初始化服务Socket&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;参数说明：&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;返回：void&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;作者：luoc<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;日期：2005-6-30<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;init()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;type</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">TLS</span><span style="color: #000000;">"</span><span style="color: #000000;">;</span><span style="color: #008000;">//</span><span style="color: #008000;">类型</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;keyf</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">..\\key\\srvstore</span><span style="color: #000000;">"</span><span style="color: #000000;">;</span><span style="color: #008000;">//</span><span style="color: #008000;">key文件路径</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;trustf</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">..\\key\\mytrust</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;pass</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">123456</span><span style="color: #000000;">"</span><span style="color: #000000;">;</span><span style="color: #008000;">//</span><span style="color: #008000;">密码</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;port</span><span style="color: #000000;">=</span><span style="color: #000000;">2001</span><span style="color: #000000;">;</span><span style="color: #008000;">//</span><span style="color: #008000;">端口</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">初始化上下文</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SSLContext&nbsp;ctx</span><span style="color: #000000;">=</span><span style="color: #000000;">SSLContext.getInstance(type);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyManagerFactory&nbsp;kmf</span><span style="color: #000000;">=</span><span style="color: #000000;">KeyManagerFactory.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SunX509</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TrustManagerFactory&nbsp;tmf</span><span style="color: #000000;">=</span><span style="color: #000000;">TrustManagerFactory.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SunX509</span><span style="color: #000000;">"</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStore&nbsp;ks</span><span style="color: #000000;">=</span><span style="color: #000000;">KeyStore.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">JKS</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStore&nbsp;tks</span><span style="color: #000000;">=</span><span style="color: #000000;">KeyStore.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">JKS</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">载入keystore</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ks.load(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(keyf),pass.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tks.load(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(trustf),pass.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kmf.init(ks,pass.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmf.init(tks);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(),</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SecureRandom());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ss</span><span style="color: #000000;">=</span><span style="color: #000000;">(SSLServerSocket)ctx.getServerSocketFactory().createServerSocket(port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ss.setNeedClientAuth(</span><span style="color: #0000ff;">true</span><span style="color: #000000;">);</span><span style="color: #008000;">//</span><span style="color: #008000;">客户端要认证</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(Exception&nbsp;e)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法名称：newListener&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法功能：创建服务器监听&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;参数说明：&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;返回：void&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;作者：luoc<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;日期：2005-6-30<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">private</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;newListener()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Thread(</span><span style="color: #0000ff;">this</span><span style="color: #000000;">)).start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;重载方法：run&nbsp;处理客户端的请求&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;参阅：</span><span style="color: #808080;">@see</span><span style="color: #008000;">&nbsp;java.lang.Runnable#run()&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;参数说明：&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;run()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Socket&nbsp;socket</span><span style="color: #000000;">=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">accept&nbsp;a&nbsp;connection</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket</span><span style="color: #000000;">=</span><span style="color: #000000;">ss.accept();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(IOException&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Class&nbsp;Server&nbsp;died:&nbsp;</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">+</span><span style="color: #000000;">&nbsp;e.getMessage());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">create&nbsp;a&nbsp;new&nbsp;thread&nbsp;to&nbsp;accept&nbsp;the&nbsp;next&nbsp;connection</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;newListener();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">process&nbsp;connection</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out</span><span style="color: #000000;">=</span><span style="color: #000000;">socket.getOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in</span><span style="color: #000000;">=</span><span style="color: #000000;">socket.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">read&nbsp;data&nbsp;from&nbsp;client&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;buff[]</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;[</span><span style="color: #000000;">512</span><span style="color: #000000;">];&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;data[]</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;[</span><span style="color: #000000;">1024</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">buff&nbsp;len=</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">buff.length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;startpos</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">((len</span><span style="color: #000000;">=</span><span style="color: #000000;">in.read(buff))</span><span style="color: #000000;">!=-</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">读联欢数据&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(len</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&amp;&amp;</span><span style="color: #000000;">&nbsp;buff[</span><span style="color: #000000;">0</span><span style="color: #000000;">]</span><span style="color: #000000;">==</span><span style="color: #000000;">TranTool.DATA_END)</span><span style="color: #008000;">//</span><span style="color: #008000;">数据结束标志</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data</span><span style="color: #000000;">=</span><span style="color: #000000;">TranTool.byteDynExt(data,buff,len,startpos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">read&nbsp;len:</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">len</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;data:[</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String(buff,</span><span style="color: #000000;">0</span><span style="color: #000000;">,len)</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">]</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startpos</span><span style="color: #000000;">+=</span><span style="color: #000000;">len;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">recv&nbsp;from&nbsp;client:[</span><span style="color: #000000;">"</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String(data,</span><span style="color: #000000;">0</span><span style="color: #000000;">,startpos));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">]&nbsp;data&nbsp;end.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">send&nbsp;message&nbsp;to&nbsp;client</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write((startpos</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">&nbsp;data&nbsp;success&nbsp;receive.</span><span style="color: #000000;">"</span><span style="color: #000000;">).getBytes());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(TranTool.DATA_END);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">success&nbsp;echo&nbsp;is&nbsp;send.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.flush();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(IOException&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">finally</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">&nbsp;(IOException&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">全局变量</span><span style="color: #008000;">*/</span><span style="color: #000000;">&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;SSLServerSocket&nbsp;ss</span><span style="color: #000000;">=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">测试函数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String&nbsp;args[])<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">init&nbsp;SSLServer<img src="http://www.blogjava.net/Images/dot.gif"  alt="" /></span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SSLServer&nbsp;srv</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SSLServer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Thread(srv).start();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">SSLServer&nbsp;listener&nbsp;begin.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<img src ="http://www.blogjava.net/libin2722/aggbug/179836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:08 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中SSL证书认证通讯-Certification</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179834.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:07:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179834.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179834.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179834.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179834.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179834.html</trackback:ping><description><![CDATA[需要两套证书：
<p>　<span style="color: #4d4db3;">１、客户端（公钥、私钥）　2、服务端（公钥、私钥）</span></p>
<p>&nbsp;&nbsp;&nbsp; 服务端应用&#8216;服务端私钥&#8217;和&#8216;客户端公钥&#8217;与客户端通讯；客户端应用&#8216;客户端私钥&#8217;和&#8216;服务端公钥&#8217;与服务端通讯。</p>
<p><em>　<span style="background-color: #dddddd;">如下介绍证书生成（一套）：</span></em></p>
<p>　<span style="color: #ff9900;">１、用JDK的keytool生成密钥store</span></p>
<p>&nbsp;&nbsp;&nbsp; keytool -genkey -alias mykey -keystore srvstore</p>
<p>&nbsp;&nbsp;&nbsp; 输入密码（程序中密码为&#8216;123456&#8217;）和相应的证书信息</p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: #e6941a;">２、从srvstore中导出证书</span></p>
<p>&nbsp;&nbsp;&nbsp; keytool -export -alias mykey -file srvcert.crt -keystore srvstore</p>
<p>&nbsp;&nbsp;&nbsp; 输入刚才上面设置的密码</p>
<p>&nbsp;&nbsp;&nbsp; <span style="color: #dd9222;">３、将证书导到公钥中</span></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; keytool -import -alias mytrust -file srvcert.crt -keystore srvtrust</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 输入公钥的密码（程序中密码为&#8216;123456&#8217;）</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179834.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:07 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179834.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中SSL证书认证通讯-Client</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179833.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:05:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179833.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179833.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179833.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179833.html</trackback:ping><description><![CDATA[<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #008000;">/**</span><span style="color: #008000;">******************************************************************<br />
&nbsp;*&nbsp;项目名称&nbsp;&nbsp;&nbsp;&nbsp;：rochoc&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;包名称&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;：rochoc.net.security&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;文件名称&nbsp;&nbsp;&nbsp;&nbsp;：SSLClient&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;编写者&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;：LuckyStar&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;编写日期&nbsp;&nbsp;&nbsp;&nbsp;：2008-2-13&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;程序功能（类）描述&nbsp;：安全通讯的客户端&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*<br />
&nbsp;*&nbsp;程序变更日期&nbsp;&nbsp;&nbsp;：<br />
&nbsp;*&nbsp;变更作者&nbsp;&nbsp;&nbsp;&nbsp;：<br />
&nbsp;*&nbsp;变更说明&nbsp;&nbsp;&nbsp;&nbsp;：<br />
*******************************************************************</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
</span><span style="color: #0000ff;">package</span><span style="color: #000000;">&nbsp;rochoc.net.security;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.FileInputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.IOException;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.InputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.io.OutputStream;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.security.KeyStore;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;java.security.SecureRandom;<br />
<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.KeyManagerFactory;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.SSLContext;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.SSLSocket;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.SSLSocketFactory;<br />
</span><span style="color: #0000ff;">import</span><span style="color: #000000;">&nbsp;javax.net.ssl.TrustManagerFactory;<br />
<br />
</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;*&nbsp;类名：SSLClient&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*&nbsp;类描述：&nbsp;安全通讯的客户端&lt;p&gt;<br />
&nbsp;*&nbsp;编写者&nbsp;：luoc&lt;p&gt;<br />
&nbsp;*&nbsp;编写日期&nbsp;：2005-6-30&lt;p&gt;<br />
&nbsp;*&nbsp;主要public成员变量：&lt;p&gt;<br />
&nbsp;*&nbsp;主要public方法：&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
<br />
</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;SSLClient<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*构造函数说明：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*参数说明：&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;SSLClient()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;init();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法名称：init&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法功能：初始化客户端Socket&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;参数说明：&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;返回：void&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;作者：luoc<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;日期：2005-6-30<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;init()<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">server&nbsp;socket's&nbsp;ip&nbsp;and&nbsp;port</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;host</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">localhost</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;port</span><span style="color: #000000;">=</span><span style="color: #000000;">2001</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">keystore&nbsp;path&nbsp;and&nbsp;password</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;keyf</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">..\\key\\mystore</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;trustf</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">..\\key\\srvtrust</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;pass</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">123456</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">set&nbsp;up&nbsp;a&nbsp;connection</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SSLSocketFactory&nbsp;ssf</span><span style="color: #000000;">=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">init&nbsp;context</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SSLContext&nbsp;ctx</span><span style="color: #000000;">=</span><span style="color: #000000;">SSLContext.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">TLS</span><span style="color: #000000;">"</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyManagerFactory&nbsp;kmf</span><span style="color: #000000;">=</span><span style="color: #000000;">KeyManagerFactory.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SunX509</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TrustManagerFactory&nbsp;tmf</span><span style="color: #000000;">=</span><span style="color: #000000;">TrustManagerFactory.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">SunX509</span><span style="color: #000000;">"</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStore&nbsp;ks</span><span style="color: #000000;">=</span><span style="color: #000000;">KeyStore.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">JKS</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;KeyStore&nbsp;tks</span><span style="color: #000000;">=</span><span style="color: #000000;">KeyStore.getInstance(</span><span style="color: #000000;">"</span><span style="color: #000000;">JKS</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">load&nbsp;keystore</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ks.load(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(keyf),pass.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tks.load(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;FileInputStream(trustf),pass.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;kmf.init(ks,pass.toCharArray());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmf.init(tks);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(),</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SecureRandom());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">load&nbsp;keystore&nbsp;success.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ssf</span><span style="color: #000000;">=</span><span style="color: #000000;">ctx.getSocketFactory();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">create&nbsp;socket</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket</span><span style="color: #000000;">=</span><span style="color: #000000;">(SSLSocket)ssf.createSocket(host,port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">create&nbsp;socket&nbsp;success.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">handshake</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.startHandshake();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">handshake&nbsp;success.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(Exception&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">establish&nbsp;connection&nbsp;error.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/**</span><span style="color: #008000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法名称：sendMessage&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法功能：发送信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;参数说明：</span><span style="color: #808080;">@param</span><span style="color: #008000;">&nbsp;msg&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;返回：void&nbsp;&lt;p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;作者：luoc<br />
&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;日期：2005-6-30<br />
&nbsp;&nbsp;&nbsp;&nbsp;*</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;sendMessage(String&nbsp;msg)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out</span><span style="color: #000000;">=</span><span style="color: #000000;">socket.getOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in</span><span style="color: #000000;">=</span><span style="color: #000000;">socket.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">send&nbsp;message</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">send&nbsp;message:[</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">msg</span><span style="color: #000000;">+</span><span style="color: #000000;">"</span><span style="color: #000000;">]</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(msg.getBytes());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(TranTool.DATA_END);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.flush();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">receive&nbsp;message</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">&nbsp;[]&nbsp;buff</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">byte</span><span style="color: #000000;">[</span><span style="color: #000000;">1024</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">recv&nbsp;len:</span><span style="color: #000000;">"</span><span style="color: #000000;">+</span><span style="color: #000000;">(len</span><span style="color: #000000;">=</span><span style="color: #000000;">in.read(buff)));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">receive&nbsp;from&nbsp;srv:[</span><span style="color: #000000;">"</span><span style="color: #000000;">);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;String(buff,</span><span style="color: #000000;">0</span><span style="color: #000000;">,len));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">]&nbsp;receive&nbsp;end.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(IOException&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">finally</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">try</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;socket.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">catch</span><span style="color: #000000;">(Exception&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">/*</span><span style="color: #008000;">全局变量</span><span style="color: #008000;">*/</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;SSLSocket&nbsp;socket</span><span style="color: #000000;">=</span><span style="color: #0000ff;">null</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">测试函数</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">public</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">static</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;main(String&nbsp;args[])<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SSLClient&nbsp;sc</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;SSLClient();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;msg</span><span style="color: #000000;">=</span><span style="color: #000000;">"</span><span style="color: #000000;">Hello&nbsp;SSL&nbsp;Server.</span><span style="color: #000000;">"</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(args.length</span><span style="color: #000000;">==</span><span style="color: #000000;">1</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg</span><span style="color: #000000;">=</span><span style="color: #000000;">args[</span><span style="color: #000000;">0</span><span style="color: #000000;">];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff;">else</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="color: #000000;">"</span><span style="color: #000000;">Useage:Please&nbsp;input&nbsp;the&nbsp;message&nbsp;you&nbsp;want&nbsp;to&nbsp;send.</span><span style="color: #000000;">"</span><span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sc.sendMessage(msg);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></div>
<img src ="http://www.blogjava.net/libin2722/aggbug/179833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:05 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5SSL_ServerAndClient 的配置实例</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179832.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:03:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179832.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179832.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179832.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179832.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179832.html</trackback:ping><description><![CDATA[<p>本文演示了在产生服务器端和客户端证书之后, 如何在 Tomcat 5.5 上进行双向 SSL 的配置.<br />
<br />
关于如何产生证书, 请参考 <a href="http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Tomcat5SSL_ServerAndClient</span></strong></a>.<br />
<br />
首先, 到 <a style="border-bottom: 1px dotted;" href="http://tomcat.apache.org/"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://tomcat.apache.org</span></strong></a> 下载 Tomcat 5.5 的最新版本, 我下载的是 Tomcat 5.5.15 的 tar.gz 方式发布版本, 解压缩到一个目录(本文中是解压缩在 C:"TEMP"ssl 目录下).<br />
</p>
<hr />
<strong>说明:</strong> 本文所使用的例子可以在这里下载(使用右键菜单"目标另存为...")
<ul>
    <li><a href="http://thinkbase.net/w/main/Wiki/5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.tomcat5.5-ssl-sample.zip?action=action_view_attachment&amp;attachment=Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.tomcat5.5-ssl-sample.zip" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">att:Tomcat5SSL_ServerAndClient 在 Tomcat 5.5 上的配置实例.tomcat5.5-ssl-sample.zip</span></strong></a></li>
</ul>
<strong><span style="color: #32328c; font-family: Trebuchet MS;">
<hr />
</span></strong>下面开始进行配置:<br />
<h2>第一步: 将服务器端证书 ssl-test.net-tomcat.keystore 复制到 Tomcat 的 conf 目录中</h2>
<ul>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.001.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="386" width="500"  alt="" /></li>
</ul>
<h2>第二步: 修改 Tomcat 的 conf 目录下 server.xml 文件, 加上 SSL Connector 的定义</h2>
<ul>
    <li><strong>注意:</strong> 如果需要使用双向 SSL(即客户端也要求使用证书), 那么必须设置 clientAuth="true";
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.002.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="309" width="500"  alt="" />
    </li>
    <li>顺便把 HTTP Connector 的 URLEncoding 也设置成 UTF-8, 这个主要是为了解决一些中文问题(与本试验无关, 你也可以不配置):
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.003.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="276" width="500"  alt="" /></li>
</ul>
<h2>第三步: 在 Tomcat 的 webapps 目录下建立一个新的 Web 应用 "ssltest", 编辑 ssltest 目录下 WEB-INF/web.xml, 配置 ssltest/ssl/ 目录下的内容为必须通过 SSL 方式才能访问</h2>
<ul>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.004.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="336" width="500"  alt="" /></li>
</ul>
<h2>第四步: 写两个完全一样的测试页面, 分别放在 ssltest/ 和 ssltest/ssl/ 目录下, 按照上一步的配置, ssltest/ssl/ 目录下的测试页面必须通过 SSL 方式才能访问</h2>
<ul>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.005.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="261" width="500"  alt="" /></li>
</ul>
<h2>第五步: 导入客户端证书到浏览器中(双击客户端证书文件 "web-client.p12" 即可导入 IE)</h2>
<ul>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.006-1.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="356" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.006-2.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="356" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.006-3.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="356" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.006-4.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="356" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.006-5.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="356" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.006-6.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.007.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="356" width="500"  alt="" /></li>
</ul>
<h2>实际运行效果</h2>
配置完毕后, 启动 Tomcat, 可以看到 <a style="border-bottom: 1px dotted;" href="http://localhost:8080/ssltest/test.jsp"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://localhost:8080/ssltest/test.jsp</span></strong></a> 能够使用普通的 HTTP 方式访问, 而通过 <a style="border-bottom: 1px dotted;" href="http://localhost:8080/ssltest/ssl/test.jsp"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://localhost:8080/ssltest/ssl/test.jsp</span></strong></a> 对 ssltest/ssl 目录下内容的访问则会自动切换到 <a style="border-bottom: 1px dotted;" href="https://localhost:8443/"><strong><span style="color: #32328c; font-family: Trebuchet MS;">https://localhost:8443</span></strong></a> 上去了; 同时可以看到, 使用 HTTPS 方式访问时, 客户端证书的 Subject 可以被 jsp 页面获得:
<ul>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.008.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="216" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.009.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="216" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.009-firefox.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="159" width="500"  alt="" /></li>
</ul>
试着在浏览器里面把导入的证书删除, 你会发现 ssltest/ssl 目录下的内容已经不能访问了:
<ul>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.010.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="216" width="500"  alt="" />
    </li>
    <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=+Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.010-firefox.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" height="159" width="500"  alt="" /></li>
</ul>
<h2>相关下载</h2>
本文所涉及的文件可以在下列地址下载:
<ul>
    <li><a href="http://thinkbase.net/w/main/Wiki/5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.tomcat5.5-ssl-sample.zip?action=action_view_attachment&amp;attachment=Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B.tomcat5.5-ssl-sample.zip" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">att:Tomcat5SSL_ServerAndClient 在 Tomcat 5.5 上的配置实例.tomcat5.5-ssl-sample.zip</span></strong></a></li>
</ul>
<img src ="http://www.blogjava.net/libin2722/aggbug/179832.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:03 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179832.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5SSL_ServerAndClient</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179831.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 13:59:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179831.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179831.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179831.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179831.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179831.html</trackback:ping><description><![CDATA[<h2>配置适用于正式使用环境下的Tomcat Web服务器双向SSL认证</h2>
<br />
关于如何使用Tomcat服务器实现双向SSL认证的文章很早就有了, 比较实用的文章可以看看 <a href="http://thinkbase.net/w/main/Wiki?IBM++developerWorks+%E4%B8%AD%E5%9B%BD%E7%BD%91%E7%AB%99+2002%E5%B9%B45%E6%9C%88+%E9%85%8D%E7%BD%AETomcat+4%E4%BD%BF%E7%94%A8SSL"><strong><span style="color: #32328c; font-family: Trebuchet MS;">IBM developerWorks 中国网站 2002年5月 配置Tomcat 4使用SSL</span></strong></a>( <a style="border-bottom: 1px dotted;" href="http://www-900.ibm.com/developerWorks/cn/security/se-tcssl/index.shtml"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://www-900.ibm.com/developerWorks/cn/security/se-tcssl/index.shtml</span></strong></a> ), 使用 google 还可以搜索到很多类似的文章.<br />
<br />
但
是现在看来, 这些文章也有不足之处, 一是只说明了在 Tomcat 4 服务器上的配置方法, 与现在普遍使用的 Tomcat 5
系列的配置方法有一定的差异, 其次, 这些文章中的方法大多是作为一种实验性的操作介绍, 如果用于实际Web服务器的产生证书环境,
还是会存在一些问题的:
<ul>
    <li>生成的CA私钥(ca-key.pem)以及自签名根证书(ca-cert.pem)均为没有加密的明文, 由于一旦在服务器发布,
    以及客户端证书发布之后, 根证书是不能随便修改的,
    那么在保管没有加密的CA私钥以及自签名根证书时就会存在安全性问题(如果别人得到你的CA根证书, 他就可以替你生成客户端证书了); </li>
    <li>生成的服务器端证书(server_keystore)不包括信任的CA根证书,
    信任的CA根证书被导入到JSSE的默认位置, 如果进行证书操作的计算机和真正运行Web应用的不是同一台计算机, 那么在安装服务器端证书的时候,
    还需要在服务器上将CA根证书导入JSSE默认位置; </li>
    <li>生成客户端证书的过程比较烦琐, 不方便批量进行客户端证书的生成;
    </li>
    <li>没有统一的配置文件, 生成证书的过程中需要执行相当多的命令, 可重复性差, 出错的可能性比较大.</li>
</ul>
针对以上的问题, 在参考"配置Tomcat 4使用SSL"这篇文章的基础上, 整理出由4个批处理命令和一个配置文件组成的证书工具包, 这个工具包考虑到在实际Web服务器环境下产生证书的需求, 克服了上面提到的那些问题.<br />
<h3>用到的软件包</h3>
<ul>
    <li>Tomcat 5.0.x
    </li>
    <li>JSSE 中的 keytool 工具, 在 JDK 1.4 中已经自带了这个工具, 因此, 只需要安装 JDK1.4.x 即可
    </li>
    <li>openssl(openssl 已经被包含在这个工具包里面了, 不需要另外安装, 参见<a href="http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient#download"><strong><span style="color: #32328c; font-family: Trebuchet MS;">工具包下载</span></strong></a>)
    </li>
    <li>cygwin 的 sed 和 echo 命令(这些命令文件已经包含在工具包里面, 不需要另外安装, 参见<a href="http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient#download"><strong><span style="color: #32328c; font-family: Trebuchet MS;">工具包下载</span></strong></a>)</li>
</ul>
<h3>配置及主要命令介绍</h3>
<ul>
    <li><strong>PATH 环境变量</strong>
    <ul>
        <li>安装 JDK 之后, 需要将环境变量 JAVA_HOME 设置为 JDK 的安装目录, 同时在 PATH 中加上 %JAVA_HOME%"bin.</li>
    </ul>
    </li>
    <li><strong>工具包结构</strong>
    <ul>
        <li><strong>.bin</strong>: 存放openssl 以及 cygwin 的 sed 和 echo 命令的可执行执行文件;
        </li>
        <li><strong>.etc</strong>: 存放系统的配置文件, 其中最主要的配置文件是 .etc/config.cmd;
        </li>
        <li><strong>dist</strong>: 这个目录存放产生的各种证书;
        </li>
        <li><strong>work</strong>: 产生证书时使用的临时文件的存放目录, <strong>为了安全起见, 在每次证书相关操作结束后, 建议清空这个目录</strong>;
        </li>
        <li><strong>step0,1,2,3 四个批处理命令</strong>: 这四个命令分别用于证书各个方面的操作.</li>
    </ul>
    </li>
    <li><strong>.etc/config.cmd</strong>
    <ul>
        <li>这个文件是系统的配置文件, 主要配置 CA根证书/服务器证书/客户端证书 的相关信息, 例如证书的distinguished name信息等等, 在生成证书之前, 需要首先根据实际情况更新这个配置文件;</li>
    </ul>
    </li>
    <li><strong>step0-ca-pfx.bat</strong>
    <ul>
        <li>该命令生成CA私钥以及自签名根证书, 最后得到PKCS12格式的CA根证书(PKCS12格式的CA根证书受密码保护, 因此有比较好的安全性);
        </li>
        <li>生成的PKCS12格式的CA根证书保存在 dist"ca-cert 目录下, 在正式使用的系统中,
        这个证书文件(*.pfx)需要妥善保存, 因为以后的服务器证书和客户端证书都需要依赖这个证书, 尤其是客户端证书, 如果丢失了CA根证书,
        就无法发布新的客户端证书了, 而重新生成CA根证书, 则需要重新生成服务器证书和客户端证书, 在客户端用户较多的情况下,
        重新发布所有的客户端证书是有相当大的工作量; </li>
        <li>在执行这个命令的过程中, 会提示输入证书保护密码, 请注意不要遗忘或者泄漏这个密码, 否则根证书的安全会受到威胁.</li>
    </ul>
    </li>
    <li><strong>step1-ca-prepare.bat</strong>
    <ul>
        <li>该命令用于从PKCS12格式的CA根证书中导出CA私钥和未加密CA根证书;
        </li>
        <li>由于安全原因, CA根证书平时以密码保护的PKCS12格式文件(*.pfx)存放, 那么如果需要使用CA根证书来发布服务器证书或者客户端证书时, 首先需要执行这个命令得到CA根证书的未加密形式;
        </li>
        <li>在执行这个命令的过程中, 会出现两次提示输入根证书的保护密码, 如果密码不正确, 这个命令将不能执行成功, 也就无法进行下面两步的发布证书的操作了.</li>
    </ul>
    </li>
    <li><strong>step2-server.bat</strong>
    <ul>
        <li>该命令用于生成服务器端证书(keystore文件);
        </li>
        <li>注意: CA根证书同时也会被导入到证书的keystore文件中, 这样在将这个证书应用到Tomcat Web服务器上的时候就不需要将CA根证书导入到JSSE的默认位置了;
        </li>
        <li>这个命令必须在执行 step1-ca-prepare.bat 之后才能正常运行.</li>
    </ul>
    </li>
    <li><strong>step3-client.bat</strong>
    <ul>
        <li>这个命令用于发布客户端证书;
        </li>
        <li>为了便于批量生成客户端证书, 这个命令支持命令行参数, 第1到3个参数依次为:
        <ul>
            <li>客户端证书的名称(Common Name)
            </li>
            <li>客户端证书所属的组织(Organizational Unit Name)
            </li>
            <li>产生的PKS12格式客户端证书的导入密码, 这个密码可以保护证书只能被知道密码的用户导入到浏览器</li>
        </ul>
        </li>
        <li>这个命令必须在执行 step1-ca-prepare.bat 之后才能正常运行.</li>
    </ul>
    </li>
</ul>
<strong>说明:</strong>当Web
服务器开始正式运行以后, step0-ca-pfx.bat 命令是不能再次执行的, 如果需要重新发布服务器证书, 或者发布新的客户端证书,
在执行 step2-server.bat 和 step3-client.bat 命令前, 可以通过 step1-ca-prepare.bat
重新从保存的PKCS12格式CA根证书中导出CA私钥和未加密CA根证书.<br />
<br />
<h3>Tomcat 5 服务器配置</h3>
参考配置方法如下:
<ul>
    <li>将 "step2-server.bat" 命令产生的 dist"server 目录下的 keystore
    文件(如果使用本工具包的默认配置, 这个文件叫做"ssl-test.net-tomcat.keystore")复制到 Tomcat 安装目录的
    conf 目录下; </li>
    <li>修改 Tomcat 安装目录的 conf 目录下的 "server.xml" 文件, 修改 &lt;Service name="Catalina"&gt; 包含的 "Connector" 元素, 示例如下(仅供参考):</li>
</ul>
<pre>  &lt;Service name="Catalina"&gt;<br />
&lt;Connector URIEncoding="UTF-8"<br />
acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true"<br />
port="8080" redirectPort="8443"<br />
maxSpareThreads="75" maxThreads="150" minSpareThreads="25"&gt;<br />
&lt;/Connector&gt;<br />
&lt;Connector URIEncoding="UTF-8" port="8443"<br />
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br />
enableLookups="false" disableUploadTimeout="true"<br />
acceptCount="100" debug="0" scheme="https" secure="true"<br />
clientAuth="true" sslProtocol="TLS"<br />
keystoreFile="${catalina.home}/conf/ssl-test.net-tomcat.keystore"<br />
keystorePass="openssl"<br />
truststoreFile="${catalina.home}/conf/ssl-test.net-tomcat.keystore"<br />
truststorePass="openssl"/&gt;<br />
......</pre>
<h3>启用双向 SSL 时 Web 应用程序的配置</h3>
<ul>
    <li>要启用双向 SSL 认证, 在 Web 应用程序的 web.xml 中需要如下增加一些配置: <code>auth-method=CLIENT-CERT</code> 说明是"以客户端数字证书来确认用户的身份", <code>transport-guarantee=CONFIDENTIAL</code> 表示应用程序要求数据必须在一种"防止其他实体看到传输的内容的方式中传送".</li>
</ul>
<pre>    &lt;login-config&gt;<br />
&lt;!-- Authorization setting for SSL --&gt;<br />
&lt;auth-method&gt;CLIENT-CERT&lt;/auth-method&gt;<br />
&lt;realm-name&gt;Client Cert Users-only Area&lt;/realm-name&gt;<br />
&lt;/login-config&gt;<br />
&lt;security-constraint&gt;<br />
&lt;!-- Authorization setting for SSL --&gt;<br />
&lt;web-resource-collection &gt;<br />
&lt;web-resource-name &gt;SSL&lt;/web-resource-name&gt;<br />
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />
&lt;/web-resource-collection&gt;<br />
&lt;user-data-constraint&gt;<br />
&lt;transport-guarantee&gt;CONFIDENTIAL&lt;/transport-guarantee&gt;<br />
&lt;/user-data-constraint&gt;<br />
&lt;/security-constraint&gt;</pre>
<ul>
    <li>经过以上的配置之后, 那么即使用户是通过 http 访问 Web 应用程序的, 浏览器也会自动切换到 https 方式并弹出选择客户端证书的对话框.</li>
</ul>
<h3>如何使用客户端证书进行用户验证</h3>
<ul>
    <li>查看一些资料上提到客户端证书内容中 subject 的 CN 部分可以和 Tomcat 的 Realm 中的用户集成, 不过一直没有尝试成功;
    </li>
    <li>在 web 应用程序中, 可以通过 java 代码从 request 对象中获得, 根据 Servlet Specifications, 使用<code>request.getAttribute("javax.servlet.request.X509Certificate")</code> 就可以得到 https 请求的客户端证书链信息, 其中第一个元素就是客户端证书, 相应的示例代码如下:</li>
</ul>
<div>
<table align="center" bgcolor="#ffffff" border="2" cellpadding="3" cellspacing="0">
    <tbody>
        <tr>
            <td align="left" nowrap="nowrap" valign="top"><code><span style="font-size: 10pt;"><span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">String&nbsp;certSubject&nbsp;=&nbsp;</span><span style="color: #0000c0;"><strong>null</strong></span><span style="color: #000000;">;</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">X509Certificate</span><span style="color: #000000;">[]&nbsp;</span><span style="color: #000000;">certChain=</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">(</span><span style="color: #000000;">X509Certificate</span><span style="color: #000000;">[])</span><span style="color: #000000;">request.getAttribute</span><span style="color: #000000;">(</span><span style="color: #990000;">"javax.servlet.request.X509Certificate"</span><span style="color: #000000;">)</span><span style="color: #000000;">;</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #c00000;"><strong>int&nbsp;</strong></span><span style="color: #000000;">len=certChain.length;</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000c0;"><strong>if&nbsp;</strong></span><span style="color: #000000;">(</span><span style="color: #000000;">len&gt;</span><span style="color: #990000;">0</span><span style="color: #000000;">){</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">X509Certificate&nbsp;cert&nbsp;=&nbsp;</span><span style="color: #000000;">(</span><span style="color: #000000;">X509Certificate</span><span style="color: #000000;">)</span><span style="color: #000000;">certChain</span><span style="color: #000000;">[</span><span style="color: #990000;">0</span><span style="color: #000000;">]</span><span style="color: #000000;">;</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">Principal&nbsp;pSubject&nbsp;=&nbsp;cert.getSubjectDN</span><span style="color: #000000;">()</span><span style="color: #000000;">;</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">certSubject&nbsp;=&nbsp;pSubject.getName</span><span style="color: #000000;">()</span><span style="color: #000000;">;</span><br />
            <span style="color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000;">}</span></span></code> </td>
            <br />
            <ul>
                <li>客户端证书的 subject 是类似 <code>CN=client, OU=web, O=ssl-test.net, L=your_locality, ST=your_province, C=CN</code> 这样的字符串, 其中 CN=... 就是客户端证书的用户名称, Web 应用程序可以通过这个字段来验证 https 请求对应的用户身份了.</li>
            </ul>
            <br />
            <h3>工具包下载</h3>
            <ul>
                <li><a href="http://thinkbase.net/release/tomcat-ca.20050118.zip"><strong><span style="color: #32328c; font-family: Trebuchet MS;">tomcat-ca.20050118.zip</span></strong></a>, 4,202,211字节, MD5: 5495e6cede88f14fe87e93734dbd36da</li>
            </ul>
            <h3>运行界面(使用 Mozilla Firefox 1.0)</h3>
            <ul>
                <li>没有安装证书时访问 Web 应用程序被服务器拒绝<br />
                <img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=Tomcat5SSL_ServerAndClient.No-CA.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" />
                </li>
                <li>访问 Web 应用程序时提示选择证书的对话框<br />
                <img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&amp;attachment=Tomcat5SSL_ServerAndClient.Select-CA.png" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" /></li>
            </ul>
            <hr />
            比较复杂的问题, 请到 <a href="http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient+%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Tomcat5SSL_ServerAndClient 常见问题</span></strong></a> 页面讨论.<br />
            <br />
            例子请看
            <ul>
                <li><a href="http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+5.5+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Tomcat5SSL_ServerAndClient 在 Tomcat 5.5 上的配置实例</span></strong></a> ;
                </li>
                <li><a href="http://thinkbase.net/w/main/Wiki?Tomcat5SSL_ServerAndClient+%E5%9C%A8+Tomcat+4.1.31+%E4%B8%8A%E7%9A%84%E9%85%8D%E7%BD%AE%E5%AE%9E%E4%BE%8B"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Tomcat5SSL_ServerAndClient 在 Tomcat 4.1.31 上的配置实例</span></strong></a></li>
            </ul>
        </tr>
    </tbody>
</table>
</div>
<img src ="http://www.blogjava.net/libin2722/aggbug/179831.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 21:59 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179831.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>配置Tomcat 4使用SSL</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179828.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 13:53:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179828.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179828.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179828.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179828.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179828.html</trackback:ping><description><![CDATA[<blockquote>目前介绍配置Tomcat
4使用单向SSL认证(只验证服务器证书)的资料很多，过程也比较简单。但是由于配置其使用双向SSL认证(还需要验证客户端个人证书)除了需要CA对证
书签名外，还要从CA获得个人证书。有关这一问题，目前结合具体web服务器来讲解如何操作的资料很少。作者通过摸索借助一些SSL工具在本地实现了简单
的CA功能，并在此基础上配置成功了Tomcat的双向认证，希望能把其中的一些经验与大家共享。不过受本人水平所限，文中难免会有错误与不当之处，敬请
大家谅解。</blockquote>
<p><a name="1"><strong><span style="color: #32328c; font-family: Trebuchet MS;">1．Tomcat简介</span></strong></a> <br />
Tomcat
是Apache
Jakarta的子项目之一，作为一个优秀的开源web应用服务器，全面支持jsp1.2以及servlet2.3规范。因其技术先进、性能稳定，而且免
费，因而深受Java爱好者的喜爱并得到了部分软件开发商的认可，成为目前比较流行的web应用服务器。</p>
<p><a name="2"><strong><span style="color: #32328c; font-family: Trebuchet MS;">2．SSL(Server Socket Layer)简介</span></strong></a> <br />
在
网络上信息在源-宿的传递过程中会经过其它的计算机。一般情况下，中间的计算机不会监听路过的信息。但在使用网上银行或者进行信用卡交易的时候有可能被监
视，从而导致个人隐私的泄露。由于Internet和Intranet体系结构的原因，总有某些人能够读取并替换用户发出的信息。随着网上支付的不断发
展，人们对信息安全的要求越来越高。因此Netscape公司提出了SSL协议，旨在达到在开放网络(Internet)上安全保密地传输信息的目的，这
种协议在WEB上获得了广泛的应用。之后IETF(www.ietf.org)对SSL作了标准化，即RFC2246，并将其称为TLS
（Transport Layer Security），从技术上讲，TLS1.0与SSL3.0的差别非常微小。 </p>
<p><a name="3"><strong><span style="color: #32328c; font-family: Trebuchet MS;">3．SSL工作原理</span></strong></a> <br />
SSL协议使用不对称加密技术实现会话双方之间信息的安全传递。可以实现信息传递的保密性、完整性，并且会话双方能鉴别对方身份。不同于常用的http协议，我们在与网站建立SSL安全连接时使用https协议，即采用https://ip:port/的方式来访问。</p>
<p>当我们与一个网站建立https连接时，我们的浏览器与Web Server之间要经过一个握手的过程来完成身份鉴定与密钥交换，从而建立安全连接。具体过程如下： </p>
<ol>
    <li>用户浏览器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送到服务器。
    </li>
    <li>服务器将其SSL版本号、加密设置参数、与session有关的数据以及其它一些必要信息发送给浏览器，同时发给浏览器的还有服务器的证书。如果配置服务器的SSL需要验证用户身份，还要发出请求要求浏览器提供用户证书。
    </li>
    <li>客户端检查服务器证书，如果检查失败，提示不能建立SSL连接。如果成功，那么继续。
    </li>
    <li>客户端浏览器为本次会话生成pre-master secret，并将其用服务器公钥加密后发送给服务器。
    </li>
    <li>如果服务器要求鉴别客户身份，客户端还要再对另外一些数据签名后并将其与客户端证书一起发送给服务器。
    </li>
    <li>如果服务器要求鉴别客户身份，则检查签署客户证书的CA是否可信。如果不在信任列表中，结束本次会话。如果检查通过，服务器用自己的私钥解密收到的pre-master secret，并用它通过某些算法生成本次会话的master secret。
    </li>
    <li>客户端与服务器均使用此master secret生成本次会话的会话密钥(对称密钥)。在双方SSL握手结束后传递任何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运算量低一个数量级以上，能够显著提高双方会话时的运算速度。
    </li>
    <li>客户端通知服务器此后发送的消息都使用这个会话密钥进行加密。并通知服务器客户端已经完成本次SSL握手。
    </li>
    <li>服务器通知客户端此后发送的消息都使用这个会话密钥进行加密。并通知客户端服务器已经完成本次SSL握手。
    </li>
    <li>本次握手过程结束，会话已经建立。双方使用同一个会话密钥分别对发送以及接受的信息进行加、解密。</li>
</ol>
<p><a name="4"><strong><span style="color: #32328c; font-family: Trebuchet MS;">4．配置Tomcat 4.x 使用SSL</span></strong></a></p>
<p><strong>4.1 用到的软件包</strong> <br />
</p>
<ul>
    <li>Tomcat 4.0.2<br />
    用途：Web Server。<br />
    下载：<a style="border-bottom: 1px dotted;" href="http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.3/bin/" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.3/bin/</span></strong></a>
    </li>
    <li>JSSE 1.0,2<br />
    用途：用来产生Tocmcat使用的秘钥对(keystore)。<br />
    下载： <a style="border-bottom: 1px dotted;" href="http://java.sun.com/products/jsse/" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://java.sun.com/products/jsse/</span></strong></a>
    </li>
    <li>Openssl 0.9.9.6<br />
    用途：用来产生CA证书、签名并生成IE可导入的PKCS#12格式私钥。<br />
    下载：<a style="border-bottom: 1px dotted;" href="http://www.openssl.org/" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">http://www.openssl.org/</span></strong></a></li>
</ul>
<p>以上工具的安装过程可以参考自带的帮助，本文就不再详细描述了。</p>
<p><strong>4.2 建立自己的CA</strong></p>
<p><strong>4.2.1 建立工作目录</strong> <br />
<code>mkdir ca</code></p>
<p><strong>4.2.2 生成CA私钥以及自签名根证书</strong> <br />
<strong>4.2.2.1 生成CA私钥</strong> <br />
<code>openssl genrsa -out ca"ca-key.pem 1024</code></p>
<p><strong>4.2.2.2 生成待签名证书</strong> <br />
<code>openssl req -new -out ca"ca-req.csr -key ca"ca-key.pem</code></p>
<p><strong>4.2.2.3 用CA私钥进行自签名</strong> <br />
<code>openssl x509 -req -in ca"ca-req.csr -out ca"ca-cert.pem -signkey ca"ca-key.pem -days 365</code></p>
<p><strong>4.3 设置Tomcat 4.x</strong> <br />
在本文中用符号"%JDK_HOME%"来表示JDK的安装位置，用符号"%TCAT_HOME%" 表示Tomcat的安装位置。</p>
<p><strong>4.3.1建立工作目录</strong> <br />
<code>mkdir server</code></p>
<p><strong>4.3.2 生成server端证书</strong> <br />
<strong>4.3.2.1 生成KeyPair</strong><br />
<code>%JDK_HOME%"bin"keytool
-genkey -alias tomcat_server -validity 365 -keyalg RSA -keysize 1024
-keypass changeit -storepass changeit -dname "cn=localhost,
ou=department, o=company, l=Beijing, st=Beijing, c=CN" -keystore
server"server_keystore</code></p>
<p><strong>4.3.2.2 生成待签名证书</strong><br />
<code>%JDK_HOME%"bin"keytool -certreq
-alias tomcat_server -sigalg MD5withRSA -file server"server.csr
-keypass changeit -keystore server"server_keystore -storepass changeit</code></p>
<p><strong>4.3.2.3 用CA私钥进行签名</strong><br />
<code>openssl x509 -req -in server"server.csr -out server"server-cert.pem -CA ca"ca-cert.pem -CAkey ca"ca-key.pem -days 365 </code></p>
<p><strong>4.3.2.4 导入信任的CA根证书到JSSE的默认位置(%JDK_ROOT %/jre/security/cacerts)</strong><br />
<code>%JDK_HOME%"bin"keytool
-import -v -trustcacerts -storepass changeit -alias my_ca_root -file
ca"ca-cert.pem -keystore %JDK_HOME%"jre"lib"security"cacerts </code></p>
<p><strong>4.3.2.5 把CA签名后的server端证书导入keystore</strong><br />
<code>%JDK_HOME%"bin"keytool
-import -v -trustcacerts -storepass changeit -alias tomcat_server -file
server"server-cert.pem -keystore server"server_keystore </code></p>
<p><strong>4.3.2.6 查看server端证书</strong><br />
<code>keytool -list -keystore %JDK_HOME%"jre"lib"security"cacerts<br />
keytool -list -keystore server"server_keystore </code></p>
<p><strong>4.3.3 修改server.xml使Tomcat支持SSL</strong><br />
首先找到以下内容，去掉对其的注释。然后参照红色部分修改。如果配置Tomcat不验证客户身份，可以设置clientAuth="false"。
<table bgcolor="#cccccc" border="1" cellpadding="0" cellspacing="0" width="100%">
    <tbody>
        <tr>
            <td>
            <pre>  &lt;Connector className="org.apache.catalina.connector.http.HttpConnector"<br />
            port="8443" minProcessors="5" maxProcessors="75"<br />
            enableLookups="true"<br />
            acceptCount="10" debug="0" scheme="https" secure="true"&gt;<br />
            &lt;Factory className="org.apache.catalina.net.SSLServerSocketFactory"<br />
            clientAuth="true" protocol="TLS"<br />
            keystoreFile="%TCAT_HOME%/conf/server_keystore" keystorePass="changeit"<br />
            /&gt;<br />
            &lt;/Connector&gt;</pre>
            </td>
        </tr>
    </tbody>
</table>
然后把文件server"server_keystore复制到目录%TCAT_HOME%"conf"下。</p>
<p><strong>4.4 在IE中安装个人证书</strong> <br />
<strong>4.4.1 建立工作目录</strong><br />
<code>mkdir client </code></p>
<p><strong>4.4.2 生成client私钥并用CA私钥签名</strong></p>
<p><strong>4.4.2.1 生成client私钥</strong><br />
<code>openssl genrsa -out client"client-key.pem 1024 </code></p>
<p><strong>4.4.2.2 生成待签名证书</strong><br />
<code>openssl req -new -out client"client-req.csr -key client"client-key.pem </code></p>
<p><strong>4.4.2.3 用CA私钥进行签名</strong><br />
<code>openssl x509 -req -in
client"client-req.csr -out client"client.crt -signkey
client"client-key.pem -CA ca"ca-cert.pem -CAkey ca"ca-key.pem
-CAcreateserial -days 365 </code></p>
<p><strong>4.4.2.4 生成client端的个人证书</strong><br />
因为JSSE1.0.2没有完全实现了对PKCS#12格式文件的操作(只能读取，不能输出)，所以在这里需要用openssl制作client端的个人证书(包含私钥)。<br />
<code>openssl pkcs12 -export -clcerts -in client"client.crt -inkey client"client-key.pem -out client"client.p12</code></p>
<p><strong>4.4.2.5 安装信任的根证书</strong><br />
把ca"ca-key.pem改名为ca"ca-key.cer，在client端的IE中使用"工具 ' Internet选项 ' 内容 ' 证书 ' 导入"把我们生成的CA根证书导入，使其成为用户信任的CA。</p>
<p><strong>4.4.3 安装个人证书</strong><br />
把client.p12导入到client端的IE中作为个人证书，导入过程同4.4.2.5。</p>
<p><strong>4.5 用IE浏览器使用SSL协议访问Tomcat</strong></p>
<p><strong>4.5.1 启动Tomcat 4.x</strong><br />
执行%TCAT_HOME%"bin"startup.bat启动Tomcat 4.x</p>
<p><strong>4.5.2 用IE访问Tomcat 4.x</strong><br />
在IE浏览器的地址栏中输入https://localhost:8443，如果前面的操作都正确的话，应该可以看到Tomcat的欢迎页面。同时状态栏上的小锁处于闭合状态，表示您已经成功地与服务器建立了要求客户端验证的SSL安全连接。</p>
<p><a name="5"><strong><span style="color: #32328c; font-family: Trebuchet MS;">5 结论</span></strong></a> <br />
以
上我们实现了为Tomcat 4.x配置要求客户端验证的SSL的全过程。对于其它类型的服务器，例如Apache，Netscape
Enterprise Server,
Websphere，Weblogic等，一般只是在服务器端保存证书的方式略有不同，但它们的原理都是类似的，配置时可以在本文中办法的基础上做出相应
的调整。</p>
<p><a name="resources"><span style="color: #32328c; font-family: Trebuchet MS;"><strong>参考资料</strong></span></a></p>
<ul>
    <li><a style="border-bottom: 1px dotted;" href="http://jakarta.apache.org/tomcat/tomcat-4.0-doc/ssl-howto.html" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Tomcat SSL Configuration HOW-TO</span></strong></a>
    </li>
    <li><a style="border-bottom: 1px dotted;" href="http://www.netscape.com/eng/ssl3/" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">SSL3.0规范</span></strong></a>
    </li>
    <li><a style="border-bottom: 1px dotted;" href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;q257591" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Deion of the Secure Sockets Layer (SSL) Handshake (Q257591)</span></strong></a>
    </li>
    <li><a style="border-bottom: 1px dotted;" href="http://java.sun.com/products/jdk/1.2/docs/tooldocs/solaris/keytool.html" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">keytool - Key and Certificate Management Tool</span></strong></a>
    </li>
    <li><a style="border-bottom: 1px dotted;" href="http://www.openssl.org/docs/apps/openssl.html" target="_blank"><strong><span style="color: #32328c; font-family: Trebuchet MS;">Openssl使用手册</span></strong></a> </li>
</ul>
<img src ="http://www.blogjava.net/libin2722/aggbug/179828.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 21:53 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179828.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>