我正在编写SOAP服务(让我们称之为X),它充当“转发代理”,替换了主体中的几个元素,然后调用另一个SOAP服务(Y)。当我调用Y时,我想使用在X中接收到的相同的WS-安全凭据(明文用户名和密码),但我在检索密码元素的值时遇到了问题。
我在wsit-package.service.xml文件中声明的策略引用了com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidator的实现。
<wsp1_2:Policy wsu:Id="UsernameToken"
xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"
xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"
xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
<wsp1_2:ExactlyOne>
<wsp1_2:All>
<sp:SupportingTokens>
<wsp1_2:Policy>
<sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient" />
<sp:IncludeTimestamp />
</wsp1_2:Policy>
</sp:SupportingTokens>
<wsss:ValidatorConfiguration wspp:visibility="private" >
<wsss:Validator name="usernameValidator"
classname="com.service.validator.SecurityValidator" />
</wsss:ValidatorConfiguration>
</wsp1_2:All>
</wsp1_2:ExactlyOne>
</wsp1_2:Policy>我能够访问验证器中的密码:
@Override
public boolean validate(Request request) throws PasswordValidationException {
String password = ((PlainTextPasswordRequest) request).getPassword();
return true;
}但是,由于验证器没有访问WebServiceContext的权限,所以没有一个方便的存储位置可以供我的服务端点访问。
对于其他标头,例如WS寻址,我可以使用Handler (SOAPHandler<SOAPMessageContext>的实现)提取值,然后将它们放在应用程序范围下的上下文中,供端点检索。报头在SOAP消息到达我的处理程序链时已经被删除,因此无法在Handler中检索它们的值。
除了使用验证器将密码存储在数据库/全局映射/线程本地存储等极端操作之外,是否有任何方法可以检索在我的端点上提供的WS-Security密码?
我应该注意,我可以通过Subject subj = SubjectAccessor.getRequesterSubject(context)访问端点上的WS-Security用户名信息,但这似乎不包含密码。
发布于 2012-11-19 18:34:57
由于缺乏更好的解决方案,我最终使用ThreadLocal存储来访问服务端点中的WS-Security用户名和密码:
package com.my.ws.validator;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidationException;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidator;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback.PlainTextPasswordRequest;
import com.sun.xml.wss.impl.callback.PasswordValidationCallback.Request;
public class SecurityValidator implements PasswordValidator {
private static final ThreadLocal<String> username = new ThreadLocal<String>();
private static final ThreadLocal<String> password = new ThreadLocal<String>();
@Override
public boolean validate(final Request request) throws PasswordValidationException {
if (request instanceof PlainTextPasswordRequest) {
PlainTextPasswordRequest plainText = (PlainTextPasswordRequest) request;
if (null == plainText.getUsername() || plainText.getUsername().trim().isEmpty())
throw new PasswordValidationException("A username must be provided");
else
username.set(plainText.getUsername());
if (null == plainText.getPassword() || plainText.getPassword().trim().isEmpty())
throw new PasswordValidationException("A password must be provided");
else
password.set(plainText.getPassword());
return true;
}
return false;
}
public static String getUsername() {
String user = username.get();
username.remove();
return user;
}
public static String getPassword() {
String pass = password.get();
password.remove();
return pass;
}
}https://stackoverflow.com/questions/13297345
复制相似问题