【问题标题】:Spring WS client set cookie for authenticationSpring WS 客户端设置 cookie 进行身份验证
【发布时间】:2014-08-07 18:01:35
【问题描述】:

为了使用 RPC Web 服务,首先我必须调用 Web 方法“身份验证”,然后我应该能够调用其他 Web 方法。我试图实现一个 Spring Web 客户端来使用该服务,但出现了严重错误。

该服务最初是为php用户设计的,他们提供的示例客户端代码如下:

$soap = new SoapClient('http://www.2972.ir/wsdl?XML'); 
if ($soap->Authentication('user', '123456')) { 
    echo $soap->getCredit();
}

'authentication' 方法成功时返回 1,否则返回 -1。 'getCredit' 方法返回一个显示用户当前余额的浮点数。

现在我在 Java 中的实现:

@Service
public class MessageService implements IMessageService {

    @Autowired
    private IranSMSPanelPortType webService;

    public String doSomething() {
        int status = webService.authentication("user", "123456");
        System.out.println("# status: "+status);
        return String.valueOf(webService.getCredit());
    }

我得到的状态码等于“1”,但在调用第二个网络方法时,我得到了这个异常:

 javax.xml.ws.soap.SOAPFaultException: You are not authorized


很明显,在php中调用'authentication'方法与在java中调用它的效果不同。所以我调查了一下,发现在“身份验证”网络方法的响应 cookie 中设置了一些东西。

这里是回复的一瞥:

标题

HTTP/1.1 200 OK
Date: Thu, 07 Aug 2014 17:26:49 GMT
Server: Apache/2
X-Powered-By: PHP/5.4.24
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Connection: close
Set-Cookie: PHPSESSID=m607671c9d8aeks5vm2r84n8r3; path=/
Vary: Accept-Encoding,User-Agent
Transfer-Encoding: chunked
Content-Type: text/xml; charset=utf-8

信封

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://www.iransmspanel.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <ns1:AuthenticationResponse>
      <result xsi:type="xsd:int">1</result>
    </ns1:AuthenticationResponse>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>


如您所见,PHPSESSID 已被赋值!这个参数很可能是用来处理授权的。

给定以下 Spring Web Service 配置,我怎样才能达到相同的结果?

<bean id="smsWebService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
    <property name="serviceInterface" value="com.iransmspanel.IranSMSPanelPortType" />  
    <property name="wsdlDocumentUrl"  value="http://www.2972.ir/wsdl?XML" />
    <property name="namespaceUri"     value="http://www.iransmspanel.com/" />
    <property name="serviceName"      value="IranSMSPanel" />
    <property name="portName"         value="IranSMSPanelPort" />
</bean>


如果需要处理身份验证,我会欢迎 Web 服务客户端的其他实现。

【问题讨论】:

    标签: php web-services jakarta-ee soap spring-ws


    【解决方案1】:

    我终于设法使用自定义 SAOP-Handler 并从消息 Http Headers 中手动提取 PHPSESSID 解决了这个问题。


    弹簧配置

    <bean id="smsWebService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
        ...
        <property name="handlerResolver"  ref="credentialHandlerResolver"/>
    </bean>
    
    <bean id="credentialHandlerResolver" class="com.example.handlers.CredentialHandlerResolver"/>
    


    CredentialHandlerResolver.java

    import javax.xml.ws.handler.Handler;
    import javax.xml.ws.handler.HandlerResolver;
    import javax.xml.ws.handler.PortInfo;
    ...
    
    public class CredentialHandlerResolver implements HandlerResolver {
        private List<Handler> chain;
        CredentialHandlerResolver() {
            chain = new ArrayList<Handler>();
            chain.add(new CredentialHandler());
        }
        public List<Handler> getHandlerChain(PortInfo portInfo) {
            return chain;
        }
    }
    


    CredentialHandler.java

    public class CredentialHandler implements SOAPHandler<SOAPMessageContext> {
        public static String PHPSESSID;
    
        public boolean handleMessage(SOAPMessageContext context) {
            Boolean isRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            try {
                SOAPMessage message = context.getMessage();
                SOAPBody body = message.getSOAPPart().getEnvelope().getBody();
                if(!isRequest && body.getFirstChild().getLocalName().equals("AuthenticationResponse") && body.getFirstChild().getTextContent().equals("1")) {
                    // extracting PHPSESSID from HTTP headers
                    Map<String, List<String>> httpHeaders = (Map<String, List<String>>) context.get(MessageContext.HTTP_RESPONSE_HEADERS);
                    String session = httpHeaders.get("Set-Cookie").get(0);
                    PHPSESSID = session.substring(10, session.indexOf(';'));
                }
                else if (isRequest && PHPSESSID != null && !body.getFirstChild().getLocalName().equals("Authentication")){
                    // add PHPSESSID to HTTP headers
                    Map<String, List<String>> headers = new HashMap<String, List<String>>();
                    headers.put("Cookie", Arrays.asList("PHPSESSID=" + PHPSESSID));
                    context.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
                }
            }
            catch (SOAPException ex) {
                ex.printStackTrace();
                return false;
            }
            return true;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 2014-08-29
      • 2013-07-20
      • 1970-01-01
      相关资源
      最近更新 更多