Spring WS客户端设置cookie用于身份验证 [英] Spring WS client set cookie for authentication

查看:376
本文介绍了Spring WS客户端设置cookie用于身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了使用RPC Web服务,首先我必须调用Web方法'Authentication',然后我应该能够调用其他Web方法。我试图实现一个Spring Web客户端来使用这个服务,但是有些事情是非常错误的。

In order to consume a RPC web service, first I have to call a web method 'Authentication' and then I am supposed to be able to call other web methods. I have tried to implement a spring web client to consume this service but something is going terribly wrong.

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

This service was originally designed for php users and the sample client code they provided is as following:

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

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

'authentication' method will return 1 when successful and -1 otherwise. 'getCredit' method return a float showing user current balance.

现在用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'但是在调用第二个时web方法我得到这个例外:

The status code I get is equal to '1' but upon calling the second web method I get this exception:

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


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

It is clear that calling the 'authentication' method in php does not have the same effect as calling it in java. So I investigated a little more and found out that something is being set in the response cookies of 'authentication' web method.

以下是对响应的一瞥:

标题

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分配了一个值!这个参数很可能用于处理授权。

As you can see a PHPSESSID has been assigned a value! It is most likely that this parameter is used to handle the authorization.

鉴于以下Spring Web Service配置,我如何才能获得相同的结果?

Given the following Spring Web Service configuration how can I achieve the same result?

<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服务客户端的其他实现。

I would welcome other implementation of the web service client if it is necessary to handle the authentication.

推荐答案

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

I finally managed to solve this problem using a custom SAOP-Handler and manually extracting PHPSESSID from message Http Headers.


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

<bean id="credentialHandlerResolver" class="com.example.handlers.CredentialHandlerResolver"/>


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;
    }
}


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;
    }

这篇关于Spring WS客户端设置cookie用于身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆