CXF 客户端安全

发布于 2024-11-19 00:54:13 字数 2631 浏览 4 评论 0原文

我正在创建 Java Soap Web 服务的客户端,但无法弄清楚如何正确传递密码。这是我的“硬编码”密码示例:

@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");
}}

我真正想做的是将密码传递到回调处理程序中。我在 CXF 文档中看到的示例实现了“硬编码”回调(正如我在本例中所做的那样)或作为用户名的函数:

if (pc.getIdentifier().equals("user"))
   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);
            // ...
}

I am creating a client to a Java soap web service, but am having trouble figuring out how to properly pass the password. Here is my "hardcoded" password example:

@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");
}}

What I really want to do is to pass the password into the callback handler. The examples that I have seen in the CXF documentation implement the callback either "hardcoded" (as I did in this example) or as a function of the username:

if (pc.getIdentifier().equals("user"))
   pc.setPassword("pwd");

Neither of these meet my needs. Is there a way that I can do something like the following:

@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);
            // ...
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

巴黎盛开的樱花 2024-11-26 00:54:13

使用 PW_CALLBACK_REF 而不是 PW_CALLBACK_CLASS,并传递实例化对象,而不是静态类。您可以将密码注入到所述对象中。

像这样的东西:

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

Use PW_CALLBACK_REF instead PW_CALLBACK_CLASS, and pass an instantiated object, instead of the static class. You can inject the password in said object.

Something like:

    outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
    CXFClientPasswordHandler handler = new CXFClientPasswordHandler();
    handler.setPassword(password);
    outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
探春 2024-11-26 00:54:13

我还能够执行以下操作:

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

I was also able to do the following:

    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);
白鸥掠海 2024-11-26 00:54:13

您的 ClientPasswordCallback 类可能是这样的,有自己的 pwd 字段和关联的设置器:

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_CALLBACK_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);

    // ...
}

Your ClientPasswordCallback class may be like that, with his own pwd field and the associated 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);
    }
}

Then you can instanciate it in your test, set its password and use PW_CALLBACK_REF key to add it to the outProps map:

@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);

    // ...
}
ヅ她的身影、若隐若现 2024-11-26 00:54:13

我一直使用以下方法添加属性来请求上下文以进行 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");

        }

        }


    }

}

I have always used following way of adding properties to request context for http level authentication and CallbackHandler for adding message level username token.

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");

        }

        }


    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文