2012-08-16 36 views
7

Tôi gặp sự cố khi đặt tiêu đề Cấp quyền HTTP cho yêu cầu dịch vụ web bằng Apache CXF. Tôi đã thiết lập khách hàng của tôi qua mùa xuân:Xác thực cơ sở HTTP thông qua trình chặn đánh chặn CXF không hoạt động

<bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" /> 
<bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> 

<bean id="myHTTPAuthInterceptor" class="my.app.MyHTTPAuthInterceptor" autowire="constructor" /> 

<bean id="webServiceFactory" class="my.app.WebServiceFactory"> 
    <property name="wsdlLocation" value="classpath:/my/app/webservice.wsdl" /> 
    <property name="serviceURL"> 
     <jee:jndi-lookup jndi-name="webservice/url" /> 
    </property> 
    <property name="inInterceptors"> 
     <list> 
      <ref bean="loggingInInterceptor" /> 
     </list> 
    </property> 
    <property name="outInterceptors"> 
     <list> 
      <ref bean="loggingOutInterceptor" /> 
      <ref bean="myHTTPAuthInterceptor" /> 
     </list> 
    </property> 
</bean> 

<bean id="myWebService" factory-bean="webServiceFactory" factory-method="getInstance" /> 

Headers được thiết lập thông qua MyHTTPAuthInterceptor như thế này:

public MyHTTPAuthInterceptor(ConfigDao configDao) 
{ 
    super(Phase.POST_PROTOCOL); 

    this.configDao = configDao; 
} 

@Override 
public void handleMessage(Message message) throws Fault 
{ 
    Map<String, List<?>> headers = (Map<String, List<?>>) message.get(Message.PROTOCOL_HEADERS); 

    String authString = configDao.getUsername() + ":" + config.getPassword(); 
    headers.put("Authorization", Collections.singletonList("Basic " + new String(Base64.encodeBase64(authString.getBytes())))); 
} 

Với tên người dùng và cả các thiết lập để 'thử', mọi thứ có vẻ là OK trong các bản ghi:

Headers: {SOAPAction=[""], Accept=[*/*], Authorization=[Basic dGVzdDp0ZXN0]} 

Tuy nhiên, máy chủ trả lại HTTP 401: Không được ủy quyền.

Không biết chuyện gì xảy ra, tôi đã tiếp cận toàn bộ cách khác bằng cách thay đổi mã nhà máy dịch vụ web của khách hàng. Tôi đã thêm một chính sách cho phép cơ bản để ống dẫn của khách hàng như thế này:

HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); 
AuthorizationPolicy authorizationPolicy = new AuthorizationPolicy(); 
authorizationPolicy.setUserName("test"); 
authorizationPolicy.setPassword("test"); 
authorizationPolicy.setAuthorizationType("Basic"); 
httpConduit.setAuthorization(authorizationPolicy); 

Tested thiết lập của tôi một lần nữa, cùng log (thứ tự khác nhau mặc dù):

Headers: {SOAPAction=[""], Authorization=[Basic dGVzdDp0ZXN0], Accept=[*/*]} 

Bây giờ phản ứng của máy chủ là 200 OK!

Sự cố được giải quyết mà bạn có thể nghĩ, nhưng cách tiếp cận thứ hai không thực sự hiệu quả đối với tôi. Ứng dụng của tôi là môi trường nhiều người thuê, tất cả đều có tên người dùng và mật khẩu khác nhau. Với cách tiếp cận thứ hai tôi không thể tái sử dụng khách hàng của mình.

Làm cách nào để trình chặn đánh chặn hoạt động chính xác? Tôi đang cắm vào giai đoạn sai? Thứ tự của các tiêu đề có quan trọng không? Nếu vậy, làm thế nào để thay đổi nó?

Trả lời

5

Tôi gần như chính xác thiết lập giống như của bạn nhưng tôi đang đặt trình chặn chặn của tôi trong giai đoạn PRE_PROTOCOL. Cho đến nay, tôi đã không gặp bất kỳ vấn đề gì. Bạn có thể thử điều đó.

Tôi nghĩ POST_PROTOCOL đã quá muộn vì quá nhiều đã được ghi vào luồng.

+0

Thử nó, nhưng than ôi, không may mắn ... – verhage

+2

Ok, tôi phải sửa bản thân mình ở đây. Mắc lỗi. Nó hoạt động! Cảm ơn bạn rất nhiều, câu trả lời của bạn được chấp nhận :) – verhage

3

Nếu bạn đang tìm kiếm để biểu lộ khách hàng và thẩm định phương pháp tốt nhất là để thiết lập httpConduit trong bối cảnh mùa xuân ..

**in your spring context file...** 

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:jaxws="http://cxf.apache.org/jaxws" 
     ... 

    <bean id="properties" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer"> 
    <property name="locations"> 
     <util:list> 
      <value>file:${config.dir}/application.properties</value> 
     </util:list> 
    </property> 
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> 
</bean> 
    ... 
    <jaxws:client id="serviceClient" serviceClass="com.your.ServiceClass" address="${webservice.soap.address}" > 
    <jaxws:inInterceptors> 
     <bean id="loggingInInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" > 
      <property name="prettyLogging" value="true" /> 
     </bean> 
    </jaxws:inInterceptors> 
    <jaxws:outInterceptors> 
     <bean id="loggingOutInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" > 
      <property name="prettyLogging" value="true" /> 
     </bean> 
    </jaxws:outInterceptors> 
    </jaxws:client> 
    ... 


applicaiton.properties 
--------------------- 
webservices.http.auth.username=userName 
webservices.http.auth.password=Password 
webservice.soap.address=https://your.service.url/services/service 

a) bằng cách đề cập địa chỉ SOAP trong thuộc tính tên. mà bạn có thể tìm thấy trong WSDL của bạn

Ex: if in your WSDL.. 
    <wsdl-definitions ... targetNamespace="http://your.target.namespace.com/" ...> 
    ... 
    <wsdl:port binding="tns:YourServiceSoapBinding" 
     name="YourServiceImplPort"> 
     <soap:address location="https://your.service.url/services/service" /> 

Sau đó

... 
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration" 
xmlns:sec="http://cxf.apache.org/configuration/security" 
... 
<http-conf:conduit name="https://your.service.url/services/service"> 
    <http-conf:authorization> 
     <sec:UserName>${webservices.http.auth.username}</sec:UserName> 
     <sec:Password>${webservices.http.auth.password}</sec:Password> 
     <sec:AuthorizationType>Basic</sec:AuthorizationType> 
    </http-conf:authorization> 
</http-conf:conduit> 

Hoặc b) Tên thuộc tính nên được {} targetNamespace portName.http_conduit

<http-conf:conduit name="{http://your.target.namespace.com/}YourServiceImplPort.http_conduit"> 
    <http-conf:authorization> 
     <sec:UserName>${webservices.http.auth.username}</sec:UserName> 
     <sec:Password>${webservices.http.auth.password}</sec:Password> 
     <sec:AuthorizationType>Basic</sec:AuthorizationType> 
    </http-conf:authorization> 
</http-conf:conduit> 
Các vấn đề liên quan