??xml version="1.0" encoding="utf-8" standalone="yes"?>国产亚洲老熟女视频,亚洲国产精品一区二区九九,亚洲日韩一区精品射精http://m.tkk7.com/libin2722/category/29421.html快乐学习Q快乐工?/description>zh-cnWed, 13 Feb 2008 17:53:12 GMTWed, 13 Feb 2008 17:53:12 GMT60对google个性主늚拖拽效果的js的完整注释-1http://m.tkk7.com/libin2722/archive/2008/02/13/179851.htmlC物C物Wed, 13 Feb 2008 14:51:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179851.htmlhttp://m.tkk7.com/libin2722/comments/179851.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179851.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179851.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179851.html// 工具c,使用Util的命名空_方便理
var  Util  =   new  Object();
// 获取http header里面的UserAgentQ浏览器信息
Util.getUserAgent  =  navigator.userAgent;
// 是否是Gecko核心的BrowserQ比如Mozila、Firefox
Util.isGecko  =  Util.getUserAgent.indexOf( " Gecko " !=   - 1 ;
// 是否是Opera
Util.isOpera  =  Util.getUserAgent.indexOf( " Opera " !=   - 1 ;
// 获取一个element的offset信息Q其实就是相对于Body的padding以内的绝对坐?/span>
//
后面一个参数如果是true则获取offsetLeftQfalse则是offsetTop
//
关于offset、style、client{坐标的定义参考dindin的这个帖子:http://www.jroller.com/page/dindin/?anchor=pro_java_12
Util.getOffset  =    (el, isLeft) {
    
var  ret  =   0 ;
    
while  (el  !=   null ) {
        ret 
+=  el[ " offset "   +  (isLeft  ?   " Left "  :  " Top " )];
        el 
=  el.offsetParent;
    }
    
return  ret;
};
// 一个(参数中的funcName是这个fuction的名字)l定C个element上,q且以这个element的上下文q行Q其实是一U承,q个可以google些文章看?/span>
Util.bind  =    (el, fucName) {
    
return    () {
        
return  el[fucName].apply(el, arguments);
    };
};
// 重新计算所有的可以拖拽的element的坐标,对同一个column下面的可拖拽囑ֱ重新计算它们的高度而得出新的坐标,防止遮叠
//
计算出来的坐标记录在pagePosLeft和pagePosTop两个属性里?/span>
Util.re_calcOff  =    (el) {
    
for  ( var  i  =   0 ; i  <  Util.dragArray.length; i ++ ) {
        
var  ele  =  Util.dragArray[i];
        ele.elm.pagePosLeft 
=  Util.getOffset(ele.elm,  true );
        ele.elm.pagePosTop 
=  Util.getOffset(ele.elm,  false );
    }
    
var  nextSib  =  el.elm.nextSibling;
    
while  (nextSib) {
        nextSib.pagePosTop 
-=  el.elm.offsetHeight;
        nextSib 
=  nextSib.nextSibling;
    }
};

// 隐藏Google Ig中间那个tableQ也是拖拽的容器,配合show一般就是刷新用Q解决一些浏览器的怪癖
Util.hide  =    () {
    Util.rootElement.style.display 
=   " none " ;
};
// 昄Google Ig中间那个tableQ解释同?/span>
Util.show  =    () {
    Util.rootElement.style.display 
=   "" ;
};

// Ud时显C的占位虚线?/span>
ghostElement  =   null ;
// 获取q个虚线框,通过dom动态生?/span>
getGhostElement  =    () {
    
if  ( ! ghostElement) {
        ghostElement 
=  createElement( " DIV " );
        ghostElement.className 
=   " modbox " ;
        ghostElement.backgroundColor 
=   "" ;
        ghostElement.style.border 
=   " 2px dashed #aaa " ;
        ghostElement.innerHTML 
=   " &nbsp; " ;
    }
    
return  ghostElement;
};

// 初始化可以拖拽的Element的函敎ͼ与拖拽无关的我去掉了
  draggable(el) {
     // 公用的开始拖拽的函数
     this ._dragStart  =  start_Drag;
     // 公用的正在拖拽的函数
     this ._drag  =  when_Drag;
     // 公用的拖拽结束的函数
     this ._dragEnd  =  end_Drag;
     // q个函数主要用来q行拖拽l束后的dom处理
     this ._afterDrag  =  after_Drag;
     // 是否正在被拖动,一开始当然没有被拖动
     this .isDragging  =   false ;
     // 这个Element的this指针注册在elmq个变量里面Q方便在自己的上下文以外调用自己的函数等Q很常用的方?
     this .elm  =  el;
     // 触发拖拽的ElementQ在q里是q个div上显C标题的那个div
     this .header  =  getElementById(el.id  +   " _h " );
     // 对于有i的element拖拽不同Q这里检一下ƈ记录
     this .hasI  =   this .elm.getElementsByTagName( " I " ).length  >   0 ;
     // 如果扑ֈ了headerq定drag相关的event
     if  ( this .header) {
         // 拖拽时的叉子鼠标指针
         this .header.style.cursor  =   " move " ;
         // 函数绑定到header和element的this上,参照那个函数的说?
        Drag.init( this .header,  this .elm);
         // 下面三个语句写好的三个函数l定l这个elemnt的三个函数钩子上Q也实Celement从draggablel承可拖拽的函数
         this .elm.onDragStart  =  Util.bind( this ,  " _dragStart " );
         this .elm.onDrag  =  Util.bind( this ,  " _drag " );
         this .elm.onDragEnd  =  Util.bind( this ,  " _dragEnd " );
    }
};

// 下面是draggable里面用到的那4?
// 公用的开始拖拽的函数
  start_Drag() {
     // 重置坐标Q实现拖拽以后自q位置马上会被填充的效?
    Util.re_calcOff( this );
     // 记录原先的邻居节点,用来Ҏ是否被移动到新的位置
     this .origNextSibling  =   this .elm.nextSibling;
     // 获取Ud的时候那个灰色的虚线?
     var  _ghostElement  =  getGhostElement();
     // 获取正在Ud的这个对象的高度
     var  offH  =   this .elm.offsetHeight;
     if  (Util.isGecko) {
         // 修正gecko引擎的怪癖?
        offH  -=  parseInt(_ghostElement.style.borderTopWidth)  *   2 ;
    }
     // 获取正在Ud的这个对象的宽度
     var  offW  =   this .elm.offsetWidth;
     // 获取left和top的坐?
     var  offLeft  =  Util.getOffset( this .elm,  true );
     var  offTop  =  Util.getOffset( this .elm,  false );
     // 防止闪烁Q现隐藏
    Util.hide();
     // 自q宽度记录在style属性里?
     this .elm.style.width  =  offW  +   " px " ;
     // 那个灰框设定得与正在拖动的对象一样高Q比较Ş?
    _ghostElement.style.height  =  offH  +   " px " ;
     // 把灰框放到这个对象原先的位置?
     this .elm.parentNode.insertBefore(_ghostElement,  this .elm.nextSibling);
     // ׃要拖动必d被拖动的对象从原先的盒子模型里面抽出来,所以设定position为absoluteQ这个可以参考一下css布局斚w的知?
     this .elm.style.position  =   " absolute " ;
     // 讄zIndexQ让它处在最前面一层,当然其实zIndex=100是让它很靠前Q如果页面里有zIndex>100的,?#8230;…
     this .elm.style.zIndex  =   100 ;
     // ׃position=absolute了,所以left和top实现l对坐标定位Q这是先前计算坐标的作用,不让q个模型pQ要从开始拖动的地方开始移?
     this .elm.style.left  =  offLeft  +   " px " ;
     this .elm.style.top  =  offTop  +   " px " ;
     // 坐标讑֮完毕Q可以显CZQ这样就不会闪烁?
    Util.show();
     // q里本来有个ig_d.GQ没搞明白干什么用的,不过没有也可以用Q谁知道ȝ告诉我一壎ͼ不好意?
     // q没有开始拖拽,q里做个记号
     this .isDragging  =   false ;
     return   false ;
};

// 初始化可以拖拽的Element的函敎ͼ与拖拽无关的我去掉了
  draggable(el) {
     // 公用的开始拖拽的函数
     this ._dragStart  =  start_Drag;
     // 公用的正在拖拽的函数
     this ._drag  =  when_Drag;
     // 公用的拖拽结束的函数
     this ._dragEnd  =  end_Drag;
     // q个函数主要用来q行拖拽l束后的dom处理
     this ._afterDrag  =  after_Drag;
     // 是否正在被拖动,一开始当然没有被拖动
     this .isDragging  =   false ;
     // 这个Element的this指针注册在elmq个变量里面Q方便在自己的上下文以外调用自己的函数等Q很常用的方?
     this .elm  =  el;
     // 触发拖拽的ElementQ在q里是q个div上显C标题的那个div
     this .header  =  getElementById(el.id  +   " _h " );
     // 对于有i的element拖拽不同Q这里检一下ƈ记录
     this .hasI  =   this .elm.getElementsByTagName( " I " ).length  >   0 ;
     // 如果扑ֈ了headerq定drag相关的event
     if  ( this .header) {
         // 拖拽时的叉子鼠标指针
         this .header.style.cursor  =   " move " ;
         // 函数绑定到header和element的this上,参照那个函数的说?
        Drag.init( this .header,  this .elm);
         // 下面三个语句写好的三个函数l定l这个elemnt的三个函数钩子上Q也实Celement从draggablel承可拖拽的函数
         this .elm.onDragStart  =  Util.bind( this ,  " _dragStart " );
         this .elm.onDrag  =  Util.bind( this ,  " _drag " );
         this .elm.onDragEnd  =  Util.bind( this ,  " _dragEnd " );
    }
};
// 下面是draggable里面用到的那4?
// 公用的开始拖拽的函数
  start_Drag() {
     // 重置坐标Q实现拖拽以后自q位置马上会被填充的效?
    Util.re_calcOff( this );
     // 记录原先的邻居节点,用来Ҏ是否被移动到新的位置
     this .origNextSibling  =   this .elm.nextSibling;
     // 获取Ud的时候那个灰色的虚线?
     var  _ghostElement  =  getGhostElement();
     // 获取正在Ud的这个对象的高度
     var  offH  =   this .elm.offsetHeight;
     if  (Util.isGecko) {
         // 修正gecko引擎的怪癖?
        offH  -=  parseInt(_ghostElement.style.borderTopWidth)  *   2 ;
    }
     // 获取正在Ud的这个对象的宽度
     var  offW  =   this .elm.offsetWidth;
     // 获取left和top的坐?
     var  offLeft  =  Util.getOffset( this .elm,  true );
     var  offTop  =  Util.getOffset( this .elm,  false );
     // 防止闪烁Q现隐藏
    Util.hide();
     // 自q宽度记录在style属性里?
     this .elm.style.width  =  offW  +   " px " ;
     // 那个灰框设定得与正在拖动的对象一样高Q比较Ş?
    _ghostElement.style.height  =  offH  +   " px " ;
     // 把灰框放到这个对象原先的位置?
     this .elm.parentNode.insertBefore(_ghostElement,  this .elm.nextSibling);
     // ׃要拖动必d被拖动的对象从原先的盒子模型里面抽出来,所以设定position为absoluteQ这个可以参考一下css布局斚w的知?
     this .elm.style.position  =   " absolute " ;
     // 讄zIndexQ让它处在最前面一层,当然其实zIndex=100是让它很靠前Q如果页面里有zIndex>100的,?#8230;…
     this .elm.style.zIndex  =   100 ;
     // ׃position=absolute了,所以left和top实现l对坐标定位Q这是先前计算坐标的作用,不让q个模型pQ要从开始拖动的地方开始移?
     this .elm.style.left  =  offLeft  +   " px " ;
     this .elm.style.top  =  offTop  +   " px " ;
     // 坐标讑֮完毕Q可以显CZQ这样就不会闪烁?
    Util.show();
     // q里本来有个ig_d.GQ没搞明白干什么用的,不过没有也可以用Q谁知道ȝ告诉我一壎ͼ不好意?
     // q没有开始拖拽,q里做个记号
     this .isDragging  =   false ;
     return   false ;
};
// 在拖拽时的相应函敎ͼ׃l定到鼠标的moveq个event上,所以会传入鼠标的坐标clientX, clientY
  when_Drag(clientX, clientY) {
     // 刚开始拖拽的时候将囑ֱ变透明Qƈ标记为正在被拖拽
     if  ( ! this .isDragging) {
         this .elm.style.filter  =   " alpha(opacity=70) " ;
         this .elm.style.opacity  =   0.7 ;
         this .isDragging  =   true ;
    }
     // 被拖拽到的新的columnQ当然也可以是原来那个)
     var  found  =   null ;
     // 最大的距离Q可能是防止溢出或者什么bug
     var  max_distance  =   100000000 ;
     // 遍历所有的可拖拽的elementQ寻扄当前鼠标坐标最q的那个可拖拽元素,以便后面插入
     for  ( var  i  =   0 ; i  <  Util.dragArray.length; i ++ ) {
         var  ele  =  Util.dragArray[i];
         // 利用勾股定理计算鼠标到遍历到的这个元素的距离
         var  distance  =  Math.sqrt(Math.pow(clientX  -  ele.elm.pagePosLeft,  2 )  +  Math.pow(clientY  -  ele.elm.pagePosTop,  2 ));
         // 自己已经动了,所以不计算自己?
         if  (ele  ==   this ) {
             continue ;
        }
         // 如果计算p|l箋循环
         if  (isNaN(distance)) {
             continue ;
        }
         // 如果更小Q记录下q个距离Qƈ它作ؓfound
         if  (distance  <  max_distance) {
            max_distance  =  distance;
            found  =  ele;
        }
    }
     // 准备让灰框落?
     var  _ghostElement  =  getGhostElement();
     // 如果扑ֈ了另外的落脚?
     if  (found  !=   null   &&  _ghostElement.nextSibling  !=  found.elm) {
         // 扑ֈ落脚点就先把灰框插进去,q就是我们看到的那个灰框停靠的特效,有点像吸附的感觉Q哈?
        found.elm.parentNode.insertBefore(_ghostElement, found.elm);
         if  (Util.isOpera) {
             // Opera的现实问题,要隐?昄后才能刷新出变化
            body.style.display  =   " none " ;
            body.style.display  =   "" ;
        }
    }
};
// 拖拽完毕
  end_Drag() {
     // 拖拽完毕后执行后面的钩子Q执行after_Drag()Q如果布局发生了变动了p录到q程服务器,保存你拖拽后新的布局序
     if  ( this ._afterDrag()) {
         // remote call to save the change
    }
     return   true ;
};
// 拖拽后的执行钩子
  after_Drag() {
     var  return  =   false ;
     // 防止闪烁
    Util.hide();
     // 把拖拽时的position=absolute和相关的那些style都消?
     this .elm.style.position  =   "" ;
     this .elm.style.width  =   "" ;
     this .elm.style.zIndex  =   "" ;
     this .elm.style.filter  =   "" ;
     this .elm.style.opacity  =   "" ;
     // 获取灰框
     var  ele  =  getGhostElement();
     // 如果现在的邻居不是原来的d?
     if  (ele.nextSibling  !=   this .origNextSibling) {
         // 把被拖拽的这个节Ҏ到灰框的前面
        ele.parentNode.insertBefore( this .elm, ele.nextSibling);
         // 标明被拖拽了新的地方
        return  =   true ;
    }
     // U除灰框Q这是这个灰框的生命周期应该q束了
    ele.parentNode.removeChild(ele);
     // 修改完毕Q显C?
    Util.show();
     if  (Util.isOpera) {
         // Opera的现实问题,要隐?昄后才能刷新出变化
        body.style.display  =   " none " ;
        body.style.display  =   "" ;
    }
     return  return;
};


// 可拖拽Element的原形,用来eventl定到各个钩子,q部分市比较通用的,netvibes也是基本完全相同的实?
// q部分推荐看dindin的这个,也会帮助理解Q?a >http://www.jroller.com/page/dindin/?anchor=pro_java_12
var  Drag  =  {
     // 对这个element的引用,一ơ只能拖拽一个Element
    obj: null ,
     // element是被拖拽的对象的引用QelementHeader是鼠标可以拖拽的区?
    init:   (elementHeader, element) {
         // startl定到down事gQ按下鼠标触发start
        elementHeader.down  =  Drag.start;
         // element存到header的obj里面Q方便header拖拽的时候引?
        elementHeader.obj  =  element;
         // 初始化绝对的坐标Q因Z是position=absolute所以不会v什么作用,但是防止后面onDrag的时候parse出错?
         if  (isNaN(parseInt(element.style.left))) {
            element.style.left  =   " 0px " ;
        }
         if  (isNaN(parseInt(element.style.top))) {
            element.style.top  =   " 0px " ;
        }
         // 挂上I,初始化这几个成员Q在Drag.init被调用后才帮定到实际的函敎ͼ可以参照draggable里面的内?
        element.onDragStart  =   new  ();
        element.onDragEnd  =   new  ();
        element.onDrag  =   new  ();
    },
     // 开始拖拽的l定Q绑定到鼠标的移动的event?
    start:   (event) {
         var  element  =  Drag.obj  =   this .obj;
         // 解决不同览器的event模型不同的问?
        event  =  Drag.fixE(event);
         // 看看是不是左键点?
         if  (event.which  !=   1 ) {
             // 除了左键都不起作?
             return   true ;
        }
         // 参照q个函数的解释,挂上开始拖拽的钩子
        element.onDragStart();
         // 记录鼠标坐标
        element.lastMouseX  =  event.clientX;
        element.lastMouseY  =  event.clientY;
         // Global的eventl定到被拖动的element上面?
        up  =  Drag.end;
        move  =  Drag.drag;
         return   false ;
    },
     // Element正在被拖动的函数
    drag:   (event) {
         // 解决不同览器的event模型不同的问?
        event  =  Drag.fixE(event);
         // 看看是不是左键点?
         if  (event.which  ==   0 ) {
             // 除了左键都不起作?
             return  Drag.end();
        }
         // 正在被拖动的Element
         var  element  =  Drag.obj;
         // 鼠标坐标
         var  _clientX  =  event.clientY;
         var  _clientY  =  event.clientX;
         // 如果鼠标没动׃么都不作
         if  (element.lastMouseX  ==  _clientY  &&  element.lastMouseY  ==  _clientX) {
             return   false ;
        }
         // 刚才Element的坐?
         var  _lastX  =  parseInt(element.style.top);
         var  _lastY  =  parseInt(element.style.left);
         // 新的坐标
         var  newX, newY;
         // 计算新的坐标Q原先的坐标+鼠标Ud的值差
        newX  =  _lastY  +  _clientY  -  element.lastMouseX;
        newY  =  _lastX  +  _clientX  -  element.lastMouseY;
         // 修改element的显C坐?
        element.style.left  =  newX  +   " px " ;
        element.style.top  =  newY  +   " px " ;
         // 记录element现在的坐标供下一ơ移动?
        element.lastMouseX  =  _clientY;
        element.lastMouseY  =  _clientX;
         // 参照q个函数的解释,挂接上Drag时的钩子
        element.onDrag(newX, newY);
         return   false ;
    },
     // Element正在被释攄函数Q停止拖?
    end:   (event) {
         // 解决不同览器的event模型不同的问?
        event  =  Drag.fixE(event);
         // 解除对Global的event的绑?
        move  =   null ;
        up  =   null ;
         // 先记录下onDragEnd的钩子,好移除obj
         var  _onDragEndFuc  =  Drag.obj.onDragEnd();
         // 拖拽完毕Qobj清空
        Drag.obj  =   null ;
         return  _onDragEndFuc;
    },
     // 解决不同览器的event模型不同的问?
    fixE:   (ig_) {
         if  ( typeof  ig_  ==   " undefined " ) {
            ig_  =  event;
        }
         if  ( typeof  ig_.layerX  ==   " undefined " ) {
            ig_.layerX  =  ig_.offsetX;
        }
         if  ( typeof  ig_.layerY  ==   " undefined " ) {
            ig_.layerY  =  ig_.offsetY;
        }
         if  ( typeof  ig_.which  ==   " undefined " ) {
            ig_.which  =  ig_.button;
        }
         return  ig_;
    }
};

// 下面是初始化的函CQ看看上面这些东西怎么被调?
var  _IG_initDrag  =     (el) {
     // column那个容器Q在google里面是那个table布局的tbodyQnetvibes用的<div>
    Util.rootElement  =  el;
     // q个tbody的行
    Util._rows  =  Util.rootElement.tBodies[ 0 ].rows[ 0 ];
     // 列,google?列,其实也可以更?
    Util.column  =  Util._rows.cells;
     // 用来存取可拖拽的对象
    Util.dragArray  =   new  Array();
     var  counter  =   0 ;
     for  ( var  i  =   0 ; i  <  Util.column.length; i ++ ) {
         // 搜烦所有的column
         var  ele  =  Util.column[i];
         for  ( var  j  =   0 ; j  <  ele.childNodes.length; j ++ ) {
             // 搜烦每一column里面的所有element
             var  ele1  =  ele.childNodes[j];
             // 如果是div把它初始化Z个draggable对象
             if  (ele1.tagName  ==   " DIV " ) {
                Util.dragArray[counter]  =   new  draggable(ele1);
                counter ++ ;
            }
        }
    }
};

// google的页面里可以拖动的部分的id?t_1"
// 挂蝲刎ͼ载入完毕执行。不q实际上google没有用?
// 而是写在面最下面Q异曲同工吧Q也许直接写在页面是U怪癖Q或者也有可能是兼容性考虑?

// 请将下面两条被注释掉的代码加Q到你自׃载的一个google ig面里面Q把里面的所有其余删除,挂上q个js也可以拖拽了Q哈?
// _table=getElementById("t_1");
// = _IG_initDrag(_table);

// 其实看懂q些代码对学习java很有益,希望对大家能有帮?/span>


C物 2008-02-13 22:51 发表评论
]]>
Google“爬虫”主动“送食”(转蝲Q?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:44:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179850.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179850.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/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>收录Q抓取更多的内容Q甚x取所有网)Q可以?span style="font-family: Times New Roman;">google</span>提供?span style="font-family: Times New Roman;">google Sitemap</span>服务Q?span style="font-family: Times New Roman;"> <a >https://www.google.com/webmasters/tools/docs/zh_CN/sitemap-generator.html</a></span>Q?/p> <p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">使搜索引搜烦蜘蛛的收录由被动变ؓdQ?span style="font-family: Times New Roman;">google Sitemap</span>服务目前不提供在线创徏<span style="font-family: Times New Roman;">Sitemap</span>的功能,但是我们可以借助W三方网站提供的此类服务Q打开|站Q?a ><span style="font-family: Times New Roman;">http://www.xml-sitemaps.com</span></a>Q(如图<span style="font-family: Times New Roman;">1</span>Q?nbsp;</p> <p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">?#8220;<span style="font-family: Times New Roman;">Starting URL</span>”栏中输入你自q|站地址Q在“<span style="font-family: Times New Roman;">Change frequency</span>”下拉列表选择|站的更新频率(l常 每天 每年{不同的时段Q,?#8220;<span style="font-family: Times New Roman;">Last modification</span>”选择最后修Ҏ_选择<span style="font-size: 8.5pt;">Use server's response</span>服务器反映时?nbsp;Q,?#8220;Priority”栏中速入跟新的优先权Q最后点?#8220;Start”按钮创徏|站地图 Q如?Q?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文gQ将“Sitemap.xml”下蝲到本地然后再传到服务器主目录下,下面用Gmail帐户登陆到google Sitemap,d自己的网站sitemap文gQ如?Q?img src="http://www.6b9g.com/sitemap.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" alt="" />Q再选在d该站点的sitemapQ注意在选择分类的时候选择d常规|络(如图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地址Q各?a >http://www.6b9g.com/sitemap.xml</a>  再点?#8220;d普通sitemap” 按钮</p> <p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">首发 高峰 站长互动信息|?nbsp;  <a >http://www.6b9g.com</a></p> <img src ="http://m.tkk7.com/libin2722/aggbug/179850.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:44 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>论坛灌水?-- HTTPClienthttp://m.tkk7.com/libin2722/archive/2008/02/13/179849.htmlC物C物Wed, 13 Feb 2008 14:37:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179849.htmlhttp://m.tkk7.com/libin2722/comments/179849.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179849.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179849.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179849.html
本程序用了HTTPClient包,下蝲地址Q?br /> http://www.innovation.ch/java/HTTPClient/

灌水机原理很单,是分析论坛的表单,用自qE序模拟提交可以了Q?br /> 本文的目的在于介lHTTPClientq个开源工P比jdk?net包强何止癑ր,
HTTPClient的特Ҏ多个操作可以复用同一个连接,讄q接时(Zsocket)Q用代理验证。具体可以到innovation|站看看Ҏ数据?br />
如下是灌水程序的单程序,仅供参?br /> import java.net.*;
import java.io.*;
import java.util.*;
import HTTPClient.*;

class WebRequester{
private static InputStream istr = null;
private static OutputStream ostr = null;
private static NVPair form_data[];
private static HTTPConnection httpCon;
private static HTTPResponse rsp;
private static String host;
private static WebRequester instance;
private WebRequester(){
}
public static WebRequester getInstance(){
  if(instance==null){
    instance = new WebRequester();
  }
  return instance;
}
public static String request(HTTPConnection connection,String pathName,String method,NVPair form_data[]) {
  try{
    httpCon = connection;
    if(method.toLowerCase().equals("get")){
      if(form_data!=null)
      rsp = httpCon.Get(pathName, form_data);
      else
      rsp = httpCon.Get(pathName);
    }
    else{
      if(form_data!=null)
      rsp = httpCon.Post(pathName, form_data);
      else
      rsp = httpCon.Post(pathName);
    }
    istr = rsp.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(istr));
    String line;
    StringBuffer result = new StringBuffer();
    while ((line = reader.readLine()) != null) {
    result.append(line + System.getProperty("line.separator"));
    }
    return result.toString();
  } catch(Exception e){
  }
return "";
}
}


public class Flood
{
private HTTPConnection connection;
public Flood(){

  getConnection("sitename.com",80);
}
public void releaseConnection(){
  if(connection!=null){
    connection.stop();
    connection = null;
  }
}
public HTTPClient.HTTPConnection getConnection(String hostName,int port){
  if(connection==null){
    try{
      connection = new HTTPClient.HTTPConnection(hostName,port);
      HTTPClient.Module.setPolicyHandler(null);
      connection.addDefaultModule(Class.forName("HTTPClient.Module"), 1);
      connection.addModule(Class.forName("HTTPClient.RedirectionModule"),2);
    }catch(Exception e){
      e.printStackTrace();
    }
  }
  return connection;
}

public void post(String subject,String body){
  NVPair[] form_data = new NVPair[5];
  form_data[0] = new NVPair("forumID","87");
  form_data[1] = new NVPair("subject",subject);
  form_data[2] = new NVPair("classifier","-1");
  form_data[3] = new NVPair("body",body);
  form_data[4] = new NVPair("doPost"," ??");
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);

}
public void reply(String thread,String subject,String body){
  //提交表单需要多项Q查看回复页面表单可以获?br />   NVPair[] form_data = new NVPair[7];
  form_data[0] = new NVPair("forumID","87");
  form_data[1] = new NVPair("subject",subject);
  form_data[2] = new NVPair("classifier","-1");
  form_data[3] = new NVPair("body",body);
  form_data[4] = new NVPair("reply","true");
  form_data[5] = new NVPair("threadID",thread);
  form_data[6] = new NVPair("doPost"," ??");
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);

}
public void finish(){
  releaseConnection();
}
public void login(){

  WebRequester wr = WebRequester.getInstance();
  NVPair[] form_data = new NVPair[4];
  //对应登陆需要的表单字段填写
  form_data[0] = new NVPair("formUsername","user");
  form_data[1] = new NVPair("formPassword","pass");
  form_data[2] = new NVPair("formLogins cript","sitename.com/loginuser.jsp");
  form_data[3] = new NVPair("forumLogin","Y");
  //提交到指定登陆页?br />   wr.request(connection,"cgi-bin/gzhome/registration/LoginUser1.jsp","post",form_data);
  //假如重定向,必须用该链接再次h新的面
  wr.request(connection,"loginuser.jsp","get",null);
  wr.request(connection,"index.jspa","get",null);
}


public static void main(String[] args)
{  
  try{
  Flood f=new Flood();
  f.login();
  //post一个新主题Qidql自׃?br />   //f.post("friends","剧本");
  //得到某个主题idQ进行指定数量的跟帖
  for(int i=0;i<50;i++){
    f.reply("67145","Re: 警告Q在U朋友发a又少了,望奔走相?,"z水来了");
  }
  /*如下是读取某个文件每一行文字作为回帖进行灌?br />   BufferedReader br = new BufferedReader(new FileReader("E:""movie""101-105""Friends - 1x04 - TOW George Stephanopoulos.CHN.srt"));
  StringBuffer sb = new StringBuffer();
  String t = null;
  int counter=0;
  while((t=br.readLine())!=null){
  if(t.length()==0){
    //System.out.println(sb.toString());
      //System.out.println("====");
  counter++;
  f.reply("66617","" + counter,sb.toString());
  sb.delete(0,sb.length());
  }
  sb.append(t + ""n");
  
  }*/
  f.finish();
}catch(Exception e){
  e.printStackTrace();
}
}
}


OKOK~大家自己研究
我做好了

C物 2008-02-13 22:37 发表评论
]]>
httpclient中MultipartPostMethodcM传文?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:35:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179848.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179848.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/libin2722/services/trackbacks/179848.html</trackback:ping><description><![CDATA[<p>在文件上传过E中到很多问题Q首先是搞错了类Q刚开始时我用的是PostodMethod,以ؓ一? setrequestbodyQ)Ҏ可以搞定,l果改过来改q去也没改出来什么名堂,最后改用的是MultipartPostMethodc,呵呵Q? 问题解决了,关键ҎMultipartPostMethodc里的addParameter()和addPart()两个Ҏ都要用到Q而且要注意顺 序。不q马上又出现了新的问题,httpclient不支持中文名的文件上传,晕了。又在这上面费了一D|间。解决的途径是。找? httpclient3.0"rc"java"org"apache"commons"httpclient"util目录下的 EncodingUtil.java,打开Q找到文仉面这个地方:<br /> public static byte[] getAsciiBytes(final String data) {        <br /> if (data == null) {            <br /> throw new IllegalArgumentException("Parameter may not be null");       }        <br /> try {           return data.getBytes("US-ASCII");       } <br /> catch (UnsupportedEncodingException e) {throw new HttpClientError("HttpClient requires ASCII support");       }  <br /> }<br /> ? C没有Qreturn data.getBytes("US-ASCII");它的~码方式是US-ASCIIQ问题就出在q里了,把这个取掉,换成"GBK"或? "GB2312"保存以后~译Q重新运行程序,goooooooooooood。中文名文g现在可以上传了,呵呵</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 /> <HTML><br />   <HEAD><br />     < HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"/><br />     <TITLE>File Upload Page</TITLE><br />   </HEAD><br />   <BODY>Upload Files<br />     <FORM name="filesForm" action="ProcessFileUpload.jsp"<br />     method="post" enctype="multipart/form-data"><br />         File 1:<input type="file" name="file1"/><br/><br />         File 2:<input type="file" name="file2"/><br/><br />         File 3:<input type="file" name="file3"/><br/><br />         <input type="submit" name="Submit" ="Upload Files"/><br />     </FORM><br />   </BODY><br /> </HTML></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 /> <%@ page contentType="text/html;charset=windows-1252"%><br /> <%@ page import="org.apache.commons.fileupload.DiskFileUpload"%><br /> <%@ page import="org.apache.commons.fileupload.FileItem"%><br /> <%@ page import="jsp servlet ejb .util.List"%><br /> <%@ page import="jsp servlet ejb .util.Iterator"%><br /> <%@ page import="jsp servlet ejb .io.File"%><br /> html><br /> <head><br /> < http-equiv="Content-Type" content="text/html; charset=windows-1252"><br /> <title>Process File Upload</title><br /> </head><br /> <%<br />         System.out.println("Content Type ="+request.getContentType());</p> <p>        DiskFileUpload fu = new DiskFileUpload();<br />         // If file size exceeds, a FileUploadException will be thrown<br />         fu.setSizeMax(1000000);</p> <p>        List fileItems = fu.parseRequest(request);<br />         Iterator itr = fileItems.iterator();</p> <p>        while(itr.hasNext()) {<br />           FileItem fi = (FileItem)itr.next();</p> <p>          //Check if not form field so as to only handle the file inputs<br />           //else condition handles the submit button input<br />           if(!fi.isFormField()) {<br />             System.out.println(""nNAME: "+fi.getName());<br />             System.out.println("SIZE: "+fi.getSize());<br />             //System.out.println(fi.getOutputStream().toString());<br />             File fNew= new File(application.getRealPath("/"), fi.getName());</p> <p>            System.out.println(fNew.getAbsolutePath());<br />             fi.write(fNew);<br />           }<br />           else {<br />             System.out.println("Field ="+fi.getFieldName());<br />           }<br />         }<br /> %><br /> <body><br /> Upload Successful!!<br /> </body><br /> </html></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: “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.”</p> <p>This contrasting behavior on different browsers can cause problems. One workaround that I found in an article at <a 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…blaming Microsoft is always the easy way out) </p> <p>File tempFileRef  = 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 />     private static String url =<br />       "http://localhost/yaoliang/ProcessFileUpload.jsp";</p> <p>    public static void main(String[] args) throws IOException {<br />         HttpClient client = new HttpClient();<br />         MultipartPostMethod mPost = new MultipartPostMethod(url);<br />         client.setConnectionTimeout(8000);</p> <p>        // Send any XML file as the body of the POST request<br />         File f1 = new File("D:/students.xml");<br />         File f2 = new File("D:/demy.xml");<br />         File f3 = new File("D:/demyRules.xml");</p> <p>        System.out.println("File1 Length = " + f1.length());<br />         System.out.println("File2 Length = " + f2.length());<br />         System.out.println("File3 Length = " + f3.length());</p> <p>        mPost.addParameter(f1.getName(),f1.getName(),  f1);<br />         mPost.addParameter(f2.getName(), f2.getName(), f2);<br />         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>        int statusCode1 = client.executeMethod(mPost);</p> <p>        System.out.println("statusLine>>>" + mPost.getStatusLine());<br />         mPost.releaseConnection();<br />     }<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://m.tkk7.com/libin2722/aggbug/179848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:35 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用HttpClient来对付各U顽固的WEB服务?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:34:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179847.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179847.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/libin2722/services/trackbacks/179847.html</trackback:ping><description><![CDATA[<p>一般的情况下我们都是用IE或者Navigator览器来讉K一个WEB服务器,用来览面查看信息或者提交一些数据等{。所讉K的这些页? 有的仅仅是一些普通的面Q有的需要用L录后方可使用Q或者需要认证以及是一些通过加密方式传输Q例如HTTPS。目前我们用的览器处理这些情况都 不会构成问题。不q你可能在某些时候需要通过E序来访问这L一些页面,比如从别人的|页?#8220;?#8221;一些数据;利用某些站点提供的页面来完成某种功能Q例? 说我们想知道某个手机L的归属地而我们自己又没有q样的数据,因此只好借助其他公司已有的网站来完成q个功能Q这个时候我们需要向|页提交手机Lq从 q回的页面中解析出我们想要的数据来。如果对方仅仅是一个很单的面Q那我们的程序会很简单,本文也就没有必要大张旗鼓的在q里费口舌。但是考虑C 些服务授权的问题Q很多公司提供的面往往q不是可以通过一个简单的URL可以访问的Q而必ȝq注册然后登录后方可使用提供服务的页面,q个时候就? 及到问题的处理。我们知道目前流行的动态网|术例如ASP、JSP无不是通过来处理会话信息的。ؓ了我们的程序能使用别h所提供的服务页面,p求程 序首先登录后再访问服务页面,q过E就需要自行处理,x当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情 啊!况且q仅仅是我们所说的固的WEB服务器中的一个很常见?#8220;固”Q再有如通过HTTP来上传文件呢Q不需要头|q些问题有了“?#8221;很Ҏ解决 了! <br /> </p> <p><span style="font-size: 10pt; font-family: Courier New;">我们不可能列举所 有可能的固Q我们会针对几种最常见的问题进行处理。当然了Q正如前面说到的Q如果我们自׃用java.net.HttpURLConnection? 搞定q些问题是很恐怖的事情Q因此在开始之前我们先要介l一下一个开放源码的目Q这个项目就是Apache开源组l中的httpclientQ它隶属? Jakarta的commons目Q目前的版本?.0RC2。commons下本来已l有一个net的子目Q但是又把httpclient单独提出 来,可见http服务器的讉Kl非易事?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">Commons-httpclient 目是专门设计来简化HTTP客户端与服务器进行各U通讯~程。通过它可以让原来很头疼的事情现在L的解冻I例如你不再管是HTTP或者HTTPS? 通讯方式Q告诉它你想使用HTTPS方式Q剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时l常到的几个问题进 行分别介l如何用httpclient来解军_们,Z让读者更快的熟悉q个目我们最开始先l出一个简单的例子来读取一个网늚内容Q然后@序渐q解 x前进中的所有问题?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">1Q?d|页(HTTP/HTTPS)内容</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">下面是我们给出的一个简单的例子用来讉K某个面</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方式讉K某个面</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;">    public static void main(String[] args) throws IOException</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">    {</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        HttpClient client = new HttpClient();    </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //讄代理服务器地址和端?nbsp;    </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //使用GETҎQ如果服务器需要通过HTTPSq接Q那只需要将下面URL中的http换成https</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        HttpMethod method = new GetMethod("<a target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //使用POSTҎ</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //HttpMethod method = new PostMethod("<a target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        client.executeMethod(method);</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //打印服务器返回的状?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        System.out.println(method.getStatusLine());</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //打印q回的信?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        System.out.println(method.getResponseBodyAsString());</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //释放q接</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        method.releaseConnection();</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">    }<br /> }</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">在这个例子中首先创徏一? HTTP客户?HttpClient)的实例,然后选择提交的方法是GET或者POSTQ最后在HttpClient实例上执行提交的ҎQ最后从所? 择的提交Ҏ中读取服务器反馈回来的结果。这是使用HttpClient的基本流E。其实用一行代码也可以搞定整个请求的q程Q非常的单!</span></p> <span style="font-size: 10pt; font-family: Courier New;"> <p><br /> 2Q?以GET或者POST方式向网|交参?/p> <p>其实前面一个最单的CZ中我们已l介l了如何使用GET或者POST方式来请求一个页面,本小节与之不同的是多了提交时讑֮面所需的参敎ͼ我们 知道如果是GET的请求方式,那么所有参数都直接攑ֈ面的URL后面用问号与面地址隔开Q每个参数用&隔开Q例如:<a target="_blank"><span style="color: #000000;">http://java.sun.com?name=liudong&mobile=123456</span></a>Q但是当使用POSTҎ时就会稍微有一点点ȝ。本节的例子演C向如何查询手机L所在的城市Q代码如下:</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>* 以便查询LD?330227所在的省䆾以及城市</p> <p>* @author Liudong</p> <p>*/</p> <p>public class SimpleHttpClient {</p> <p>    public static void main(String[] args) throws IOException</p> <p>    {</p> <p>        HttpClient client = new HttpClient();</p> <p>        client.getHostConfiguration().setHost("<a target="_blank"><span style="color: #000000;">www.imobile.com.cn</span></a>", 80, "http");</p> <p>        HttpMethod method = getPostMethod();//使用POST方式提交数据</p> <p>        client.executeMethod(method);</p> <p>       //打印服务器返回的状?/p> <p>        System.out.println(method.getStatusLine());</p> <p>        //打印l果面</p> <p>        String response =</p> <p>           new String(method.getResponseBodyAsString().getBytes("8859_1"));</p> <p>       //打印q回的信?/p> <p>        System.out.println(response);</p> <p>        method.releaseConnection();</p> <p>    }</p> <p>    /**</p> <p>     * 使用GET方式提交数据</p> <p>     * @return</p> <p>     */</p> <p>    private static HttpMethod getGetMethod(){</p> <p>        return new GetMethod("/simcard.php?simcard=1330227");</p> <p>    }</p> <p>    /**</p> <p>     * 使用POST方式提交数据</p> <p>     * @return</p> <p>     */</p> <p>    private static HttpMethod getPostMethod(){</p> <p>        PostMethod post = new PostMethod("/simcard.php");</p> <p>        NamePair simcard = new NamePair("simcard","1330227");</p> <p>        post.setRequestBody(new NamePair[] { simcard});</p> <p>        return post;</p> <p>    }</p> <p>}</p> <p>在上面的例子中页?a target="_blank"><span style="color: #000000;">http://www.imobile.com.cn/simcard.php</span></a>需要一个参数是simcardQ这个参数gؓ手机LD,x机号码的前七位,服务器会q回提交的手机号码对应的省䆾、城市以及其他详l信息。GET的提交方法只需要在URL后加入参C息,而POST则需要通过NamePaircL讄参数名称和它所对应的?/p> <p>3Q?处理面重定?/p> <p>在JSP/Servlet~程中response.sendRedirectҎ是使用HTTP协议中的重定向机制。它与JSP中的< jsp:forward …>的区别在于后者是在服务器中实现页面的跌{Q也是说应用容器加载了所要蟩转的面的内容ƈq回l客LQ而前者是q回一个状态码Q这些状态码 的可能D下表Q然后客Ld需要蟩转到的页面的URLq新加载新的页面。就是这样一个过E,所以我们编E的时候就要通过 HttpMethod.getStatusCode()Ҏ判断q回值是否ؓ下表中的某个值来判断是否需要蟩转。如果已l确认需要进行页面蟩转了Q那么可 以通过dHTTP头中的location属性来获取新的地址?/p> </span> <img src ="http://m.tkk7.com/libin2722/aggbug/179847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:34 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVAҎ字证书的常用操作http://m.tkk7.com/libin2722/archive/2008/02/13/179844.htmlC物C物Wed, 13 Feb 2008 14:16:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179844.htmlhttp://m.tkk7.com/libin2722/comments/179844.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179844.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179844.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179844.html一需要包含的?/strong>

import java.security.*;

import java.io.*;

import java.util.*;

import java.security.*;

import java.security.cert.*;

import sun.security.x509.*

import java.security.cert.Certificate;

import java.security.cert.CertificateFactory;

?从文件中d证书

用keytool?keystore中的证书写入文g中,然后从该文g中读取证书信?br />
CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in=new FileInputStream("out.csr");

Certificate c=cf.generateCertificate(in); String s=c.toString();

?从密钥库中直接读取证?/strong>

String pass="123456";

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,pass.toCharArray());

java.security.cert.Certificate c=ks.getCertificate(alias);//alias为条目的别名

?JAVAE序中显C书指定信?/strong>

System.out.println("输出证书信息:"n"+c.toString());

System.out.println("版本?"+t.getVersion());

System.out.println("序列?"+t.getSerialNumber().toString(16));

System.out.println("M名:"+t.getSubjectDN());

System.out.println("{֏者:"+t.getIssuerDN());

System.out.println("有效期:"+t.getNotBefore());

System.out.println("{֐法Q?+t.getSigAlgName());

byte [] sig=t.getSignature();//{֐?br />
PublicKey pk=t.getPublicKey();

byte [] pkenc=pk.getEncoded();

System.out.println("公钥");

for(int i=0;i<pkenc.length;i++)System.out.print(pkenc[i]+",");

?JAVAE序列出密钥库所有条?/strong>

String pass="123456";

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,pass.toCharArray());

Enumeration e=ks.aliases();

while(e.hasMoreElements())

java.security.cert.Certificate c=ks.getCertificate((String)e.nextElement());

?JAVAE序修改密钥库口?/strong>

String oldpass="123456";

String newpass="654321";

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,oldpass.toCharArray());

in.close();

FileOutputStream output=new FileOutputStream(".keystore");

ks.store(output,newpass.toCharArray());

output.close();

?JAVAE序修改密钥库条目的口o及添加条?/strong>

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,storepass.toCharArray());

Certificate [] cchain=ks.getCertificate(alias);获取别名对应条目的证书链

PrivateKey pk=(PrivateKey)ks.getKey(alias,oldkeypass.toCharArray());获取别名对应条目的私?br />
ks.setKeyEntry(alias,pk,newkeypass.toCharArray(),cchain);向密钥库中添加条?br />
W一个参数指定所d条目的别名,假如使用已存在别名将覆盖已存在条目,使用新别名将增加一个新条目Q第二个参数为条目的U钥Q第三个|的新口令,W四个ؓ该私钥的公钥的证书链

FileOutputStream output=new FileOutputStream("another");

ks.store(output,storepass.toCharArray())keystore对象内容写入新文?/p>

?JAVAE序验别名和删除条目

FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,storepass.toCharArray());

ks.containsAlias("sage");验条目是否在密钥库中Q存在返回true

ks.deleteEntry("sage");删除别名对应的条?br />
FileOutputStream output=new FileOutputStream(".keystore");

ks.store(output,storepass.toCharArray())keystore对象内容写入文g,条目删除成功

?JAVAE序{֏数字证书

Q?Q从密钥库中dCA的证?br />
FileInputStream in=new FileInputStream(".keystore");

KeyStore ks=KeyStore.getInstance("JKS");

ks.load(in,storepass.toCharArray());

java.security.cert.Certificate c1=ks.getCertificate("caroot");

Q?Q从密钥库中dCA的私?br />
PrivateKey caprk=(PrivateKey)ks.getKey(alias,cakeypass.toCharArray());

Q?Q从CA的证书中提取{֏者的信息

byte[] encod1=c1.getEncoded(); 提取CA证书的编?br />
X509CertImpl cimp1=new X509CertImpl(encod1); 用该~码创徏X509CertImplcd对象

X509CertInfo cinfo1=(X509CertInfo)cimp1.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象

X500Name issuer=(X500Name)cinfo1.get(X509CertInfo.SUBJECT+"."+CertificateIssuerName.DN_NAME); 获取X509Namecd的签发者信?br />
Q?Q获取待{֏的证?br />
CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in2=new FileInputStream("user.csr");

java.security.cert.Certificate c2=cf.generateCertificate(in);

Q?Q从待签发的证书中提取证书信?br />
byte [] encod2=c2.getEncoded();

X509CertImpl cimp2=new X509CertImpl(encod2); 用该~码创徏X509CertImplcd对象

X509CertInfo cinfo2=(X509CertInfo)cimp2.get(X509CertImpl.NAME+"."+X509CertImpl.INFO); 获取X509CertInfo对象

Q?Q设|新证书有效?br />
Date begindate=new Date(); 获取当前旉

Date enddate=new Date(begindate.getTime()+3000*24*60*60*1000L); 有效期ؓ3000?br />
CertificateValidity cv=new CertificateValidity(begindate,enddate); 创徏对象

cinfo2.set(X509CertInfo.VALIDITY,cv); 讄有效?br />
Q?Q设|新证书序列?br />
int sn=(int)(begindate.getTime()/1000); 以当前时间ؓ序列?br />
CertificateSerialNumber csn=new CertificateSerialNumber(sn);

cinfo2.set(X509CertInfo.SERIAL_NUMBER,csn);

Q?Q设|新证书{֏?br />
cinfo2.set(X509CertInfo.ISSUER+"."+CertificateIssuerName.DN_NAME,issuer);应用W三步的l果

Q?Q设|新证书{֐法信息

AlgorithmId algorithm=new AlgorithmId(AlgorithmId.md5WithRSAEncryption_oid);

cinfo2.set(CertificateAlgorithmId.NAME+"."+CertificateAlgorithmId.ALGORITHM,algorithm);

Q?0Q创书ƈ使用CA的私钥对其签?br />
X509CertImpl newcert=new X509CertImpl(cinfo2);

newcert.sign(caprk,"MD5WithRSA"); 使用CAU钥对其{֐

Q?1Q将新证书写入密钥库

ks.setCertificateEntry("lf_signed",newcert);

FileOutputStream out=new FileOutputStream("newstore");

ks.store(out,"newpass".toCharArray()); q里是写入了新的密钥库,也可以用第七条来增加条?/p>

?数字证书的检?/strong>

Q?Q验证证书的有效?br />
QaQ获取X509Certificatecd对象

CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in1=new FileInputStream("aa.crt");

java.security.cert.Certificate c1=cf.generateCertificate(in1);

X509Certificate t=(X509Certificate)c1;

in2.close();

QbQ获取日?br />
Date TimeNow=new Date();

QcQ检验有效?br />
try{

t.checkValidity(TimeNow);

System.out.println("OK");

}catch(CertificateExpiredException e){ //q期

System.out.println("Expired");

System.out.println(e.getMessage());

}catch((CertificateNotYetValidException e){ //未生效

System.out.println("Too early");

System.out.println(e.getMessage());}

Q?Q验证证书签名的有效?br />
QaQ获取CA证书

CertificateFactory cf=CertificateFactory.getInstance("X.509");

FileInputStream in2=new FileInputStream("caroot.crt");

java.security.cert.Certificate cac=cf.generateCertificate(in2);

in2.close();

QcQ获取CA的公?br />
PublicKey pbk=cac.getPublicKey();

QbQ获取待验的证书Q上步已l获取了Q就是C1Q?br />
QcQ检验证?br />
boolean pass=false;

try{

c1.verify(pbk);

pass=true;

}catch(Exception e){

pass=false;

System.out.println(e);

}



C物 2008-02-13 22:16 发表评论
]]>
使用Java实现CA(?http://m.tkk7.com/libin2722/archive/2008/02/13/179843.htmlC物C物Wed, 13 Feb 2008 14:14:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179843.htmlhttp://m.tkk7.com/libin2722/comments/179843.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179843.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179843.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179843.html    PKCS#10证书hl构中的主要信息包含了被{֏?证书甌?的主体名U?DN)和他的公?因此一个CA在获取到一个PKCS#10证书h?可以从中获取到M和签发证书有关的信息,然后用它自己的私钥签发证?

    使用BC Provider在Java中构造一个证书请求格式的对象调用其构造函数即?q个函数如下:

    PKCS10CertificationRequest(java.lang.String signatureAlgorithm, X509Name subject, java.security.PublicKey key, ASN1Set attributes, java.security.PrivateKey signingKey)

    它的参数是自{֐法,证书甌者的DN,证书甌者的公钥,额外的属性集(是要申L证书的扩展信?,甌证书者的U钥.甌证书者的U钥仅仅是用来进行一下自{֐,q不出现在证书请求中,需要自{֐的目的是保证该公钥确实ؓ甌者所?

    调用该对象的getEncoded()Ҏ可以其q行DER~码,然后储存h,该对象还有另一个构造函?
    PKCS10CertificationRequest(byte[] bytes)
    q个构造函数的作用是直接从储存的DER~码中把q个对象q原出来.

    利用证书hl构q行证书{֏的代码如?q里假设CSR是一个已l获取出来的PKCS10CertificationRequestl构:

    PublicKey SubjectPublicKey = CSR.getPublicKey();
    CertificationRequestInfo CSRInfo = CSR.getCertificationRequestInfo();
    X509Name SubjectDN = CSRInfo.getSubject();
    ASN1Set Attributes = CSRInfo.getAttributes();

    q样,甌者的MDN,甌者的公钥,甌者希望在证书扩展信息中填写的属性都得到?剩下的事情就和用户在现场输入时一样了,其它的信息一般是甌? 不能军_?另外证书h格式中有一样信息没有明给出来,那就是证书的有效?q个应该单独询问用户,或者用其它的方法保存v?



C物 2008-02-13 22:14 发表评论
]]>
使用Java实现CA(?http://m.tkk7.com/libin2722/archive/2008/02/13/179841.htmlC物C物Wed, 13 Feb 2008 14:12:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179841.htmlhttp://m.tkk7.com/libin2722/comments/179841.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179841.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179841.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179841.html    一份证书就是一个权威机构对一个主体的w䆾的确认的证明.即一份证书表CZ个权威机构确认了一个主体就是它自己,而不是其它的冒名替?M可以是一? 个h,也可以不?例如,在需要安全服务的时?需要ؓ一台网站的服务器颁发证?q种证书的主体就是一台服务器.{v证书的权威机构就叫做CA,该权? 机构本n也是一个主?权威机构通过对包含有待认证的M的一pd信息的待{֐证书"(TBS,to be signed)q行数字{֐来表C机构对它的认?一份包含了待认证的M的相关信息的TBS再加上CA使用自己的私钥进行签名生的字节放在一? 构成了一份标准的X509证书.

    一个TBS中包含了以下q些主要信息:

    证书的版?通常?(X509v3)

    证书的序列号,RFC3280中规?每个CA必须保它颁发的每一份证书的序列号都是唯一?q且序列号只能用非负整?

    {֏?CA)的主体名U?一个DN对象.

    证书的有效期,表示Ҏ是两个时间?表示了该证书从何时开始生?何时开始作?

    待认证的M的主体名U?也是一个DN对象.

    待认证的M的公?M安全应用在确认完证书的有效性后,可以开始用该M的公钥与之进行安全通信.

    如果是X509v3证书,即版本号?的话,后面q有一个证书扩展信息字D?可以在证书里面添加一些其它的信息.

    下面我们来看一下表CZ体的M名称l构:DN.q个l就构是一个属性的集合.每个属性有属性名U和属性?它的作用是用来表示"我是?,也就是说,q个证书到底是谁颁发l谁?q个证书对应的公钥是谁拥有的.

    通常使用一个字W串来表CDNl构,q种字符串说明了q种l构中的各个属性的cd和?

    C=CN;S=BeiJing;L=BeiJing;O=PKU;OU=ICST;CN=wolfenstein

    q里C是国家和地区代码,S和L都是地区代码,S相当于省或者州q样的?L相当于城市?O是组l机构名U?OU是次U组l机构名U?CN是主体的 通用?common name).在这?C,S,L{等属性的cd都是相对固定?例如C一般就是用来表C国家和地区代码,在DNl构中还可以d一些其它类型的信息,一? 也都是以"xxx=xxx"q样来表C的.

    下面我们来说明如何在Java语言中构造出一个主体名U对?

    BC Provider中用X509Name对象来表CDN,构造一个X509Name的步骤大体如?

    先构造两个vector对象,用来表示属性名U和属性?

    Vector oids = new Vector();
    Vector attributes = new Vector();

    然后在oidsq个用来表示属性名U的vector对象中将属性名UC个一个添加进?

    oids.addElement(X509Name.C);

    ......

    oids.addElement(X509Name.CN);

    X509Name对象里面有若q常?例如上面的X509Name.C.q有X509Name.ST{等,都可以和上面丄例子对应h.

    然后属性值添加到attributes对象?

    attributes.addElement("CN");

    ......

    attributes.addElement("Wolfenstein");

    最后就可以构造出一个X509Name对象:

    X509Name SubjectDN = new X509Name(oids, attributes);

    q样,我们的主体名U结构就立h?

    下次我们可以讲关键的部分了,那就是如何用JavaE序完成CA最重要的功?{v证书.



C物 2008-02-13 22:12 发表评论
]]>
使用Java实现CA(一)http://m.tkk7.com/libin2722/archive/2008/02/13/179839.htmlC物C物Wed, 13 Feb 2008 14:11:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179839.htmlhttp://m.tkk7.com/libin2722/comments/179839.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179839.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179839.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179839.html    在所有的此类E序的开?无论是在cȝ构造函C也好,在初始化函数中也?,都要先来上这么一?Security.addProvider(new BouncyCastleProvider());BouncyCaslte的Providerd到系l中,q样以后pȝ在运行相关程序的时候调用的 是q个Provider中的加密法.

    然后我们可以开始开CA?首先,作ؓ一个CA要有自己的一对公钥和U钥,我们先要生成q么一?使用KeyPairGenerator对象可以了, 调用KeyPairGenerator.getInstanceҎ可以Ҏ要生成的密钥cd来生一个合适的实例,例如常用的RSA,DSA{?然后? 用该对象的initializeҎ和generateKeyPairҎ可以生一个KeyPair对象?然后调用KeyPair对象中的相应Ҏ 可以获取生成的密钥对中的公钥和U钥?

    有了公钥和私钥对以后,下面的一个很现实问题是如何把它们储存v?通常我们要对q些安全对象,如公?U钥,证书{先q行~码.~码的目的是Z把结 构复杂的安全对象变成字节以便存储和d,如DER~码.另外,通常q把DER~码后的字节再ơ进行base64~码,以便使字节流中所有的字节都变 成可打印的字?

    在Java语言?q些安全对象基本上都有getEncoded()Ҏ.例如:

    byte[] keyBytes = privateKey.getEncoded();

    q样把一个私钥进行了DER~码后的l果保存C个byte数组中了.然后可以把q个byte数组保存CQ何介质中.如果有必要的?可以使用BC Provider中的Base64~码解码器类q行~码,像q样:

    byte data[] = Base64.encode(keyBytes);

    要从文g中读取私钥则应该q样:

    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyData);
    KeyFactory kfac = KeyFactory.getInstance("RSA");
    privateKey = kfac.generatePrivate(spec);

    q里说明一?对RSAU钥q行~码׃自动地按照PKCS8q行.因此d的时候将包含~码的字节数l作为PKCS8EncodedKeySpec对象 的构造函数的参数可以生成一个该cd的对?然后创徏一个密钥工厂对象就可以按照要求生成一个RSAU钥?很显然这里的keyData应该是和上面? keyBytes内容相同.

    Z提高pȝ的安全?通常U钥在经qDER~码?q会使用一个口令进行加?然后再储存在文gpȝ?在用私钥的时?如果没有正确的口?是无法把U钥q原出来?

    保存证书和保存私钥类?Certificate对象中也有一个getEncoded的方?

    q次pq些.大家应该可以把这些安全对象很熟练C文gpȝ和内存之间来回地折腾了吧.q对以后实现CA是很重要?下次我会讲一下证书中表示M的方?DN.

C物 2008-02-13 22:11 发表评论
]]>
使用Java开发和信息安全相关的程?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179838.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:10:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179838.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179838.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179838.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/libin2722/services/trackbacks/179838.html</trackback:ping><description><![CDATA[q里说的信息安全是相对于pȝ安全而言?它更侧重于加?解密,数字{֐,验证,证书{等.而系l安全主要侧重于pȝ本n是否有安全漏z?如常见的׃软g设计的不完善而导致的满天飞的~冲区溢出等{? <p>    Java语言中负责加密功能的部g是JCE(Java Crypto Extenstion),它用开攑ּ的思想,可以允许用户自己~写加密法的具体实现的模块{?q些东西被称为JCE Provider,JCE的提供?SUN公司本n提供了一些Provider.不过我推荐用Bouncy Castle的Provider.原因是它实现的加密算法多,q比较新的椭圆曲U?ECC)法都有??a >http://www.bouncycastle.org/</a>? 以找C所希望?Bouncy Castle除了提供Provider本n以外,q包括了一个S/MIME和一个open pgp 的jar包只有Provider本n是必要的,后两个包是方便你~程而提供的.例如有了S/MIME包后,你就不再需要ؓ诸如"加密一个字W串? 者一片文章然后签?之类的很现实的应用程序写上一大堆代码?只要引用S/MIME包中的某几个c?很快可以搞?而open pgp的存?使你在用Java~写和PGP/GPG交互的程序时方便多了.</p> <p>    q次先写q么多了,下次开始具体讲把这些东西搞下来后怎么开始干zd.我以我现在手头上正在做的事情告诉大家,如何做一个CA.</p> <p>    有了BC Provider,开CA,真的是q么?</p> <img src ="http://m.tkk7.com/libin2722/aggbug/179838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:10 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA中SSL证书认证通讯-Serverhttp://m.tkk7.com/libin2722/archive/2008/02/13/179836.htmlC物C物Wed, 13 Feb 2008 14:08:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179836.htmlhttp://m.tkk7.com/libin2722/comments/179836.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179836.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179836.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179836.html/********************************************************************
 * 目名称    Qrochoc   <p>
 * 包名U?nbsp;     Qrochoc.net.security <p>
 * 文g名称    QSSLServer   <p>
 * ~写?nbsp;     : LuckyStar    <p>
 * ~写日期    Q?008-2-13    <p>
 * E序功能Q类Q描q?nbsp;Q用于安全通讯的服务SocketQ采用java中的SSLServerSocket<p>
 *
 * E序变更日期   Q?br />  * 变更作?nbsp;   Q?br />  * 变更说明    Q?br /> *******************************************************************
*/
package rochoc.net.security;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManagerFactory;

/**
 * cdQSSLServer  <p>
 * cLqͼ安全通讯的服务端 <p>
 * ~写?nbsp;Qluoc<p>
 * ~写日期 Q?005-6-30<p>
 * 主要public成员变量Q?lt;p>
 * 主要publicҎQ?nbsp;  <p>
 *
*/

public class SSLServer implements Runnable
{
    
/**
     *构造函数说明:       <p>
     *参数说明Q?nbsp;  <p>
    *
*/
    
public SSLServer()
    {       
        init();
    }
   
    
/**
    * Ҏ名称Qinit<p>
    * Ҏ功能Q初始化服务Socket            <p>
    * 参数说明Q?nbsp;<p>
    * q回Qvoid <p>
    * 作者:luoc
    * 日期Q?005-6-30
    *
*/
    
public void init()
    {
        String type
="TLS";//cd
        String keyf="..\\key\\srvstore";//key文g路径
        String trustf="..\\key\\mytrust";
        String pass
="123456";//密码
        int port=2001;//端口
        try
        {
            
//初始化上下文
            SSLContext ctx=SSLContext.getInstance(type);
            KeyManagerFactory kmf
=KeyManagerFactory.getInstance("SunX509");
            TrustManagerFactory tmf
=TrustManagerFactory.getInstance("SunX509");           
            KeyStore ks
=KeyStore.getInstance("JKS");
            KeyStore tks
=KeyStore.getInstance("JKS");
            
//载入keystore
            ks.load(new FileInputStream(keyf),pass.toCharArray());
            tks.load(
new FileInputStream(trustf),pass.toCharArray());
            kmf.init(ks,pass.toCharArray());
            tmf.init(tks);
            ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(),
new SecureRandom());
            ss
=(SSLServerSocket)ctx.getServerSocketFactory().createServerSocket(port);
            ss.setNeedClientAuth(
true);//客户端要认证
        }catch (Exception e) {
      e.printStackTrace();
     }       
    }
   
    
/**
    * Ҏ名称QnewListener<p>
    * Ҏ功能Q创建服务器监听            <p>
    * 参数说明Q?nbsp;<p>
    * q回Qvoid <p>
    * 作者:luoc
    * 日期Q?005-6-30
    *
*/
    
private void newListener()
    {
        (
new Thread(this)).start();
    }
   
    
/**
     * 重蝲ҎQrun 处理客户端的h<p>
     * 参阅Q?/span>@see java.lang.Runnable#run() <p>
     * 参数说明Q?nbsp;<p>
    *
*/
    
public void run()
    {
        Socket socket
=null;
        
//accept a connection
        try
        {
            socket
=ss.accept();
        }
catch(IOException e)
        {
            System.out.println(
"Class Server died: " + e.getMessage());
         e.printStackTrace();
         
return;
        }
       
        
//create a new thread to accept the next connection
        newListener();
       
        
//process connection
        try
        {
            OutputStream out
=socket.getOutputStream();
            InputStream in
=socket.getInputStream();
            
//read data from client    
            byte buff[]=new byte [512]; 
            
byte data[]=new byte [1024];
            System.out.println(
"buff len="+buff.length);
            
int len=0;
            
int startpos=0;
            
while((len=in.read(buff))!=-1)
            {
                
//读联Ƣ数?nbsp;              
                if(len==1 && buff[0]==TranTool.DATA_END)//数据l束标志
                    break;
                data
=TranTool.byteDynExt(data,buff,len,startpos);
                System.out.println(
"read len:"+len+" data:["+new String(buff,0,len)+"]");
                startpos
+=len;
            }              
            System.out.println(
"recv from client:[");                                  
            System.out.print(
new String(data,0,startpos));           
            System.out.println(
"] data end.");
            
//send message to client
            out.write((startpos+" data success receive.").getBytes());
            out.write(TranTool.DATA_END);
            System.out.println(
"success echo is send.");
            out.flush();
        }
catch(IOException e)
        {
            e.printStackTrace();
      
return;
        }
finally
        {
            
try
            {
          socket.close();
         } 
catch (IOException e)
         {}
        }
    }   
   
    
/*全局变量*/  
    SSLServerSocket ss
=null;
   
    
//试函数
    public static void main(String args[])
    {
        System.out.println(
"init SSLServer");
        SSLServer srv
=new SSLServer();
        
new Thread(srv).start();      
        System.out.println(
"SSLServer listener begin.");
    }
}


C物 2008-02-13 22:08 发表评论
]]>
JAVA中SSL证书认证通讯-Certificationhttp://m.tkk7.com/libin2722/archive/2008/02/13/179834.htmlC物C物Wed, 13 Feb 2008 14:07:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179834.htmlhttp://m.tkk7.com/libin2722/comments/179834.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179834.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179834.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179834.html Q、客LQ公钥、私钥) 2、服务端Q公钥、私钥)

    服务端应?#8216;服务端私?#8217;?#8216;客户端公?#8217;与客L通讯Q客L应用‘客户端私?#8217;?#8216;服务端公?#8217;与服务端通讯?/p>

 如下介绍证书生成Q一套)Q?/span>

 Q、用JDK的keytool生成密钥store

    keytool -genkey -alias mykey -keystore srvstore

    输入密码Q程序中密码?#8216;123456’Q和相应的证书信?/p>

    Q、从srvstore中导?/span>

    keytool -export -alias mykey -file srvcert.crt -keystore srvstore

    输入刚才上面讄的密?/p>

    Q、将证书导到公钥?/span>

     keytool -import -alias mytrust -file srvcert.crt -keystore srvtrust

     输入公钥的密码(E序中密码ؓ‘123456’Q?/p>

C物 2008-02-13 22:07 发表评论
]]>
JAVA中SSL证书认证通讯-Clienthttp://m.tkk7.com/libin2722/archive/2008/02/13/179833.htmlC物C物Wed, 13 Feb 2008 14:05:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179833.htmlhttp://m.tkk7.com/libin2722/comments/179833.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179833.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179833.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179833.html/********************************************************************
 * 目名称    Qrochoc   <p>
 * 包名U?nbsp;     Qrochoc.net.security <p>
 * 文g名称    QSSLClient   <p>
 * ~写?nbsp;     QLuckyStar    <p>
 * ~写日期    Q?008-2-13    <p>
 * E序功能Q类Q描q?nbsp;Q安全通讯的客L       <p>
 *
 * E序变更日期   Q?br />  * 变更作?nbsp;   Q?br />  * 变更说明    Q?br /> *******************************************************************
*/
package rochoc.net.security;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

/**
 * cdQSSLClient  <p>
 * cLqͼ 安全通讯的客L<p>
 * ~写?nbsp;Qluoc<p>
 * ~写日期 Q?005-6-30<p>
 * 主要public成员变量Q?lt;p>
 * 主要publicҎQ?nbsp;  <p>
 *
*/

public class SSLClient
{
    
/**
     *构造函数说明:       <p>
     *参数说明Q?nbsp;  <p>
    *
*/
    
public SSLClient()
    {
        init();
    }
   
    
/**
    * Ҏ名称Qinit<p>
    * Ҏ功能Q初始化客户端Socket            <p>
    * 参数说明Q?nbsp;<p>
    * q回Qvoid <p>
    * 作者:luoc
    * 日期Q?005-6-30
    *
*/
    
public void init()
    {
        
//server socket's ip and port
        String host="localhost";
        
int port=2001;
        
//keystore path and password
        String keyf="..\\key\\mystore";
        String trustf
="..\\key\\srvtrust";
        String pass
="123456";
        
//set up a connection
        SSLSocketFactory ssf=null;
        
try
        {
            
//init context
            SSLContext ctx=SSLContext.getInstance("TLS");           
            KeyManagerFactory kmf
=KeyManagerFactory.getInstance("SunX509");
            TrustManagerFactory tmf
=TrustManagerFactory.getInstance("SunX509");           
            KeyStore ks
=KeyStore.getInstance("JKS");
            KeyStore tks
=KeyStore.getInstance("JKS");
            
//load keystore
            ks.load(new FileInputStream(keyf),pass.toCharArray());
            tks.load(
new FileInputStream(trustf),pass.toCharArray());
            kmf.init(ks,pass.toCharArray());
            tmf.init(tks);
            ctx.init(kmf.getKeyManagers(),tmf.getTrustManagers(),
new SecureRandom());
            System.out.println(
"load keystore success.");
            ssf
=ctx.getSocketFactory();
            
//create socket
            socket=(SSLSocket)ssf.createSocket(host,port);
            System.out.println(
"create socket success.");
            
//handshake
            socket.startHandshake();
            System.out.println(
"handshake success.");
        }
catch(Exception e)
        {
            System.out.println(
"establish connection error.");
            e.printStackTrace();
            
return;
        }
       
    }
   
    
/**
    * Ҏ名称QsendMessage<p>
    * Ҏ功能Q发送信?nbsp;           <p>
    * 参数说明Q?/span>@param msg <p>
    * q回Qvoid <p>
    * 作者:luoc
    * 日期Q?005-6-30
    *
*/
    
public void sendMessage(String msg)
    {
        
try
        {
            OutputStream out
=socket.getOutputStream();
            InputStream in
=socket.getInputStream();
            
//send message
            System.out.println("send message:["+msg+"]");
            out.write(msg.getBytes());
            out.write(TranTool.DATA_END);
            out.flush();
            
//receive message
            byte [] buff=new byte[1024];
            
int len=0;
            System.out.println(
"recv len:"+(len=in.read(buff)));
            System.out.println(
"receive from srv:[");           
            System.out.print(
new String(buff,0,len));           
            System.out.println(
"] receive end.");
        }
catch(IOException e)
        {
            e.printStackTrace();
        }
finally
        {
            
try
            {
                socket.close();
            }
catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
    
/*全局变量*/
    SSLSocket socket
=null;
   
    
//试函数
    public static void main(String args[])
    {
        SSLClient sc
=new SSLClient();
        String msg
="Hello SSL Server.";
        
if(args.length==1)
        {
            msg
=args[0];
        }
else
        {
            System.out.println(
"Useage:Please input the message you want to send.");
        }
        sc.sendMessage(msg);
    }
}


C物 2008-02-13 22:05 发表评论
]]>
Tomcat5SSL_ServerAndClient 的配|实?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179832.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:03:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179832.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179832.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179832.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179832.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/libin2722/services/trackbacks/179832.html</trackback:ping><description><![CDATA[<p>本文演示了在产生服务器端和客L证书之后, 如何?Tomcat 5.5 上进行双?SSL 的配|?<br /> <br /> 关于如何产生证书, 请参?<a ><strong><span style="color: #32328c; font-family: Trebuchet MS;">Tomcat5SSL_ServerAndClient</span></strong></a>.<br /> <br /> 首先, ?<a style="border-bottom: 1px dotted;" ><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> 本文所使用的例子可以在q里下蝲(使用右键菜单"目标另存?..") <ul> <li><a 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>W一? 服务器端证?ssl-test.net-tomcat.keystore 复制?Tomcat ?conf 目录?/h2> <ul> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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>W二? 修改 Tomcat ?conf 目录?server.xml 文g, 加上 SSL Connector 的定?/h2> <ul> <li><strong>注意:</strong> 如果需要用双?SSL(卛_L也要求用证?, 那么必须讄 clientAuth="true"; </li> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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>Z?HTTP Connector ?URLEncoding 也设|成 UTF-8, q个主要是ؓ了解决一些中文问?与本试验无关, 你也可以不配|?: </li> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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>W三? ?Tomcat ?webapps 目录下徏立一个新?Web 应用 "ssltest", ~辑 ssltest 目录?WEB-INF/web.xml, 配置 ssltest/ssl/ 目录下的内容为必通过 SSL 方式才能讉K</h2> <ul> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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>W四? 写两个完全一L试面, 分别攑֜ ssltest/ ?ssltest/ssl/ 目录? 按照上一步的配置, ssltest/ssl/ 目录下的试面必须通过 SSL 方式才能讉K</h2> <ul> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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>W五? 导入客户端证书到览器中(双击客户端证书文?"web-client.p12" 卛_导入 IE)</h2> <ul> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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&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&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&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&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&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&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>实际q行效果</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 方式讉K, 而通过 <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 目录下内容的讉K则会自动切换?<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 方式讉K? 客户端证书的 Subject 可以?jsp 面获得: <ul> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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&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&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 目录下的内容已经不能讉K? <ul> <li><img src="http://thinkbase.net/w/main/Wiki?action=action_view_attachment&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&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 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://m.tkk7.com/libin2722/aggbug/179832.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:03 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179832.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat5SSL_ServerAndClienthttp://m.tkk7.com/libin2722/archive/2008/02/13/179831.htmlC物C物Wed, 13 Feb 2008 13:59:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179831.htmlhttp://m.tkk7.com/libin2722/comments/179831.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179831.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179831.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179831.html配置适用于正式用环境下的Tomcat Web服务器双向SSL认证
关于如何使用Tomcat服务器实现双向SSL认证的文章很早就有了, 比较实用的文章可以看?IBM developerWorks 中国|站 2002q??配置Tomcat 4使用SSL( http://www-900.ibm.com/developerWorks/cn/security/se-tcssl/index.shtml ), 使用 google q可以搜索到很多cM的文?

? 是现在看? q些文章也有不之处, 一是只说明了在 Tomcat 4 服务器上的配|方? 与现在普遍用的 Tomcat 5 pd的配|方法有一定的差异, 其次, q些文章中的Ҏ大多是作ZU实验性的操作介绍, 如果用于实际Web服务器的产生证书环境, q是会存在一些问题的:
  • 生成的CAU钥(ca-key.pem)以及自签名根证书(ca-cert.pem)均ؓ没有加密的明? ׃一旦在服务器发? 以及客户端证书发布之? 根证书是不能随便修改? 那么在保没有加密的CAU钥以及自签名根证书时就会存在安全性问?如果别h得到你的CA根证? 他就可以替你生成客户端证书了);
  • 生成的服务器端证?server_keystore)不包括信ȝCA根证? 信Q的CA根证书被导入到JSSE的默认位|? 如果q行证书操作的计机和真正运行Web应用的不是同一台计机, 那么在安装服务器端证书的时? q需要在服务器上CA根证书导入JSSE默认位置;
  • 生成客户端证书的q程比较烦琐, 不方便批量进行客L证书的生?
  • 没有l一的配|文? 生成证书的过E中需要执行相当多的命? 可重复性差, 出错的可能性比较大.
针对以上的问? 在参?配置Tomcat 4使用SSL"q篇文章的基? 整理出由4个批处理命o和一个配|文件组成的证书工具? q个工具包考虑到在实际Web服务器环境下产生证书的需? 克服了上面提到的那些问题.

用到的Y件包

  • Tomcat 5.0.x
  • JSSE 中的 keytool 工具, ?JDK 1.4 中已l自带了q个工具, 因此, 只需要安?JDK1.4.x 卛_
  • openssl(openssl 已经被包含在q个工具包里面了, 不需要另外安? 参见工具包下?/span>)
  • cygwin ?sed ?echo 命o(q些命o文g已经包含在工具包里面, 不需要另外安? 参见工具包下?/span>)

配置及主要命令介l?/h3>
  • PATH 环境变量
    • 安装 JDK 之后, 需要将环境变量 JAVA_HOME 讄?JDK 的安装目? 同时?PATH 中加?%JAVA_HOME%"bin.
  • 工具包结?/strong>
    • .bin: 存放openssl 以及 cygwin ?sed ?echo 命o的可执行执行文g;
    • .etc: 存放pȝ的配|文? 其中最主要的配|文件是 .etc/config.cmd;
    • dist: q个目录存放产生的各U证?
    • work: 产生证书时用的临时文g的存攄? Z安全赯, 在每ơ证书相x作结束后, 清空q个目录;
    • step0,1,2,3 四个批处理命?/strong>: q四个命令分别用于证书各个方面的操作.
  • .etc/config.cmd
    • q个文g是系l的配置文g, 主要配置 CA根证?服务器证?客户端证?的相关信? 例如证书的distinguished name信息{等, 在生成证书之? 需要首先根据实际情冉|新这个配|文?
  • step0-ca-pfx.bat
    • 该命令生成CAU钥以及自签名根证书, 最后得到PKCS12格式的CA根证?PKCS12格式的CA根证书受密码保护, 因此有比较好的安全?;
    • 生成的PKCS12格式的CA根证书保存在 dist"ca-cert 目录? 在正式用的pȝ? q个证书文g(*.pfx)需要妥善保? 因ؓ以后的服务器证书和客L证书都需要依赖这个证? 其是客L证书, 如果丢失了CA根证? 无法发布新的客L证书? 而重新生成CA根证? 则需要重新生成服务器证书和客L证书, 在客L用户较多的情况下, 重新发布所有的客户端证书是有相当大的工作量;
    • 在执行这个命令的q程? 会提C入证书保护密? h意不要遗忘或者泄漏这个密? 否则根证书的安全会受到威?
  • step1-ca-prepare.bat
    • 该命令用于从PKCS12格式的CA根证书中导出CAU钥和未加密CA根证?
    • ׃安全原因, CA根证书^时以密码保护的PKCS12格式文g(*.pfx)存放, 那么如果需要用CA根证书来发布服务器证书或者客L证书? 首先需要执行这个命令得到CA根证书的未加密Ş?
    • 在执行这个命令的q程? 会出Cơ提C入根证书的保护密? 如果密码不正? q个命o不能执行成? 也就无法q行下面两步的发布证书的操作?
  • step2-server.bat
    • 该命令用于生成服务器端证?keystore文g);
    • 注意: CA根证书同时也会被导入到证书的keystore文g? q样在将q个证书应用到Tomcat Web服务器上的时候就不需要将CA根证书导入到JSSE的默认位|了;
    • q个命o必须在执?step1-ca-prepare.bat 之后才能正常q行.
  • step3-client.bat
    • q个命o用于发布客户端证?
    • Z便于扚w生成客户端证? q个命o支持命o行参? W??个参Cơؓ:
      • 客户端证书的名称(Common Name)
      • 客户端证书所属的l织(Organizational Unit Name)
      • 产生的PKS12格式客户端证书的导入密码, q个密码可以保护证书只能被知道密码的用户导入到浏览器
    • q个命o必须在执?step1-ca-prepare.bat 之后才能正常q行.
说明:当Web 服务器开始正式运行以? step0-ca-pfx.bat 命o是不能再ơ执行的, 如果需要重新发布服务器证书, 或者发布新的客L证书, 在执?step2-server.bat ?step3-client.bat 命o? 可以通过 step1-ca-prepare.bat 重新从保存的PKCS12格式CA根证书中导出CAU钥和未加密CA根证?

Tomcat 5 服务器配|?/h3> 参考配|方法如?
  • ?"step2-server.bat" 命o产生?dist"server 目录下的 keystore 文g(如果使用本工具包的默认配|? q个文g叫做"ssl-test.net-tomcat.keystore")复制?Tomcat 安装目录? conf 目录?
  • 修改 Tomcat 安装目录?conf 目录下的 "server.xml" 文g, 修改 <Service name="Catalina"> 包含?"Connector" 元素, CZ如下(仅供参?:
  <Service name="Catalina">
<Connector URIEncoding="UTF-8"
acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true"
port="8080" redirectPort="8443"
maxSpareThreads="75" maxThreads="150" minSpareThreads="25">
</Connector>
<Connector URIEncoding="UTF-8" port="8443"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" debug="0" scheme="https" secure="true"
clientAuth="true" sslProtocol="TLS"
keystoreFile="${catalina.home}/conf/ssl-test.net-tomcat.keystore"
keystorePass="openssl"
truststoreFile="${catalina.home}/conf/ssl-test.net-tomcat.keystore"
truststorePass="openssl"/>
......

启用双向 SSL ?Web 应用E序的配|?/h3>
  • 要启用双?SSL 认证, ?Web 应用E序?web.xml 中需要如下增加一些配|? auth-method=CLIENT-CERT 说明?以客L数字证书来确认用Lw䆾", transport-guarantee=CONFIDENTIAL 表示应用E序要求数据必须在一U?防止其他实体看到传输的内容的方式中传?.
    <login-config>
<!-- Authorization setting for SSL -->
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
<security-constraint>
<!-- Authorization setting for SSL -->
<web-resource-collection >
<web-resource-name >SSL</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
  • l过以上的配|之? 那么即用户是通过 http 讉K Web 应用E序? 览器也会自动切换到 https 方式q弹出选择客户端证书的对话?

如何使用客户端证书进行用户验?/h3>
  • 查看一些资料上提到客户端证书内容中 subject ?CN 部分可以?Tomcat ?Realm 中的用户集成, 不过一直没有尝试成?
  • ?web 应用E序? 可以通过 java 代码?request 对象中获? Ҏ Servlet Specifications, 使用request.getAttribute("javax.servlet.request.X509Certificate") 可以得?https h的客L证书链信? 其中W一个元素就是客L证书, 相应的示例代码如?

  • 客户端证书的 subject 是类?CN=client, OU=web, O=ssl-test.net, L=your_locality, ST=your_province, C=CN q样的字W串, 其中 CN=... 是客户端证书的用户名称, Web 应用E序可以通过q个字段来验?https h对应的用戯n份了.

工具包下?/h3>

q行界面(使用 Mozilla Firefox 1.0)

  • 没有安装证书时访?Web 应用E序被服务器拒绝
  • 讉K Web 应用E序时提C选择证书的对话框

比较复杂的问? 请到 Tomcat5SSL_ServerAndClient 常见问题 面讨论.

例子L
    String certSubject = null;
    X509Certificate[] certChain=
        (X509Certificate[])request.getAttribute("javax.servlet.request.X509Certificate");
    int len=certChain.length;
    if (len>0){
        X509Certificate cert = (X509Certificate)certChain[0];
        Principal pSubject = cert.getSubjectDN();
        certSubject = pSubject.getName();
    }


C物 2008-02-13 21:59 发表评论
]]>配置Tomcat 4使用SSLhttp://m.tkk7.com/libin2722/archive/2008/02/13/179828.htmlC物C物Wed, 13 Feb 2008 13:53:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179828.htmlhttp://m.tkk7.com/libin2722/comments/179828.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179828.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179828.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179828.html目前介绍配置Tomcat 4使用单向SSL认证(只验证服务器证书)的资料很多,q程也比较简单。但是由于配|其使用双向SSL认证(q需要验证客L个h证书)除了需要CA对证 书签名外Q还要从CA获得个h证书。有兌一问题Q目前结合具体web服务器来讲解如何操作的资料很。作者通过摸烦借助一些SSL工具在本地实C? 的CA功能Qƈ在此基础上配|成功了Tomcat的双向认证,希望能把其中的一些经验与大家׃n。不q受本h水^所限,文中隑օ会有错误与不当之处,敬请 大家谅解?/blockquote>

1QTomcat?/span>
Tomcat 是Apache Jakarta的子目之一Q作Z个优U的开源web应用服务器,全面支持jsp1.2以及servlet2.3规范。因其技术先q、性能E_Q而且? 费,因而深受Java爱好者的喜爱q得C部分软g开发商的认可,成ؓ目前比较行的web应用服务器?/p>

2QSSL(Server Socket Layer)?/span>
? |络上信息在?宿的传递过E中会经q其它的计算机。一般情况下Q中间的计算Z会监听\q的信息。但在用网上银行或者进行信用卡交易的时候有可能被监 视,从而导致个人隐U的泄露。由于Internet和Intranet体系l构的原因,L某些够读取ƈ替换用户发出的信息。随着|上支付的不断发 展,Z对信息安全的要求来高。因此Netscape公司提出了SSL协议Q旨在达到在开攄l?Internet)上安全保密地传输信息的目的,q? U协议在WEB上获得了q泛的应用。之后IETF(www.ietf.org)对SSL作了标准化,即RFC2246Qƈ其UCؓTLS QTransport Layer SecurityQ,从技术上ԌTLS1.0与SSL3.0的差别非常微?

3QSSL工作原理
SSL协议使用不对U加密技术实C话双方之间信息的安全传递。可以实C息传递的保密性、完整性,q且会话双方能鉴别对方n份。不同于常用的http协议Q我们在与网站徏立SSL安全q接时用https协议Q即采用https://ip:port/的方式来讉K?/p>

当我们与一个网站徏立httpsq接Ӟ我们的浏览器与Web Server之间要经q一个握手的q程来完成n份鉴定与密钥交换Q从而徏立安全连接。具体过E如下:

  1. 用户览器将其SSL版本受加密设|参数、与session有关的数据以及其它一些必要信息发送到服务器?
  2. 服务器将其SSL版本受加密设|参数、与session有关的数据以及其它一些必要信息发送给览器,同时发给览器的q有服务器的证书。如果配|服务器的SSL需要验证用戯n份,q要发出h要求览器提供用戯书?
  3. 客户端检查服务器证书Q如果检查失败,提示不能建立SSLq接。如果成功,那么l箋?
  4. 客户端浏览器为本ơ会话生成pre-master secretQƈ其用服务器公钥加密后发送给服务器?
  5. 如果服务器要求鉴别客戯n份,客户端还要再对另外一些数据签名后q将其与客户端证书一起发送给服务器?
  6. 如果服务器要求鉴别客戯n份,则检查签|客戯书的CA是否可信。如果不在信d表中Q结束本ơ会话。如果检查通过Q服务器用自qU钥解密收到的pre-master secretQƈ用它通过某些法生成本次会话的master secret?
  7. 客户端与服务器均使用此master secret生成本次会话的会话密?对称密钥)。在双方SSL握手l束后传递Q何消息均使用此会话密钥。这样做的主要原因是对称加密比非对称加密的运量低一个数量以上Q能够显著提高双方会话时的运速度?
  8. 客户端通知服务器此后发送的消息都用这个会话密钥进行加密。ƈ通知服务器客L已经完成本次SSL握手?
  9. 服务器通知客户端此后发送的消息都用这个会话密钥进行加密。ƈ通知客户端服务器已经完成本次SSL握手?
  10. 本次握手q程l束Q会话已l徏立。双方用同一个会话密钥分别对发送以及接受的信息q行加、解密?/li>

4Q配|Tomcat 4.x 使用SSL

4.1 用到的Y件包

  • Tomcat 4.0.2
    用途:Web Server?br /> 下蝲Q?a style="border-bottom: 1px dotted;" target="_blank">http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.3/bin/
  • JSSE 1.0,2
    用途:用来产生Tocmcat使用的秘钥对(keystore)?br /> 下蝲Q?http://java.sun.com/products/jsse/
  • Openssl 0.9.9.6
    用途:用来产生CA证书、签名ƈ生成IE可导入的PKCS#12格式U钥?br /> 下蝲Q?a style="border-bottom: 1px dotted;" target="_blank">http://www.openssl.org/

以上工具的安装过E可以参考自带的帮助Q本文就不再详细描述了?/p>

4.2 建立自己的CA

4.2.1 建立工作目录
mkdir ca

4.2.2 生成CAU钥以及自签名根证书
4.2.2.1 生成CAU钥
openssl genrsa -out ca"ca-key.pem 1024

4.2.2.2 生成待签名证?/strong>
openssl req -new -out ca"ca-req.csr -key ca"ca-key.pem

4.2.2.3 用CAU钥q行自签?/strong>
openssl x509 -req -in ca"ca-req.csr -out ca"ca-cert.pem -signkey ca"ca-key.pem -days 365

4.3 讄Tomcat 4.x
在本文中用符?%JDK_HOME%"来表CJDK的安装位|,用符?%TCAT_HOME%" 表示Tomcat的安装位|?/p>

4.3.1建立工作目录
mkdir server

4.3.2 生成server端证?/strong>
4.3.2.1 生成KeyPair
%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

4.3.2.2 生成待签名证?/strong>
%JDK_HOME%"bin"keytool -certreq -alias tomcat_server -sigalg MD5withRSA -file server"server.csr -keypass changeit -keystore server"server_keystore -storepass changeit

4.3.2.3 用CAU钥q行{֐
openssl x509 -req -in server"server.csr -out server"server-cert.pem -CA ca"ca-cert.pem -CAkey ca"ca-key.pem -days 365

4.3.2.4 导入信Q的CA根证书到JSSE的默认位|?%JDK_ROOT %/jre/security/cacerts)
%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

4.3.2.5 把CA{֐后的server端证书导入keystore
%JDK_HOME%"bin"keytool -import -v -trustcacerts -storepass changeit -alias tomcat_server -file server"server-cert.pem -keystore server"server_keystore

4.3.2.6 查看server端证?/strong>
keytool -list -keystore %JDK_HOME%"jre"lib"security"cacerts
keytool -list -keystore server"server_keystore

4.3.3 修改server.xml使Tomcat支持SSL
首先扑ֈ以下内容Q去掉对其的注释。然后参照红色部分修攏V如果配|Tomcat不验证客戯n份,可以讄clientAuth="false"?
  <Connector className="org.apache.catalina.connector.http.HttpConnector"
port="8443" minProcessors="5" maxProcessors="75"
enableLookups="true"
acceptCount="10" debug="0" scheme="https" secure="true">
<Factory className="org.apache.catalina.net.SSLServerSocketFactory"
clientAuth="true" protocol="TLS"
keystoreFile="%TCAT_HOME%/conf/server_keystore" keystorePass="changeit"
/>
</Connector>
然后把文件server"server_keystore复制到目?TCAT_HOME%"conf"下?/p>

4.4 在IE中安装个?/strong>
4.4.1 建立工作目录
mkdir client

4.4.2 生成clientU钥q用CAU钥{֐

4.4.2.1 生成clientU钥
openssl genrsa -out client"client-key.pem 1024

4.4.2.2 生成待签名证?/strong>
openssl req -new -out client"client-req.csr -key client"client-key.pem

4.4.2.3 用CAU钥q行{֐
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

4.4.2.4 生成client端的个h证书
因ؓJSSE1.0.2没有完全实现了对PKCS#12格式文g的操?只能dQ不能输?Q所以在q里需要用openssl制作client端的个h证书(包含U钥)?br /> openssl pkcs12 -export -clcerts -in client"client.crt -inkey client"client-key.pem -out client"client.p12

4.4.2.5 安装信Q的根证书
把ca"ca-key.pem改名为ca"ca-key.cerQ在client端的IE中?工具 ' Internet选项 ' 内容 ' 证书 ' 导入"把我们生成的CA根证书导入,使其成ؓ用户信Q的CA?/p>

4.4.3 安装个h证书
把client.p12导入到client端的IE中作Z书,导入q程?.4.2.5?/p>

4.5 用IE览器用SSL协议讉KTomcat

4.5.1 启动Tomcat 4.x
执行%TCAT_HOME%"bin"startup.bat启动Tomcat 4.x

4.5.2 用IE讉KTomcat 4.x
在IE览器的地址栏中输入https://localhost:8443Q如果前面的操作都正的话,应该可以看到Tomcat的欢q页面。同时状态栏上的锁处于闭合状态,表示您已l成功地与服务器建立了要求客L验证的SSL安全q接?/p>

5 l论
? 上我们实C为Tomcat 4.x配置要求客户端验证的SSL的全q程。对于其它类型的服务器,例如ApacheQNetscape Enterprise Server, WebsphereQWeblogic{,一般只是在服务器端保存证书的方式略有不同,但它们的原理都是cM的,配置时可以在本文中办法的基础上做出相? 的调整?/p>

参考资?/strong>



C物 2008-02-13 21:53 发表评论
]]>
վ֩ģ壺 žžƵ| AëƬA| պ| һ߲Ʒ߲Ʒ| ˳վѲ| ˿1ҳ| ߹ۿHַ| ޴ɫ߹ۿ| Ƶۿ| ޹Ʒۺ˳ۺվ| 91Ʒȫѹۿ߲| ޸Ƶһ| ëƬѹۿ| һ岻| Ƶѹۿ| þ޾ƷƷ | ëƬַ߹ۿĻ| ³³ƵѲ| ȫԼƵ| һëƬѲ| avҹƷһ| 18δֹѹۿ| ޹bvվ| ŮڵƵ | Ʒһ| ŮվƵ | ؼëƬaaaaëƬ| ƷۺϾþĻ| 99þþùƷ| Ƭ߹ۿ| ҹav뾫Ʒ| ߹ۿƵ| ˵þþþƷ| ޹㽶þþþþ| ˳ɼƵ߹ۿ| ޹ŮƷþþþ| ŮڵƵվ| ˿wwwѸ| ޹˾Ʒһ | ھƷþþþþþ| 99Ƶ|