Search code examples
cxfws-security

How to disable/enable WS-Security for some server methods only with CXF?


I'm configuring WS-Security for my web service with Apache CXF. I've added WSS4JInInterceptor and callback and it's working. The problem is that some methods don't require to be protected by WS-Security and some should.

How can i do that way? Any annotations or input map keys for WSS4JInInterceptor?

I can see in WSS4jInInterceptor code:

public void handleMessage(SoapMessage msg) throws Fault {
        if (msg.containsKey(SECURITY_PROCESSED) || isGET(msg)) {
            return;
        }

So it seems i can add my custom interceptor and add SECURITY_PROCESSED to unprotected methods, but it seems that there is better approach.


Solution

  • For now i had to reinvent the wheel with my own Interceptor impl:

        // adds skip flag for methods that should not be checked
        public static class CheckMethodsInterceptor implements PhaseInterceptor<SoapMessage> {
    
            private List<String> checkedMethods;
    
            public CheckMethodsInterceptor(List<String> checkedMethods) {
                this.checkedMethods = checkedMethods;
            }
    
            protected void allowConnection(SoapMessage message) {
                // skip checking by WSS4JInInterceptor
                message.put(WSS4JInInterceptor.SECURITY_PROCESSED, "true");
            }
    
            @Override
            public void handleMessage(SoapMessage message) throws Fault {
                String action = (String)message.get("SOAPAction");
                if (action == null || !checkedMethods.contains(action.substring(action.lastIndexOf("/") + 1))) {
                    allowConnection(message);
                }
            }
    
            @Override
            public Set<String> getAfter() {
                return Collections.emptySet();
            }
    
            @Override
            public Set<String> getBefore() {
                return Collections.emptySet();
            }
    
            @Override
            public String getId() {
                return CheckMethodsInterceptor.class.getName();
            }
    
            @Override
            public String getPhase() {
                return Phase.PRE_PROTOCOL;
            }
    
            @Override
            public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
                return null;
            }
    
            @Override
            public void handleFault(SoapMessage message) {
    
            }
        }
    

    and use it like this:

        // checked methods only (before WSS4JInInterceptor !)
        SecurityService.CheckMethodsInterceptor checkMethodsInterceptor =
            new SecurityService.CheckMethodsInterceptor(Arrays.asList(
                "CreateUsers",
                "GetUsers"
            ));
        ep.getServer().getEndpoint().getInInterceptors().add(checkMethodsInterceptor);
    
        WSS4JInInterceptor inSecurityInterceptor = new WSS4JInInterceptor(inSecurityProperties);
    

    Feel free to suggest better solution.