开发者

custom interceptor for cxf service to allow spring security authentication

I'm using spring security for authentication in my app and now I'm exposing a web service using cxf and I want to authenticate the current web service call using spring security. But I need to access the certificate in the web service call (i'm using ws-security)

This is an excerpt of my cxf bean declaration:

<jaxws:endpoint id="service2"
                    implementor="xxx.service2.CXFLibraryImpl"
                    wsdlLocation="classpath:service2.wsdl"
                    address="/service2">
  <jaxws:inInterceptors>

            <bean class="com.kprtech.service.ws.service2.MyWSS4JInInterceptor">
            </bean>
</jaxws:endpoint>

THis is the wsdl exposing ws-security:

<?xml version='1.0' encoding='UTF-8'?><wsdl:definitions name="CXFLibraryImplService" targetNamespace="http://service2.ws.service.kprtech.com/" xmlns:ns1="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://service2.ws.service.kprtech.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <wsdl:types>
<xs:schema elementFormDefault="unqualified" targetNamespace="http://service2.ws.service.kprtech.com/" version="1.0" xmlns:ns1="http://cxf.apache.org/bindings/xformat" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://service2.ws.service.kprtech.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xs:element name="sayHello" type="tns:sayHello" />
<xs:element name="sayHelloResponse" type="tns:sayHelloResponse" />
<xs:complexType name="sayHello">
<xs:sequence>
<xs:element minOccurs="0" name="arg0" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="sayHelloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
  </wsdl:types>
  <wsdl:message name="sayHello">
    <wsdl:part element="tns:sayHello" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="sayHelloResponse">
    <wsdl:part element="tns:sayHelloResponse" name="parameters">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="Library">
    <wsdl:operation name="sayHello">
      <wsdl:input message="tns:sayHello" name="sayHello">
    </wsdl:input>
      <wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="CXFLibraryImplServiceSoapBinding" type="tns:Library">
    <wsp:PolicyReference URI="#SignEncr" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" />
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="sayHello">
      <soap:operation soapAction="" style="document" />
      <wsdl:input name="sayHello">
        <soap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="sayHelloResponse">
        <soap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CXFLibraryImplService">
    <wsdl:port binding="tns:CXFLibraryImplServiceSoapBinding" name="CXFLibraryImplPort">
      <soap:address location="http://localhost:8888/domicilios/services/service2" />
    </wsdl:port>
  </wsdl:service>
    <wsp:Policy wsu:Id="SignEncr" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

    &l开发者_如何学JAVAt;wsp:ExactlyOne>
      <wsp:All>
        <sp:AsymmetricBinding xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
          <wsp:Policy>
            <sp:InitiatorToken>
              <wsp:Policy>
                <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
                  <wsp:Policy>
                    <sp:RequireThumbprintReference />
                      <sp:WssX509V1Token10 />
                  </wsp:Policy>
                </sp:X509Token>
              </wsp:Policy>
            </sp:InitiatorToken>
            <sp:RecipientToken>
              <wsp:Policy>
                <sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">
                  <wsp:Policy>
                    <sp:RequireThumbprintReference />
                        <sp:WssX509V3Token10 />
                  </wsp:Policy>
                </sp:X509Token>
              </wsp:Policy>
            </sp:RecipientToken>
            <sp:AlgorithmSuite>
              <wsp:Policy>
                <sp:TripleDesRsa15 />
              </wsp:Policy>
            </sp:AlgorithmSuite>
            <sp:Layout>
              <wsp:Policy>
                <sp:Strict />
              </wsp:Policy>
            </sp:Layout>
            <sp:IncludeTimestamp />
            <sp:OnlySignEntireHeadersAndBody />
          </wsp:Policy>
        </sp:AsymmetricBinding>
          <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
                <wsp:Policy>
                    <sp:MustSupportRefKeyIdentifier />
                    <sp:MustSupportRefIssuerSerial />
                </wsp:Policy>
            </sp:Wss10>
        <sp:SignedParts xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
          <sp:Body />
        </sp:SignedParts>

      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
</wsdl:definitions>

The problem is that even with my custom interceptor cxf is using org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JInInterceptor

and trying to validate certs and security tokens against a crypto, and I want to do this operation by my own in my custom interceptor com.kprtech.service.ws.service2.MyWSS4JInInterceptor


I solved this some time ago:

You need a CXF configuration like the following:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">


    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-policy.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-ws-security.xml"/>

    <bean id="implementorBean" class="ws.Implementor"/>

    <jaxws:endpoint id="implementor"
                    implementor="#implementorBean"
                    wsdlLocation="/ws/server/service.wsdl"
                    address="/service">

        <jaxws:inInterceptors>

            <bean class="ws.SpringSecurityInterceptor">

            </bean>
        </jaxws:inInterceptors>

        <jaxws:properties>
            <entry key="ws-security.signature.properties" value="/ws/security/server-crypto.properties"/>
            <entry key="ws-security.signature.username" value="serverkey"/>
            <entry key="ws-security.callback-handler" value="ws.ServerCallback"/>
        </jaxws:properties>

    </jaxws:endpoint>

</beans>

And implement the interceptor like this one:

public class SpringSecurityInterceptor extends AbstractWSS4JInterceptor {

    private ThreadLocal<Subject> currentSubject = new ThreadLocal<Subject>();


    public SpringSecurityInterceptor() {
        super();
        setPhase(Phase.PRE_PROTOCOL);
        getAfter().add(WSS4JInInterceptor.class.getName());
        getAfter().add(PolicyBasedWSS4JInInterceptor.class.getName());
    }


    public void handleMessage(SoapMessage message) throws Fault {

        try {

            Subject subject = (Subject) currentSubject.get();

            if (subject == null) {
                subject = new Subject();
                currentSubject.set(subject);
            }
            List<Object> results = (List<Object>)message.get(WSHandlerConstants.RECV_RESULTS);
            if (results == null) {
                return;
            }
            for (Iterator iter = results.iterator(); iter.hasNext();) {
                WSHandlerResult hr = (WSHandlerResult) iter.next();
                if (hr == null || hr.getResults() == null) {
                    return;
                }

                    for (Iterator it = hr.getResults().iterator(); it.hasNext();) {
                      WSSecurityEngineResult er = (WSSecurityEngineResult) it.next();

                        if (er != null && er.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE) instanceof X509Certificate) {
                          X509Certificate cert = (X509Certificate)er.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);

                              // TODO do something with the certificate

                      }
                    }

            }

            message.put(Subject.class, subject);

        } catch (java.lang.reflect.UndeclaredThrowableException e) {
            Throwable undeclared = e.getUndeclaredThrowable();
            if (undeclared != null
                    && undeclared instanceof java.lang.reflect.InvocationTargetException) {
                throw new Fault(
                        ((java.lang.reflect.InvocationTargetException) undeclared)
                                .getTargetException());
            }

        } finally {
            currentSubject.set(null);
        }
    }


}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜