Java CXF客户端安全

Java CXF客户端安全,java,soap,cxf,soap-client,Java,Soap,Cxf,Soap Client,我正在创建一个JavaSOAPWeb服务的客户机,但是在弄清楚如何正确传递密码时遇到了困难。以下是我的“硬编码”密码示例: @Test public void exploratorySecurityTest() { String username = "user"; String password = "pwd"; UserStoryService service = new UserStoryService(); UserStoryServiceSoap

我正在创建一个JavaSOAPWeb服务的客户机,但是在弄清楚如何正确传递密码时遇到了困难。以下是我的“硬编码”密码示例:

@Test
public void exploratorySecurityTest() {
     String username = "user";
     String password = "pwd";

    UserStoryService service = new UserStoryService();
    UserStoryServiceSoap port = service.getUserStoryServiceSoap();

    //initialize security
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
    Map<String, Object> outProps = new HashMap<String, Object>();
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    outProps.put(WSHandlerConstants.USER, username);
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);

    int storyId = 33401;
    UserStoryDTO userStoryDTO = port.getByID(storyId);

    //success if no error
}

public class ClientPasswordCallback implements CallbackHandler {

@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
    WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
    pc.setPassword("pwd");
}}
这两个都不能满足我的需要。有没有一种方法可以让我做如下事情:

@Test
public void exploratorySecurityTest() {
     String username = "user";
     String password = "pwd";

    UserStoryService service = new UserStoryService();
    UserStoryServiceSoap port = service.getUserStoryServiceSoap();

    //initialize security
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
    Map<String, Object> outProps = new HashMap<String, Object>();
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    outProps.put(WSHandlerConstants.USER, username);

            //pass the password here?
            outProps.put("password", password);

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);

    cxfEndpoint.getOutInterceptors().add(wssOut);
            // ...
}
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj);
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

    Map<String, Object> outProps = new HashMap<String, Object>();

    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);

    System.out.println("initialize security for user " + this.username);
    outProps.put(WSHandlerConstants.USER, this.username);
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

    Map<String, Object> ctx = ((BindingProvider) obj).getRequestContext();
    ctx.put("password", this.password);

    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);
@测试
public void exploratorySecurityTest(){
字符串username=“user”;
字符串密码=“pwd”;
UserStoryService服务=新的UserStoryService();
UserStoryServiceSoap端口=service.getUserStoryServiceSoap();
//初始化安全性
org.apache.cxf.endpoint.Client Client=ClientProxy.getClient(端口);
org.apache.cxf.endpoint.endpoint cxfEndpoint=client.getEndpoint();
Map outProps=new HashMap();
put(WSHandlerConstants.ACTION,WSHandlerConstants.USERNAME\u令牌);
put(WSHandlerConstants.USER,用户名);
//在这里传递密码?
outProps.put(“密码”,密码);
outProps.put(WSHandlerConstants.PASSWORD_类型,WSConstants.PW_文本);
put(WSHandlerConstants.PW_CALLBACK_类,ClientPasswordCallback.CLASS.getName());
WSS4JOutInterceptor wssOut=新的WSS4JOutInterceptor(输出程序);
cxfEndpoint.getOutiterCeptors().add(wssOut);
// ...
}

使用PW\u CALLBACK\u REF代替PW\u CALLBACK\u类,并传递实例化对象,而不是静态类。您可以在所述对象中注入密码

比如:

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    CXFClientPasswordHandler handler = new CXFClientPasswordHandler();
    handler.setPassword(password);
    outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);

我还能够做到以下几点:

@Test
public void exploratorySecurityTest() {
     String username = "user";
     String password = "pwd";

    UserStoryService service = new UserStoryService();
    UserStoryServiceSoap port = service.getUserStoryServiceSoap();

    //initialize security
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port); 
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
    Map<String, Object> outProps = new HashMap<String, Object>();
    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    outProps.put(WSHandlerConstants.USER, username);

            //pass the password here?
            outProps.put("password", password);

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientPasswordCallback.class.getName());
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);

    cxfEndpoint.getOutInterceptors().add(wssOut);
            // ...
}
    org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj);
    org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();

    Map<String, Object> outProps = new HashMap<String, Object>();

    outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);

    System.out.println("initialize security for user " + this.username);
    outProps.put(WSHandlerConstants.USER, this.username);
    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

    Map<String, Object> ctx = ((BindingProvider) obj).getRequestContext();
    ctx.put("password", this.password);

    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
    cxfEndpoint.getOutInterceptors().add(wssOut);
org.apache.cxf.endpoint.Client=ClientProxy.getClient(obj);
org.apache.cxf.endpoint.endpoint cxfEndpoint=client.getEndpoint();
Map outProps=new HashMap();
put(WSHandlerConstants.ACTION,WSHandlerConstants.USERNAME\u令牌);
System.out.println(“为用户初始化安全”+此.username);
put(WSHandlerConstants.USER,this.username);
outProps.put(WSHandlerConstants.PASSWORD_类型,WSConstants.PW_文本);
Map ctx=((BindingProvider)obj.getRequestContext();
ctx.put(“密码”,此密码);
WSS4JOutInterceptor wssOut=新的WSS4JOutInterceptor(输出程序);
cxfEndpoint.getOutiterCeptors().add(wssOut);

我一直使用以下方法向http级身份验证的请求上下文添加属性,并使用CallbackHandler添加消息级用户名令牌

org.apache.cxf.endpoint.Client client = ClientProxy.getClient(obj);
org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();


System.out.println("initialize security for user " + this.username);
outProps.put(WSHandlerConstants.USER, this.username);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);

Map<String, Object> requestContext = ((BindingProvider) obj).getRequestContext();


//For message level authentication
requestContext.put("ws-security.username", "Ron");
requestContext.put("ws-security.callback-handler", "com.ws.cxf.client.callback.UTPasswordCallback");

//For endpoint level authentication, HTTP Basic/Digest
requestContext.put(BindingProvider.USERNAME_PROPERTY, username);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);




class UTPasswordCallback implements CallbackHandler {

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


    for(Callback cb:callbacks){
        WSPasswordCallback pcallback = (WSPasswordCallback)cb;
         if(pcallback.getUsage()==WSPasswordCallback.USERNAME_TOKEN)
        {

            if(pcallback.getIdentifier().equals("Ron"))
                pcallback.setPassword("noR");

        }

        }


    }

}
org.apache.cxf.endpoint.Client=ClientProxy.getClient(obj);
org.apache.cxf.endpoint.endpoint cxfEndpoint=client.getEndpoint();
System.out.println(“为用户初始化安全”+此.username);
put(WSHandlerConstants.USER,this.username);
outProps.put(WSHandlerConstants.PASSWORD_类型,WSConstants.PW_文本);
Map requestContext=((BindingProvider)obj).getRequestContext();
//用于消息级身份验证
requestContext.put(“ws-security.username”、“Ron”);
requestContext.put(“ws-security.callback处理程序”、“com.ws.cxf.client.callback.UTPasswordCallback”);
//对于端点级身份验证,HTTP Basic/Digest
put(BindingProvider.USERNAME\u属性,USERNAME);
requestContext.put(BindingProvider.PASSWORD_属性,PASSWORD);
类UTPasswordCallback实现CallbackHandler{
@凌驾
公共无效句柄(回调[]回调)引发IOException,
不支持CallbackException{
对于(回调cb:callbacks){
WSPasswordCallback pcallback=(WSPasswordCallback)cb;
if(pcallback.getUsage()==WSPasswordCallback.USERNAME\u令牌)
{
if(pcallback.getIdentifier().equals(“Ron”))
pcallback.setPassword(“noR”);
}
}
}
}

您的
ClientPasswordCallback
类可能是这样的,有自己的pwd字段和相关的setter:

class ClientPasswordCallback implements CallbackHandler {

    private String pwd;

    public void setPassword(String pwd) {
        passwd = pwd;
    }

    @Override
    public void handle(Callback[] callbacks) {
        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
        pc.setPassword(pwd);
    }
}
然后,您可以在测试中实例化它,设置它的密码,并使用
PW\u CALLBACK\u REF
键将它添加到
outProps
映射:

@Test
public void exploratorySecurityTest() {
    String username = "user";
    String password = "pwd";

    // ...

    outProps.put(PASSWORD_TYPE, WSConstants.PW_TEXT);
    ClientPasswordCallback handler = new ClientPasswordCallback();
    handler.setPassword(passwd);
    outProps.put(PW_CALLBACK_REF, handler);
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);

    // ...
}

顺便说一句:我已经尝试了这里介绍的方法[,但是没有运气你从处理程序内部访问“password”参数吗?或者在这种情况下你不需要定义自定义处理程序?