posts - 0, comments - 77, trackbacks - 0, articles - 356
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          XFire Web Service驗(yàn)證方案

          Posted on 2008-03-03 11:26 semovy 閱讀(1159) 評(píng)論(0)  編輯  收藏 所屬分類: WebService
          XFire的文檔做的真是相當(dāng)?shù)臓€,非常不詳細(xì),看得匪夷所思,而且和發(fā)行的代碼版本相當(dāng)?shù)牟黄ヅ洌锩娴氖纠緹o(wú)法運(yùn)行,看得真是……相當(dāng)窩火

          公司項(xiàng)目XFire的服務(wù)框架我已經(jīng)做好,這兩天就要加入驗(yàn)證功能,而且要和整體權(quán)限框架(還沒(méi)做)相結(jié)合
          開(kāi)始想通過(guò)HttpSession驗(yàn)證,這樣可以很方便的和b/s的權(quán)限系統(tǒng)相統(tǒng)一,但實(shí)在不知道如何在客戶端通過(guò)Spring或XFire訪問(wèn)HttpSession,XFire里的文檔倒是提到了:
          HttpServletRequest request = XFireServletController.getRequest();
          HttpServletResponse response = XFireServletController.getResponse();

          并且說(shuō)只要在web.xml里配置XFireSpringServlet就可以,可是按照配了,結(jié)果還是不行
          注:axis好像是有MessageContext可以很方便的訪問(wèn)到,xfire里也有MessageContext,可是getSession()出來(lái)的是null
          如果有高手知道如何做還望麻煩告知

          此條路不通只好去查XFire的文檔關(guān)于authentication部分,大概有以下幾種方案:
          1. HTTP Authentication
          2. SOAP Header authentication with JSR181
          3. SOAP authentication with handlers
          4. WS-Security
          其中第一條HTTP Authentication的文檔寫的相當(dāng)匪夷所思,文檔寫到如何在客戶端指定用戶名和密碼
          // Create your client
          Client client = ....;

          // Or get it from your proxy
          Client client = ((XFireProxy) Proxy.getInvocationHandler(myClientProxy)).getClient();

          client.setProperty(Channel.USERNAME, "username");
          client.setProperty(Channel.PASSWORD, "pass");

          去忘了寫服務(wù)端應(yīng)該怎么做,這個(gè)username和password該在那里驗(yàn)證呢??我翻遍了文檔也沒(méi)找著


          來(lái)看第二條SOAP header authentication with JSR181,看起來(lái)倒是很簡(jiǎn)單

          但是在Service的代碼中每個(gè)方法里都要寫一個(gè)UserToken驗(yàn)證的參數(shù),雖然似乎權(quán)限粒度能控制得很細(xì),但是這嚴(yán)重污染了業(yè)務(wù)邏輯的代碼,非常的不優(yōu)雅,放棄!


          public void someOperation(String data, @WebParam(header=true) UserToken token) {
          authenticate(token)

          // do your normal request here
          }

          再看WS-Security,這是webservice的安全標(biāo)準(zhǔn),但實(shí)在太復(fù)雜了,并且需要配置Service.xml,我們項(xiàng)目是Java1.5,Service.xml根本就沒(méi)有寫,是自動(dòng)生成的,我是實(shí)在找不到Service.xml該在那配置?只好作罷


          現(xiàn)在只剩下SOAP authentication with handlers,根據(jù)文檔來(lái)看這是能夠滿足我的要求的,不侵入業(yè)務(wù)邏輯,能夠和整體權(quán)限系統(tǒng)相結(jié)合,并且配置比較簡(jiǎn)單
          把例子里的代碼拷過(guò)來(lái),發(fā)現(xiàn)根本不能用,少了yom這個(gè)包,在網(wǎng)上找了很久也沒(méi)找到,后來(lái)發(fā)現(xiàn)yom其實(shí)就是yet(another) document object model,原來(lái)和dom是一回事嘛,用jdom替換,編譯通過(guò)。

          文檔里遺漏了很重要的一點(diǎn),就是關(guān)于如何在xfire-servlet里配置,導(dǎo)致很多人看了文檔也進(jìn)行不下去,我查了很久才在老外的一篇blog里找到一點(diǎn)tips,下面是配置:
              <!-- WebService base, do not modify it -->
              <bean id="webService" class="org.codehaus.xfire.spring.remoting.XFireExporter" abstract="true">
                  <property name="serviceFactory">
                      <ref bean="xfire.serviceFactory" />
                  </property>
                  <property name="xfire">
                      <ref bean="xfire" />
                  </property>
              </bean>

              <bean id="yourWebService" parent="webService">
                  <property name="serviceBean">
                      <ref bean="yourService" />
                  </property>
                  <property name="serviceClass">
                      <value>your.package.YourServiceInterface</value>
                  </property>
                  <property name="inHandlers">
                      <ref bean="authenticationHandler"/>
                  </property>
              </bean>

          AuthenticationHandler需要修改一下,其他不用變:

          AuthenticationHandler.java

          import org.apache.log4j.Logger;
          import org.codehaus.xfire.MessageContext;
          import org.codehaus.xfire.handler.AbstractHandler;
          import org.codehaus.xfire.fault.*;
          import org.jdom.*;

          public class AuthenticationHandler extends AbstractHandler {
              private static final Logger log = Logger.getLogger(AuthenticationHandler.class);
             
              public void invoke(MessageContext context) throws Exception {
                  log.info("authentication handler is invoked");
                  if (context.getInMessage().getHeader() == null)
                  {
                      throw new XFireFault("Request must include company authentication token.",
                                           XFireFault.SENDER);
                  }
                  Element header = context.getInMessage().getHeader();
                  Element token = header.getChild("AuthenticationToken");
                 
                  if (token == null)
                  {
                      throw new XFireFault("Request must include authentication token.",
                                           XFireFault.SENDER);
                  }

                  String username = token.getChild("Username").getText();
                  String password = token.getChild("Password").getText();

                  try {
                      // 現(xiàn)在你已經(jīng)得到了客戶端傳來(lái)的username和password,那就驗(yàn)證它吧(可以交給acegi來(lái)驗(yàn)證)
                      }

                  }catch(Exception e) {
                      log.warn(e);
                      throw new XFireFault("Authentication Failed.",
                              XFireFault.SENDER);
                  }
              }
          }

          客戶端代碼:

                      Service serviceModel = new ObjectServiceFactory().create(YourService.class);
                      YourService service = (YourService) new XFireProxyFactory().create(serviceModel,
                           "http://localhost:8080/YourProject/service/YourService");
                      XFireProxy proxy = (XFireProxy)Proxy.getInvocationHandler(service);
                      Client client = proxy.getClient();
                      client.addOutHandler(new ClientAuthHandler("jeffrey", "killjava"));
                      // 執(zhí)行下面代碼會(huì)進(jìn)行驗(yàn)證
                      service.someOperation();
          主站蜘蛛池模板: 临高县| 浦东新区| 博客| 会昌县| 朝阳县| 新疆| 阜新| 崇明县| 静安区| 靖宇县| 罗田县| 崇义县| 于都县| 新建县| 望都县| 江川县| 胶州市| 葫芦岛市| 中西区| 乌审旗| 罗平县| 洛阳市| 图片| 黎川县| 武强县| 富顺县| 杭锦后旗| 上林县| 合作市| 屏南县| 北流市| 民勤县| 神池县| 岳阳市| 康马县| 留坝县| 东宁县| 濉溪县| 慈利县| 日照市| 天台县|