﻿<?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-Steady's Java Zone-随笔分类-Java</title><link>http://www.blogjava.net/steady/category/23663.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 16 Oct 2007 08:50:54 GMT</lastBuildDate><pubDate>Tue, 16 Oct 2007 08:50:54 GMT</pubDate><ttl>60</ttl><item><title>禁用JavaWeb应用中URL上包含的jsessionid</title><link>http://www.blogjava.net/steady/archive/2007/09/08/143664.html</link><dc:creator>steady</dc:creator><author>steady</author><pubDate>Sat, 08 Sep 2007 12:13:00 GMT</pubDate><guid>http://www.blogjava.net/steady/archive/2007/09/08/143664.html</guid><wfw:comment>http://www.blogjava.net/steady/comments/143664.html</wfw:comment><comments>http://www.blogjava.net/steady/archive/2007/09/08/143664.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/steady/comments/commentRss/143664.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/steady/services/trackbacks/143664.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt">Java Web 应用似乎总有这样的情况，有事没事总是要在 URL 后面加上个 jsessionid，而且似乎不能使用配置的方式直接禁用 URL 传递 sessionid，这样，就比较容易造成安全性的问题，或者在浏览器地址栏里留下一堆很不好看的地址，在 Struts2 中，使用了 url 标签的所有<a style="color: #8ab037" href="http://www.linkedcast.cn" target="_blank">链接</a>，甚至 CSS, JS 这样的东西，都会加上 jsessionid，如何去禁用呢，搜索国内的相关文章，无功而返，询问我们过去的架构师，也没有做过，只好想办法去找国外的网站，找到了这样的一篇文章。<br />
<br />
http://randomcoder.com/articles/jsessionid-considered-harmful<br />
<br />
通过加入 Filter 的方式过滤掉 URL 中包含的 jsessionid，再重新包装 Response 返回给浏览器。<br />
<br />
因为没有太多东西，就不多解释了，大家拿了用就可以了。<br />
<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.</span><span style="color: #000000">*</span><span style="color: #000000">;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.http.HttpServletRequest;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.http.HttpServletResponse;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.http.HttpServletResponseWrapper;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;javax.servlet.http.HttpSession;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;java.io.IOException;<br />
<br />
</span><span style="color: #008000">/**</span><span style="color: #008000"><br />
&nbsp;*&nbsp;Servlet&nbsp;filter&nbsp;which&nbsp;disables&nbsp;URL-encoded&nbsp;session&nbsp;identifiers.<br />
&nbsp;*&nbsp;&lt;p/&gt;<br />
&nbsp;*&nbsp;&lt;pre&gt;<br />
&nbsp;*&nbsp;Copyright&nbsp;(c)&nbsp;2006,&nbsp;Craig&nbsp;Condit.&nbsp;All&nbsp;rights&nbsp;reserved.<br />
&nbsp;*&nbsp;&lt;p/&gt;<br />
&nbsp;*&nbsp;Redistribution&nbsp;and&nbsp;use&nbsp;in&nbsp;source&nbsp;and&nbsp;binary&nbsp;forms,&nbsp;with&nbsp;or&nbsp;without<br />
&nbsp;*&nbsp;modification,&nbsp;are&nbsp;permitted&nbsp;provided&nbsp;that&nbsp;the&nbsp;following&nbsp;conditions&nbsp;are&nbsp;met:<br />
&nbsp;*&nbsp;&lt;p/&gt;<br />
&nbsp;*&nbsp;&nbsp;&nbsp;*&nbsp;Redistributions&nbsp;of&nbsp;source&nbsp;code&nbsp;must&nbsp;retain&nbsp;the&nbsp;above&nbsp;copyright&nbsp;notice,<br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;list&nbsp;of&nbsp;conditions&nbsp;and&nbsp;the&nbsp;following&nbsp;disclaimer.<br />
&nbsp;*&nbsp;&nbsp;&nbsp;*&nbsp;Redistributions&nbsp;in&nbsp;binary&nbsp;form&nbsp;must&nbsp;reproduce&nbsp;the&nbsp;above&nbsp;copyright&nbsp;notice,<br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;list&nbsp;of&nbsp;conditions&nbsp;and&nbsp;the&nbsp;following&nbsp;disclaimer&nbsp;in&nbsp;the&nbsp;documentation<br />
&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and/or&nbsp;other&nbsp;materials&nbsp;provided&nbsp;with&nbsp;the&nbsp;distribution.<br />
&nbsp;*&nbsp;&lt;p/&gt;<br />
&nbsp;*&nbsp;THIS&nbsp;SOFTWARE&nbsp;IS&nbsp;PROVIDED&nbsp;BY&nbsp;THE&nbsp;COPYRIGHT&nbsp;HOLDERS&nbsp;AND&nbsp;CONTRIBUTORS&nbsp;"AS&nbsp;IS"<br />
&nbsp;*&nbsp;AND&nbsp;ANY&nbsp;EXPRESS&nbsp;OR&nbsp;IMPLIED&nbsp;WARRANTIES,&nbsp;INCLUDING,&nbsp;BUT&nbsp;NOT&nbsp;LIMITED&nbsp;TO,&nbsp;THE<br />
&nbsp;*&nbsp;IMPLIED&nbsp;WARRANTIES&nbsp;OF&nbsp;MERCHANTABILITY&nbsp;AND&nbsp;FITNESS&nbsp;FOR&nbsp;A&nbsp;PARTICULAR&nbsp;PURPOSE<br />
&nbsp;*&nbsp;ARE&nbsp;DISCLAIMED.&nbsp;IN&nbsp;NO&nbsp;EVENT&nbsp;SHALL&nbsp;THE&nbsp;COPYRIGHT&nbsp;OWNER&nbsp;OR&nbsp;CONTRIBUTORS&nbsp;BE<br />
&nbsp;*&nbsp;LIABLE&nbsp;FOR&nbsp;ANY&nbsp;DIRECT,&nbsp;INDIRECT,&nbsp;INCIDENTAL,&nbsp;SPECIAL,&nbsp;EXEMPLARY,&nbsp;OR<br />
&nbsp;*&nbsp;CONSEQUENTIAL&nbsp;DAMAGES&nbsp;(INCLUDING,&nbsp;BUT&nbsp;NOT&nbsp;LIMITED&nbsp;TO,&nbsp;PROCUREMENT&nbsp;OF<br />
&nbsp;*&nbsp;SUBSTITUTE&nbsp;GOODS&nbsp;OR&nbsp;SERVICES;&nbsp;LOSS&nbsp;OF&nbsp;USE,&nbsp;DATA,&nbsp;OR&nbsp;PROFITS;&nbsp;OR&nbsp;BUSINESS<br />
&nbsp;*&nbsp;INTERRUPTION)&nbsp;HOWEVER&nbsp;CAUSED&nbsp;AND&nbsp;ON&nbsp;ANY&nbsp;THEORY&nbsp;OF&nbsp;LIABILITY,&nbsp;WHETHER&nbsp;IN<br />
&nbsp;*&nbsp;CONTRACT,&nbsp;STRICT&nbsp;LIABILITY,&nbsp;OR&nbsp;TORT&nbsp;(INCLUDING&nbsp;NEGLIGENCE&nbsp;OR&nbsp;OTHERWISE)<br />
&nbsp;*&nbsp;ARISING&nbsp;IN&nbsp;ANY&nbsp;WAY&nbsp;OUT&nbsp;OF&nbsp;THE&nbsp;USE&nbsp;OF&nbsp;THIS&nbsp;SOFTWARE,&nbsp;EVEN&nbsp;IF&nbsp;ADVISED&nbsp;OF&nbsp;THE<br />
&nbsp;*&nbsp;POSSIBILITY&nbsp;OF&nbsp;SUCH&nbsp;DAMAGE.<br />
&nbsp;*&nbsp;&lt;/pre&gt;<br />
&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br />
@SuppressWarnings(</span><span style="color: #000000">"</span><span style="color: #000000">deprecation</span><span style="color: #000000">"</span><span style="color: #000000">)<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;DisableUrlSessionFilter&nbsp;</span><span style="color: #0000ff">implements</span><span style="color: #000000">&nbsp;Filter&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Filters&nbsp;requests&nbsp;to&nbsp;disable&nbsp;URL-based&nbsp;session&nbsp;identifiers.<br />
&nbsp;&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;doFilter(ServletRequest&nbsp;request,&nbsp;ServletResponse&nbsp;response,&nbsp;FilterChain&nbsp;chain)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;IOException,&nbsp;ServletException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;skip&nbsp;non-http&nbsp;requests</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&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">(request&nbsp;</span><span style="color: #0000ff">instanceof</span><span style="color: #000000">&nbsp;HttpServletRequest))&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chain.doFilter(request,&nbsp;response);<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 />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletRequest&nbsp;httpRequest&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(HttpServletRequest)&nbsp;request;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponse&nbsp;httpResponse&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(HttpServletResponse)&nbsp;response;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;clear&nbsp;session&nbsp;if&nbsp;session&nbsp;id&nbsp;in&nbsp;URL</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(httpRequest.isRequestedSessionIdFromURL())&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpSession&nbsp;session&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;httpRequest.getSession();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(session&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">)&nbsp;session.invalidate();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;wrap&nbsp;response&nbsp;to&nbsp;remove&nbsp;URL&nbsp;encoding</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpServletResponseWrapper&nbsp;wrappedResponse&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;HttpServletResponseWrapper(httpResponse)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;encodeRedirectUrl(String&nbsp;url)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;url;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;encodeRedirectURL(String&nbsp;url)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;url;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;encodeUrl(String&nbsp;url)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;url;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;String&nbsp;encodeURL(String&nbsp;url)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;url;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;process&nbsp;next&nbsp;request&nbsp;in&nbsp;chain</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;chain.doFilter(request,&nbsp;wrappedResponse);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Unused.<br />
&nbsp;&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(FilterConfig&nbsp;config)&nbsp;</span><span style="color: #0000ff">throws</span><span style="color: #000000">&nbsp;ServletException&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Unused.<br />
&nbsp;&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;destroy()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>
<br />
-------------------------------------------------------------------------------------------------<br />
顺便做个小<a style="color: #8ab037" href="http://www.linkedcast.cn" target="_blank">广告</a> <a href="http://www.linkedcast.cn">链客中国</a>&nbsp;<a href="http://www.linkedcast.cn">www.linkedcast.cn</a>&nbsp;上线运行，欢迎广大 Blogger 使用</span> <br />
<a href="http://www.linkedcast.cn" target="_blank"><img alt="链客中国，写文章也可以赚钱哦" src="http://www.linkedcast.cn/website/monitor/access.do?id=9d19090d1a00565f" border="0" /></a> 
   <img src ="http://www.blogjava.net/steady/aggbug/143664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/steady/" target="_blank">steady</a> 2007-09-08 20:13 <a href="http://www.blogjava.net/steady/archive/2007/09/08/143664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 整合 Discuz 论坛 (1)</title><link>http://www.blogjava.net/steady/archive/2007/08/11/136046.html</link><dc:creator>steady</dc:creator><author>steady</author><pubDate>Sat, 11 Aug 2007 09:30:00 GMT</pubDate><guid>http://www.blogjava.net/steady/archive/2007/08/11/136046.html</guid><wfw:comment>http://www.blogjava.net/steady/comments/136046.html</wfw:comment><comments>http://www.blogjava.net/steady/archive/2007/08/11/136046.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/steady/comments/commentRss/136046.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/steady/services/trackbacks/136046.html</trackback:ping><description><![CDATA[<span style="FONT-SIZE: 10pt">因为有一个 Struts2 网站发布，需要整合一个论坛来使用，公司的一个项目过去曾经整合过一个英文论坛，但似乎不能满足我们的需求，需要找一个成熟稳定的中文论坛，与我们的系统结合。<br><br>最终选择了 Discuz 作为我们的论坛系统，主要是因为它提供了一套可用的 Passport API，来直接与我们现有系统进行整合。<br><br>下面摘录 Discuz 文档中的内容来说明整合原理，随后的几篇中，将详细描述具体的整合过程。<br><br>
<p class=subtitle>假设已设置如下变量或参数
<p>
<ul>
    <li>挂接 Discuz! Passport 的应用程序假设为一套 PHP 语言编写的 CMS 系统
    <li>Discuz! 的 URL 为 http://www.myforums.com
    <li>应用程序的 URL 为 http://www.mywebsite.com
    <li>应用程序的注册页面为 http://www.mywebsite.com/register.php
    <li>应用程序的登录页面为 http://www.mywebsite.com/login.php?action=login
    <li>应用程序的退出页面为 http://www.mywebsite.com/login.php?action=logout</li>
</ul>
<p class=subtitle>开启通行证后的用户登录流程
<p>
<ul type=1>
    <li>如果用户在论坛点击&#8220;登录&#8221;，则转向到事先设置好的应用程序登录页面（http://www.mywebsite.com/login.php?action=login），并在登录页面的 URL 中加入参数 forward（加入 forward 后的链接例如 http://www.mywebsite.com/login.php?action=login&amp;forward=http://www.myforums.com/index.php），用于在登录后将用户导向到指定的 URL。<br><br>
    <li>应用程序收到此请求后，按照惯例生成表单，并<u>增加一个表单变量，将 GET 方式传递过来的 forward 参数通过表单进行传递。</u><br><br>
    <li>用户在应用程序的表单中填写登录信息，并提交到应用程序的登录验证程序。应用程序验证用户提交的用户名和密码的合法性：
    <ul><br>
        <li>如果不通过：提示用户名密码错误，要求其返回上一页重新填写。<br><br>
        <li>如果通过，需要进行如下操作：
        <ul><br>
            <li>设置自身 Cookie 或 Session，使得应用程序自身处于登录状态。<br><br>
            <li><u>检查表单中是否提交了 forward 变量，如有，则意味着登录请求可能是由论坛而来，将此变量传递到后面的请求中。如没有，自行生成 forward 变量，使得论坛登录后能够跳转回到应用程序中。</u><br><br>
            <li><u>通过 header('Location: http://www.myforums.com/api/passport.php?action=login&amp;auth=xxx&amp;forward=http://yyy&amp;verify=zzz') 的方式，将登录请求传递到论坛进行处理。其中 auth 用来将用户信息与资料以特定的格式，加密传递给论坛，forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址，verify 用于验证前面两个变量的有效性。auth、forward、verify 格式与结构将在后面进行说明。</u></li>
        </ul>
        </li>
    </ul>
    <br><br>
    <li>Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后，进行如下操作：
    <ul><br>
        <li>根据 verify 判断 auth 和 forward 变量是否合法，如合法则继续，否则终止。<br><br>
        <li>将 auth 根据既定算法解密，并还原成数组，数组的内容与格式将在后面进行说明。根据数组中的内容，检查此用户是否存在。如存在，则根据上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在，则使用数组中的信息 INSERT 到论坛用户资料表中。<br><br>
        <li>论坛设置 Cookie 或 Session，使得论坛自身处于登录状态。<br><br>
        <li>根据应用程序反馈的 forward 值，通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。</li>
    </ul>
    <br><br>
    <li>至此，登录流程结束</li>
</ul>
<p class=subtitle>开启通行证后的用户退出流程
<p>
<ul type=1>
    <li>如果用户在论坛点击&#8220;退出&#8221;，则转向到事先设置好的应用程序退出页面（http://www.mywebsite.com/login.php?action=logout），并在登录页面的 URL 中加入参数 forward（例如 http://www.mywebsite.com/login.php?action=login&amp;forward=http://www.myforums.com/index.php），用于在退出后将用户导向到指定的 URL。<br><br>
    <li>应用程序收到此请求后，清除自身 Cookie 或 Session，使得应用程序自身处于非登录状态。<br><br>
    <li><u>检查是否提交了 forward 变量，如有，则意味着登录请求可能是由论坛而来，将此变量传递到后面的请求中。如没有，自行生成 forward 变量，使得论坛登录后能够跳转回到应用程序中</u>。<br><br>
    <li><u>通过 header('Location: http://www.myforums.com/api/passport.php?action=logout&amp;forward=http://yyy&amp;verify=zzz') 的方式，将退出请求传递到论坛进行处理。其中 forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址，verify 用于验证 forward 变量的有效性。forward、verify 格式与结构将在后面进行说明</u>。<br><br>
    <li>Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后，进行如下操作：
    <ul><br>
        <li>根据 verify 判断 forward 变量是否合法，如合法则继续，否则终止。<br><br>
        <li>清楚论坛的 Cookie 或 Session，使得论坛自身处于非登录状态。<br><br>
        <li>根据应用程序反馈的 forward 值，通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL。</li>
    </ul>
    <br><br>
    <li>至此，退出流程结束。</li>
</ul>
<p class=subtitle>开启通行证后的用户注册流程
<p>
<ul type=1>
    <li>如果用户在论坛点击&#8220;注册&#8221;，则转向到事先设置好的应用程序注册页面（<a href="http://www.mywebsite.com/register.php"><u><font color=#0000ff>http://www.mywebsite.com/register.php</font></u></a>），并在注册页面的 URL 中加入参数 forward（例如 http://www.mywebsite.com/register.php?forward=http://www.myforums.com/index.php），用于在注册后将用户导向到指定的 URL<br><br>
    <li>应用程序收到此请求后，按照惯例生成表单，并<u>增加一个表单变量，将 GET 方式传递过来的 forward 参数通过表单进行传递</u><br><br>
    <li>用户在应用程序的表单中填写注册信息，并提交到应用程序的注册验证程序。应用程序验证用户提交信息的完整性和合法性：
    <ul><br>
        <li>如果不通过：提示其问题所在，要求其返回上一页重新填写<br><br>
        <li>如果通过，需要进行如下操作：
        <ul><br>
            <li>将用户资料插入到应用程序自身用户数据库中<br><br>
            <li>设置自身 Cookie 或 Session，使得应用程序自身处于登录状态<br><br>
            <li><u>检查表单中是否提交了 forward 变量，如有，则意味着注册请求可能是由论坛而来，将此变量传递到后面的请求中。如没有，自行生成 forward 变量，使得论坛注册后能够跳转回到应用程序中</u><br><br>
            <li><u>通过 header('Location: http://www.myforums.com/api/passport.php?action=login&amp;auth=xxx&amp;forward=http://yyy&amp;verify=zzz') 的方式，将注册请求传递到论坛进行处理。其中 auth 用来将用户信息与资料以特定的格式，加密传递给论坛，forward 用于告知论坛 Passport API 完成自身操作后转向到的 URL 地址，verify 用于验证前面两个变量的有效性。auth、forward、verify 格式与结构将在后面进行说明</u></li>
        </ul>
        </li>
    </ul>
    <br><br>
    <li>Discuz! Passport API 在接收到由应用程序通过 header() 提交过来的请求后，进行如下操作：
    <ul><br>
        <li>根据 verify 判断 auth 和 forward 变量是否合法，如合法则继续，否则终止<br><br>
        <li>将 auth 根据既定算法解密，并还原成数组，数组的内容与格式将在后面进行说明。根据数组中的内容，检查此用户是否存在。如存在，则根据上述数组中的内容 UPDATE 论坛中相应的用户资料。如不存在，则使用数组中的信息 INSERT 到论坛用户资料表中<br><br>
        <li>论坛设置 Cookie 或 Session，使得论坛自身处于登录状态<br><br>
        <li>根据应用程序反馈的 forward 值，通过 header('Location: http://xxx') 的形式将页面跳转到 forward 变量指定的 URL</li>
    </ul>
    <br><br>
    <li>至此，注册流程结束
    <p><strong>本部分中，加下划线显示的部分，是需要对您的应用程序进行更改的部分，事实上，这部分更改会非常容易和方便。</strong></p>
    </li>
</ul>
</span>
 <img src ="http://www.blogjava.net/steady/aggbug/136046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/steady/" target="_blank">steady</a> 2007-08-11 17:30 <a href="http://www.blogjava.net/steady/archive/2007/08/11/136046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quartz 项目应用笔记-补充</title><link>http://www.blogjava.net/steady/archive/2007/08/03/134149.html</link><dc:creator>steady</dc:creator><author>steady</author><pubDate>Fri, 03 Aug 2007 01:00:00 GMT</pubDate><guid>http://www.blogjava.net/steady/archive/2007/08/03/134149.html</guid><wfw:comment>http://www.blogjava.net/steady/comments/134149.html</wfw:comment><comments>http://www.blogjava.net/steady/archive/2007/08/03/134149.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/steady/comments/commentRss/134149.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/steady/services/trackbacks/134149.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt">Reschedule<br>rescheduleJob(<a onclick="javascript:tagshow(event, 'String');" href="javascript:;" target=_self><u><strong><font color=#000066>String</font></strong></u></a> triggerName, String groupName, Trigger newTrigger)</p>
<p style="FONT-SIZE: 10pt">在进行 reschedule 操作的时候，我们通常只需要修改 Trigger 的时间，这时候我们只需要重新 new 一个含有新的 <a onclick="javascript:tagshow(event, 'Schedule');" href="javascript:;" target=_self><u><strong><font color=#000066>Schedule</font></strong></u></a> 时间的 Trigger 对象，reschedule 一下就可以了。</p>
<p style="FONT-SIZE: 10pt">Unschedule<br>unscheduleJob(String triggerName, String groupName)</p>
<p style="FONT-SIZE: 10pt">进行 unschedule 的时候，我们只需要知道名字和 group 就可以了。</p>
<p style="FONT-SIZE: 10pt">进行 Schedule 操作前后，Database 中的相关数据都会被更改，在执行 unschedule 或者该 schedule 已经执行过，数据库中的 trigger 信息都会被删除。</p>
 <img src ="http://www.blogjava.net/steady/aggbug/134149.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/steady/" target="_blank">steady</a> 2007-08-03 09:00 <a href="http://www.blogjava.net/steady/archive/2007/08/03/134149.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Quartz 项目应用笔记</title><link>http://www.blogjava.net/steady/archive/2007/08/02/134017.html</link><dc:creator>steady</dc:creator><author>steady</author><pubDate>Thu, 02 Aug 2007 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/steady/archive/2007/08/02/134017.html</guid><wfw:comment>http://www.blogjava.net/steady/comments/134017.html</wfw:comment><comments>http://www.blogjava.net/steady/archive/2007/08/02/134017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/steady/comments/commentRss/134017.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/steady/services/trackbacks/134017.html</trackback:ping><description><![CDATA[<p style="FONT-SIZE: 10pt"><a onclick="javascript:tagshow(event, 'Quartz');" href="javascript:;" target=_self><u><strong><font color=#000066>Quartz</font></strong></u></a> 是一个强大的企业级 <a onclick="javascript:tagshow(event, 'Schedule');" href="javascript:;" target=_self><u><strong><font color=#000066>Schedule</font></strong></u></a> 工具，也是目前最好的<a onclick="javascript:tagshow(event, '%BF%AA%D4%B4');" href="javascript:;" target=_self><u><strong><font color=#000066>开源</font></strong></u></a> Schedule 工具，最近因为项目的需要，简单的用到了 Quartz 的一些功能，对项目中使用 Quartz 的一些问题做简单的记录。</p>
<p style="FONT-SIZE: 10pt">在 Quartz 的应用中，我们用到了以下的一些东西，ScheduleFactory, Scheduler, Job, JobDetail, Trigger，简单说明一下他们的用途。</p>
<p style="FONT-SIZE: 10pt">SchedulerFactory 是 Scheduler 的工厂，我们可以从中获得受工厂管理的 Scheduler 对象。<br><br>SchedulerFactory scheduleFactory = new StdSchedulerFactory();<br>Scheduler scheduler = scheduleFactory.getScheduler();</p>
<p style="FONT-SIZE: 10pt">Scheduler 是一个计划集，其中可以包含多个 JobDetail 和 Trigger 组成的计划任务。<br>我们可以从 SchedulerFactory 中取得 Scheduler。</p>
<p style="FONT-SIZE: 10pt">接口Job是每个业务上需要执行的任务需要实现的接口，该接口只有一个方法：<br><br>public interface Job {<br>&nbsp;&nbsp;&nbsp; public void execute(JobExecutionContext context)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws JobExecutionException;<br>}<br><br>我们可以在里面定义我们的 Job 执行逻辑，比如清除过期数据，更新缓存等。</p>
<p style="FONT-SIZE: 10pt">JobDetail描述了一个任务具体的信息，比如名称，组名等等。<br>JobDetail jobDetail = new JobDetail("SayHelloWorldJob", Scheduler.DEFAULT_GROUP, SayHelloWorldJob.class);<br>在上面的构造方法中，第一个是任务的名称，第二个是组名，第三个就是实际当任务需要执行的回调类。</p>
<p style="FONT-SIZE: 10pt">Trigger顾名思义就是触发器，Quartz有个很好的想法就是分离了任务和任务执行的条件。Trigger就是控制任务执行条件的类，当Trigger认为执行条件满足的时刻，Trigger会通知相关的Job去执行。分离的好处是：<br>1.你可以为某个Job关联多个Trigger，其中任何一个条件满足都可以触发job执行，这样可以完成一些组合的高级触发条件<br>2.当Trigger失效后（比如：一个永远都不能满足的条件），你不必去声明一个新的job，代替的是你可以为job关联一个新的Trigger让job可以继续执行。</p>
<p style="FONT-SIZE: 10pt">目前的Quartz实现中，存在两种Trigger,SimpleTrigger和CronTrigger,SimpleTrigger用来完成一些比如固定时间执行的任务，比如：从现在开始1分钟后等等；而CronTrigger(没错，和unix的cron进程的含意一样)用来执行calendar-like的任务，比如：每周五下午3：00，每月最后一天等等。</p>
<p style="FONT-SIZE: 10pt">在我们项目中，都是一些固定时间的 Job，所以只用到了 SimpleTrigger。<br>Trigger trigger = new SimpleTrigger("SayHelloWorldJobTrigger",Scheduler.DEFAULT_GROUP,new Date(),null,0,0L);<br>这个构造方法中，第一个是Trigger的名称，第二个是Trigger的组名，第三个是任务开始时间，第四个是结束时间，第五个是重复次数（使用SimpleTrigger.REPEAT_INDEFINITELY常量表示无限次），最后一个是重复周期（单位是毫秒），那么这样就创建了一个立刻并只执行一次的任务。</p>
<p style="FONT-SIZE: 10pt">但我们定义好了 JobDetail，Job，和 Trigger 后，就可以开始 Schedule 一个 Job 了。</p>
<p style="FONT-SIZE: 10pt">scheduler.scheduleJob(jobDetail, trigger);<br><br>这条语句就是把job和Trigger关联，这样当Trigger认为应该触发的时候就会调用（实际上是Scheduler调用）job.execute方法了。</p>
<p style="FONT-SIZE: 10pt">scheduler.start();<br>千万别忘了加上上面的语句，这条语句通知Quartz使安排的计划生效。</p>
<p style="FONT-SIZE: 10pt">关于execute方法的参数JobExecutionContext<br>JobExecutionContext就和很多Context结尾的类功能一样，提供的运行时刻的上下文环境，JobExecutionContext中有Scheduler,JobDetail,Trigger等很多对象的引用，从而当你在execute方法内部须需要这些对象的时刻提供的便利。</p>
<p style="FONT-SIZE: 10pt">在项目中，我们把需要执行的 Job 相对应的一些信息放在 JobExecutionContext 中，在 Job 执行的时候可以调用。<br><br>jobDetail.getJobDataMap().put(userid, id);<br><br>在 Job 中，我们可以拿到相关的 Context 信息：<br><br>jobExecutionContext.getJobDetail().getJobDataMap().getInt(userid);</p>
<p style="FONT-SIZE: 10pt">JobDetail和Trigger的name和group<br>Scheduler实例对应了很多job和trigger的实例，为了方便的区分，Quartz使用name和group这两个特性，正如你想向的一样，同一个group下不能有两个相同name的JobDetail，Trigger同理，同一个Scheduler下不能有两个相同group的JobDetail,Trigger同理，JobDetail和Trigger的完全限定名为：group + name</p>
<p style="FONT-SIZE: 10pt">为了让服务器重启以后，我们的 Scheduler 信息仍然不丢失，我们通常采用数据库持久化 Scheduler 的信息。<br>DBScript 在 Quartz 的下载包中的：quartz-1.6.0\docs\dbTables 下，选择自己使用的 DB 相应的 Script 导入数据库就可以了。<br>在应用中，我们需要配置一个 quartz.properties 才能正常使用 DB。我们可以在 quartz-1.6.0\examples\example10 中找到该文件的样例，稍作一些修改，就可以放到自己项目源码的根目录下使用了。<br><br>设置 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX 即可启用基于 JDBC 的 Quartz 信息持久化。<br><br>根据项目情况设置以下配置信息：<br>org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX<br>org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate<br>org.quartz.jobStore.useProperties = false<br>org.quartz.jobStore.dataSource = myDS<br>org.quartz.jobStore.tablePrefix = QRTZ_<br>org.quartz.jobStore.isClustered = false</p>
<p style="FONT-SIZE: 10pt">org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver<br>org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/myapplication<br>org.quartz.dataSource.myDS.user = root<br>org.quartz.dataSource.myDS.password =<br>org.quartz.dataSource.myDS.maxConnections = 5</p>
<p style="FONT-SIZE: 10pt">但是光设置了 Database 不够，我们还需要在 Application 启动的时候自动启动 Scheduler 才行，我们只需要简单的写一个 Servlet 的 Listener 并在 web.xml 中声明该 Listener ，在 Servlet 容易启动的时候，Scheduler 就开始自动执行。</p>
<p style="FONT-SIZE: 10pt">public class ScheduleStartListener implements ServletContextListener {<br>&nbsp;&nbsp;&nbsp; public void contextInitialized(ServletContextEvent servletContextEvent) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scheduleFactory.getScheduler().start();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (SchedulerException e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // write log<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }</p>
<p style="FONT-SIZE: 10pt">&nbsp;&nbsp;&nbsp; public void contextDestroyed(ServletContextEvent servletContextEvent) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scheduleFactory.getScheduler().shutdown();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (SchedulerException e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // write log<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<p style="FONT-SIZE: 10pt">在 web.xml 里面加入以下配置：<br>&lt;listener&gt;<br>&nbsp;&nbsp;&nbsp; &lt;listener-class&gt;org.agilejava.scheduler.ScheduleStartListener&lt;/listener-class&gt;<br>&lt;/listener&gt;</p>
<p style="FONT-SIZE: 10pt">以上简单的记录了在项目中关于 Quartz 的一些应用，如果有什么新的使用心得，会在后面继续加入的。</p>
 <img src ="http://www.blogjava.net/steady/aggbug/134017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/steady/" target="_blank">steady</a> 2007-08-02 16:28 <a href="http://www.blogjava.net/steady/archive/2007/08/02/134017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>