【问题标题】:Retrieve plaintext WS-Security password at service endpoint with Metro + WSIT?使用 Metro + WSIT 在服务端点检索明文 WS-Security 密码?
【发布时间】:2012-10-29 03:21:07
【问题描述】:

我正在编写一个 SOAP 服务(我们称之为 X),它充当某种“转发代理”,替换正文中的几个元素,然后调用另一个 SOAP 服务 (Y)。我想使用调用 Y 时在 X 中收到的相同 WS-Security 凭据(plaintext 用户名和密码),但我无法检索 Password 元素的值。

我在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-Addressing,我可以使用处理程序(SOAPHandler&lt;SOAPMessageContext&gt; 的实现)来提取值,然后将它们放回应用程序范围下的上下文中,以便我的端点检索。在 SOAP 消息到达我的处理程序链时,WS-Security 标头已经被剥离,因此无法在处理程序中检索它们的值。

没有做一些激烈的事情,比如使用验证器将密码存储在数据库/全局映射/线程本地存储中,我有什么方法可以检索在我的端点提供的 WS-Security 密码?

我应该注意,我可以通过Subject subj = SubjectAccessor.getRequesterSubject(context) 在我的端点访问 WS-Security 用户名信息,但这似乎不包含密码。

【问题讨论】:

    标签: java jax-ws ws-security java-metro-framework wsit


    【解决方案1】:

    由于缺乏更好的解决方案,我最终使用 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;
        }
    
    }
    

    【讨论】:

    • 它很聪明,但似乎有点hacky。你怎么知道在每种情况下的每个请求,密码验证器和 ws 实现都会从同一个线程执行?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多