使用Metro + WSIT检索服务端点处的纯文本WS-Security密码? [英] Retrieve plaintext WS-Security password at service endpoint with Metro + WSIT?

查看:120
本文介绍了使用Metro + WSIT检索服务端点处的纯文本WS-Security密码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个SOAP服务(简称为X),充当各种转发代理",替换主体中的几个元素,然后调用另一个SOAP服务(Y).我想使用在调用Y时在X中收到的相同的WS-Security凭据(纯文本用户名和密码),但是在检索Password元素的值时遇到了麻烦.

I'm writing a SOAP service (let's call it X) that acts as a "forwarding proxy" of sorts, replacing several elements in the body, then calling another SOAP service (Y). I would like to use the same WS-Security credentials (plaintext username and password) that I receive in X when I call Y, but I am having trouble retrieving the value of the Password element.

我在wsit-package.service.xml文件中声明的策略引用了com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidator的实现:

The policy that I declare in my wsit-package.service.xml file references an implementation of 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>

我能够在验证器中访问密码:

I am able to access the password in the validator:

@Override
public boolean validate(Request request) throws PasswordValidationException {
    String password = ((PlainTextPasswordRequest) request).getPassword();
    return true;
}

但是,由于验证者没有访问WebServiceContext的权限,因此没有方便的位置来存储它可供我的服务端点访问.

However, since the validator does not have access to the WebServiceContext, there is not a convenient place to store it that is accessible to my service endpoint.

带有其他标题,例如WS-Addressing,我可以使用处理程序(SOAPHandler<SOAPMessageContext>的实现)提取值,然后将其放回应用程序范围内的上下文中,以供端点检索. SOAP消息到达我的处理程序链时,WS-Security标头已经被剥离,因此无法在处理程序中检索它们的值.

With other headers, e.g. WS-Addressing, I am able to use a Handler (implementation of SOAPHandler<SOAPMessageContext>) to pull out the values, then put them back in the context under the application scope for my endpoint to retrieve. WS-Security headers are already stripped by the time the SOAP message gets to my handler chain, so there is no way to retrieve their values in a Handler.

需要做一些大胆的事情,例如使用验证器将密码存储在数据库/全局映射/线程本地存储中,我是否有任何方法可以检索端点提供的WS-Security密码?/strong>

Short of doing something drastic like using the validator to store the password in a database/global map/threadlocal storage, is there any way for me to retrieve the WS-Security Password that was supplied at my endpoint?

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

I should note that I am able to access the WS-Security Username information at my endpoint via Subject subj = SubjectAccessor.getRequesterSubject(context), but this does not appear to contain the password.

推荐答案

由于缺乏更好的解决方案,我最终使用ThreadLocal存储访问服务端点中的WS-Security用户名和密码:

For lack of a better solution, I ended up using ThreadLocal storage to access the WS-Security Username and Password in my service endpoint:

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

}

这篇关于使用Metro + WSIT检索服务端点处的纯文本WS-Security密码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆