代码之家  ›  专栏  ›  技术社区  ›  marktucks

JAX-WS密码类型PasswordText

  •  21
  • marktucks  · 技术社区  · 14 年前

    我有一个简单的命令行javajax-WS应用程序来测试一个SOAP请求,但是服务器希望密码类型是PasswordText,我很难理解如何设置这个。。。

    @WebServiceRef
    private static final HelloService helloService = new HelloService(url, new QName(
            URL, "HelloService"));
    
    public static void main(final String... args) {
    
        try {
            final HelloPort helloPort = helloService.getHelloPort();
            final BindingProvider hB = ((BindingProvider) helloPort);
            hB.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                                       END_POINT_ADDRESS);
            hB.getRequestContext().put(BindingProvider.USERNAME_PROPERTY,
                                       USERNAME);
            hB.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY,
                                       PASSWORD);
            ...
    

    我已经使用SOAP-UI测试了请求,所以我知道它正在工作。任何帮助设置密码类型将不胜感激。

    谢谢。

    2 回复  |  直到 11 年前
        1
  •  36
  •   SimonB    14 年前

    这将设置基本HTTP身份验证的用户名和密码。如果您在SoapUI中测试过它,我猜您所说的“PasswordText”值就是请求详细信息窗格中的“WSS Password Type”。设置WSS安全性,而不是HTTP安全性。

    对于Java6中的JAX-WS,您需要附加SOAPHandler,以便将WSS Usertoken注入SOAP头中。网上有很多关于这方面的小道消息,但是我找不到一个链接,所以这里有一些代码让你继续。。。

    要添加处理程序,您需要以下内容:

    final Binding binding = ((BindingProvider) servicePort).getBinding();
    List<Handler> handlerList = binding.getHandlerChain();
    if (handlerList == null)
        handlerList = new ArrayList<Handler>();
    
    handlerList.add(new SecurityHandler());
    binding.setHandlerChain(handlerList); // <- important!
    

    然后SecurityHandler类将执行该操作。处理程序是一般的东西,成功的消息和错误都会被调用,但也许更重要的是它们会被调用 二者都 消息方向-用于传出请求,然后再次用于传入响应。您只想处理传出的消息。所以你需要这样的东西:

    public final class SecurityHandler implements SOAPHandler<SOAPMessageContext> {
    
        ...
    
        @Override
        public boolean handleMessage(final SOAPMessageContext msgCtx) {
    
            // Indicator telling us which direction this message is going in
            final Boolean outInd = (Boolean) msgCtx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    
            // Handler must only add security headers to outbound messages
            if (outInd.booleanValue()) {
                try {
                    // Get the SOAP Envelope
                    final SOAPEnvelope envelope = msgCtx.getMessage().getSOAPPart().getEnvelope();
    
                    // Header may or may not exist yet
                    SOAPHeader header = envelope.getHeader();
                    if (header == null)
                        header = envelope.addHeader();
    
                    // Add WSS Usertoken Element Tree 
                    final SOAPElement security = header.addChildElement("Security", "wsse",
                            "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                    final SOAPElement userToken = security.addChildElement("UsernameToken", "wsse");
                    userToken.addChildElement("Username", "wsse").addTextNode("MyWSSUsername");
                    userToken.addChildElement("Password", "wsse").addTextNode("MyWSSPassword");
    
                } catch (final Exception e) {
                    LOG.error(e);
                    return false;
                }
            }
            return true;
        }
    
        ...
        // Other required methods on interface need no guts
    }
    

    我在这里做了一些假设,但希望它能让你走!

    谨致问候。

        2
  •  8
  •   cleison    10 年前

    如果实现SOAPHandler接口,msgCtx.getMessage()方法将呈现整个XML,如果处理大文件,则会出现内存不足错误。我在JAX-WS客户端上测试了UsernameToken身份验证,它可以工作:

    String SECURITY_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    String PASSWORD_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
    String AUTH_PREFIX = "wss";
    
    MyService service = new MyService();
    MyServicePort port = service.getMyServicePort();
    
    try {
        SOAPFactory soapFactory = SOAPFactory.newInstance();
        SOAPElement security = soapFactory.createElement("Security", AUTH_PREFIX, SECURITY_NS);
        SOAPElement uToken = soapFactory.createElement("UsernameToken", AUTH_PREFIX, SECURITY_NS);
        SOAPElement username = soapFactory.createElement("Username", AUTH_PREFIX, SECURITY_NS);
        username.addTextNode("username");
    
        SOAPElement pass = soapFactory.createElement("Password", AUTH_PREFIX, SECURITY_NS);
        pass.addAttribute(new QName("Type"), PASSWORD_TYPE);
        pass.addTextNode("password");
    
        uToken.addChildElement(username);
        uToken.addChildElement(pass);
        security.addChildElement(uToken);
    
        Header header = Headers.create(security);
        ((WSBindingProvider) port).setOutboundHeaders(header);
    
        // now, call webservice
    
    } catch (SOAPException ex) {
        ex.printStackTrace();
    }
    

    编辑:

    推荐文章