java CXF 客户端安全
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6636262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CXF Client Security
提问by jayraynet
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:
我正在为 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");
}}
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:
我真正想做的是将密码传递给回调处理程序。我在 CXF 文档中看到的示例实现了“硬编码”(正如我在本示例中所做的那样)或作为用户名函数的回调:
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);
// ...
}
回答by Santiago árraga
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.
使用 PW_CALLBACK_REF 代替 PW_CALLBACK_CLASS,并传递一个实例化的对象,而不是静态类。您可以在所述对象中注入密码。
Something like:
就像是:
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
CXFClientPasswordHandler handler = new CXFClientPasswordHandler();
handler.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
回答by jayraynet
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);
回答by veben
Your ClientPasswordCallback
class may be like that, with his own pwdfield and the associated setter:
你的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);
}
}
Then you can instanciate it in your test, set its password and use PW_CALLBACK_REF
key to add it to the outProps
map:
然后你可以在你的测试中实例化它,设置它的密码并使用PW_CALLBACK_REF
key 将它添加到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);
// ...
}
回答by Sabiya
I have always used following way of adding properties to request context for http level authentication and CallbackHandler for adding message level username token.
我一直使用以下方式添加属性以请求上下文以进行 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");
}
}
}
}