简体   繁体   English

使用Apache CXF验证SOAP usernameToken时出现问题

[英]Problem authenticating SOAP usernameToken with Apache CXF

I'm trying to develop a SOAP web service under Apache CXF 3.0.4 , but i'm having trouble authenticating the UsernameToken included in every SOAP message header using WS-SecurityPolicy. 我正在尝试在Apache CXF 3.0.4下开发SOAP Web服务,但是使用WS-SecurityPolicy对每个SOAP消息头中包含的UsernameToken身份验证时遇到了麻烦。 According to the documentation , WS-SecurityPolicy is automatically enabled if the cxf-rt-ws-policy and cxf-rt-ws-security modules are available on the classpath . 根据文档 ,如果在classpath上提供了cxf-rt-ws-policycxf-rt-ws-security模块,则会自动启用WS-SecurityPolicy。 It does the necessary work to handle security, after a proper configuration. 正确配置后,它会做必要的工作来处理安全性。 I do configuration through Endpoint Property Annotations, in the following way: 我通过“端点属性注释”以以下方式进行配置:

@WebService(targetNamespace = "http://tempuri.org/", name = "MyService")

@EndpointProperties(value = {
        @EndpointProperty(key = "ws-security.callback-handler", value = "org.tempuri.ServerPasswordCallback")
        //@EndpointProperty(key = "ws-security.validate.token", value = "false")
    }
)


public interface MyService {
...
}

The ServerPasswordCallback is: ServerPasswordCallback为:

public class ServerPasswordCallback implements CallbackHandler {

    public ServerPasswordCallback() {
        System.out.println("Instantiating ServerPasswordCallback");
    }

    public void handle(Callback[] callbacks) throws IOException,
            UnsupportedCallbackException {

        System.out.println("Validating on ServerPasswordCallback");

        WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];

        if (pc.getIdentifier().equals("joe")) {
            // set the password on the callback. This will be compared to the
            // password which was sent from the client.
            pc.setPassword("password");
        }
    }

}

The problem is that i get the following exception: 问题是我得到以下异常:

Caused by: org.apache.wss4j.common.ext.WSSecurityException: The security token could not be authenticated or authorized
        at org.apache.wss4j.dom.validate.UsernameTokenValidator.verifyDigestPassword(UsernameTokenValidator.java:176)
        at org.apache.wss4j.dom.validate.UsernameTokenValidator.verifyPlaintextPassword(UsernameTokenValidator.java:136)
        at org.apache.wss4j.dom.validate.UsernameTokenValidator.validate(UsernameTokenValidator.java:94)

The sent message's header is: 发送的邮件头是:

<?xml version="1.0"?>
<soapenv:Header>
  <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wsse:UsernameToken wsu:Id="UsernameToken-3B91E43693FA4F34C61536922750459149">
      <wsse:Username>joe</wsse:Username>
      <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
      <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">ey+3J+OKoHlhfqREn7Q8jw==</wsse:Nonce>
      <wsu:Created>2018-09-14T10:59:10.459Z</wsu:Created>
    </wsse:UsernameToken>
    <wsu:Timestamp wsu:Id="TS-3B91E43693FA4F34C61536922750459148">
      <wsu:Created>2018-09-14T10:59:10.459Z</wsu:Created>
      <wsu:Expires>2018-09-14T10:59:15.459Z</wsu:Expires>
    </wsu:Timestamp>
  </wsse:Security>
</soapenv:Header>

The strange thing is that seems that ServerPasswordCallback is never instantiated, and handle() is never called. 奇怪的是,似乎ServerPasswordCallback从未实例化,并且handle()从未被调用。 If in the Endpoint properties annotations i set ws-security.validate.token to false , the former Exception is thrown, even if this property should prevent Token validation. 如果在Endpoint属性注释中将ws-security.validate.token设置为false ,则即使该属性阻止令牌验证,也会抛出前一个Exception。 That fact make me think that annotations are not working, but i can't figure out why. 这个事实使我认为注释不起作用,但是我不知道为什么。 Is this the correct way of authenticating a UsernameToken ? 这是验证UsernameToken的正确方法吗? Are the Endpoint properties annotations correct? 端点属性注释正确吗?

NB I can't set Endpoint properties like suggested in the documentation because I have not access to Endpoint instance. 注意:由于无法访问Endpoint实例,因此无法设置文档中建议的Endpoint属性。 A sample project is available here 这里有一个示例项目

Finally I figured out a solution: 最后,我想出了一个解决方案:

@WebService(targetNamespace = "http://tempuri.org/", name = "MyService")

@EndpointProperties(value = {
        @EndpointProperty(key = "webservice.security.authMethod", value = "WS-SECURITY")
        @EndpointProperty(key = "ws-security.callback-handler", value = "org.tempuri.ServerPasswordCallback")
    }
)


public interface MyService {
...
}

In order to make the annotations working, it's necessary to include the following annotation in the EndpointProperties: 为了使注释起作用,必须在EndpointProperties中包含以下注释:

@EndpointProperty(key = "webservice.security.authMethod", value = "WS-SECURITY")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM