【问题标题】:Implement Authentication in CXF WebServices using WSS4J (SOAP)使用 WSS4J (SOAP) 在 CXF WebServices 中实现身份验证
【发布时间】:2021-05-20 12:44:59
【问题描述】:

我正在尝试在我的网络服务中使用用户名/密码来实现身份验证。目前我学习了 CXF 和如何配置东西,但对于我的生活,我只是无法理解安全部分。

我使用 CXF 从 WSDL 创建 Java 类。这是我的 Web 服务 XML 配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<jaxws:endpoint id="pacService" implementor="com.logicalprovisioning.internal.PacWS" address="/PacRequestSoapHttpPort">
    <jaxws:properties>
        <entry key="exceptionMessageCauseEnabled" value="true" />
        <entry key="security.callback-handler" value="com.logicalprovisioning.webservices.clients.autheticate.AuthenticationCallback"/>
    </jaxws:properties>
</jaxws:endpoint>
</beans>

我在验证用户名密码时添加的 AuthenticationCallback 条目。

我的 AutheitcationCallback 目前看起来像这样:

import java.io.IOException;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.apache.wss4j.common.ext.WSPasswordCallback;

public class AuthenticationCallback {

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

        WSPasswordCallback wsPasswordCallback = (WSPasswordCallback) callbacks[0];

        if (wsPasswordCallback.getIdentifier().equals("TIM")) {
            wsPasswordCallback.setPassword("my_password");
        }
    }
}

现在只是一个草稿。

我编写了一个客户端,用于初始化 WebService(一个抽象类),并继承它以用于不同的 Web 服务。

public abstract class WebServiceClientBase implements HandlerResolver, SOAPHandler<SOAPMessageContext> {

    protected int connectTimeout;

    protected String endPointUrl;
    protected String password;
    protected String userName;

    protected Logger logger = null;

    private Service service = null;


    public WebServiceClientBase () {
        super();
    }

    public void init() {

        // Set the security handler
        getService().setHandlerResolver(new HandlerResolverImpl());

        // Setting endpoint URL and timeout...
        getBindingProvider().getRequestContext().put("javax.xml.ws.client.receiveTimeout", connectTimeout);
        getBindingProvider().getRequestContext().put("javax.xml.ws.client.connectionTimeout", connectTimeout);
        getBindingProvider().getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPointUrl);


        Map<String, List<String>> headers = new HashMap<String, List<String>>();

        headers.put("Content-Type", Collections.singletonList("application/soap+xml"));
        headers.put(Message.ENCODING, Collections.singletonList("UTF-8"));

        getBindingProvider().getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
    }

    @Override
    @SuppressWarnings("rawtypes")
    public List<Handler> getHandlerChain(PortInfo arg0) {

        List<Handler> handlerChain = new ArrayList<Handler>();

        handlerChain.add(this);

        return handlerChain;
    }

    @Override
    public boolean handleMessage(SOAPMessageContext soapMessageContext) {

        if (!((Boolean) soapMessageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)). booleanValue()) {
            return true;
        }

        return true;
    }
    
    @Override
    public boolean handleFault(SOAPMessageContext arg0) {
        return false;
    }

    @Override
    public void close(MessageContext arg0) {

    }

    @Override
    public Set<QName> getHeaders() {
        return null;
    }

    protected Service getService() {
        return service;
    }

    protected void setService(Service service) {
        this.service = service;
    }

    protected abstract BindingProvider getBindingProvider();
}

这就是我已经走了多远。我不确定如何将身份验证信息与网络服务调用连接起来。

任何指针都会有所帮助。我也是在正确的轨道上开始吗?浏览所有教程和示例可能会陷入死胡同。

【问题讨论】:

  • I am not sure how do I connect authentication information along with the webservice call 你说的是基本身份验证还是一些与 WS-Security 相关的身份验证?
  • WS-Security 是我正在关注的。 cxf.apache.org/docs/ws-security.html 。我阅读了本指南,并查找了它的示例。但我还是无法咬牙切齿。
  • 据我了解您的问题,您正在寻找一种将身份验证信息添加到客户端请求的方法?您可以尝试定义ws-security 属性和客户端回调处理程序as outlined in this blog 或使用引用您的回调处理程序的WSS4JOutInterceptor,如in this blog 所示
  • 感谢您的博客链接。我会试一试。我会回来发现我不明白的东西
  • @RomanVottner 这两个链接很有帮助。我比以前走得更远了。但是我被困在如何在由 CXF wsdl2java 创建的客户端上添加令牌/密码信息的方面。我发现的大多数示例,Web 服务都是从头开始编写的。

标签: java web-services soap cxf


【解决方案1】:

假设 com.logicalprovisioning.internal.PacWS 是您的 jaxws 生成的 PortType 类,您可以这样做...

...
com.logicalprovisioning.internal.PacWS pacWsPort = getService().get...Port();
org.apache.cxf.endpoint.Client client = org.apache.cxf.frontend.ClientProxy.getClient(pacWSPort);
org.apache.cxf.endpoint.Endpoint endpoint = client.getEndpoint();

Map<String, Object> props = new HashMap<>();
props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
props.put(WSHandlerConstants.PW_CALLBACK_CLASS, AuthenticationCallback.class.getName());
props.put(WSHandlerConstants.USER, "TIM");
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);
endpoint.getOutInterceptors().add(wssOut);

// you can then call @WebMethod annotated methods on your PacWS object, and it should populate the wss-security soap header

上面的部分代码大概可以用cxf xml配置文件中的配置代替

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-21
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    • 2013-12-14
    • 1970-01-01
    相关资源
    最近更新 更多