Automatic NTLM Authentication for WSO2 ESB

后端 未结 2 1505
夕颜
夕颜 2021-01-27 01:58

I have a WCF Web Service sitting on a client\'s IIS server secured with NTLM authentication - I have no control over the authentication configuration on that server.

I

2条回答
  •  离开以前
    2021-01-27 02:37

    There were a few components to getting this working correctly. It's hard to find it all written down in one place, so I'll attempt to provide an end-to-end overview here.

    I first had to use a class mediator within my WSO2 ESB in-sequence to handle the sending and the NTLM authentication. The class mediator references a custom class which takes the message context from the mediation flow (called the Synapse message context) and extracts the SOAP envelope. I then loaded the Synapse SOAP envelope into an Axis2 message context object. I then used an Axis2 client along with the message context to submit my authenticated request to the server. The authentication for NTLM through Axis2 comes from the JCIFS_NTLMScheme class, which you can reference here.

    Note: you'll have to play with the logging configuration in that class to make it work with WSO2. I just removed the " org.sac.crosspather.common.util* " libraries and altered any logging I saw to use the Apache Commons logging capability


    Create a Custom Mediator Project in WSO2 Developer Studio

    Create a new project in Developer studio. Right click the project node in the project explorer and select "New > Mediator Project".

    This will generate a bit of boilerplate code for you - that is, a class which extends AbstractMediator and which implements an "mediate()" method which Synapse will call when it comes to executing the logic defined within your sequence.

    public class NTLMAuthorisation extends AbstractMediator {
    
      public boolean mediate(MessageContext context){
    
        //Mediation Logic  
    
        return true;  
    
      }  
    
    }
    


    Expose Some Variables/Properties to the User

    The class mediator looks for variables which are publicly accessible and exposes them in the WSO2 configuration. This is helpful before you can create a re-usable mediator which adapts itself to properties or values defined in the WSO2 Carbon Web UI. Here we need to expose seven variables: soapAction, SoapEndpoint, domain, host, port, username, and password. Expose the variables by defining your instance variables, along with their accessors and mutators.

    This is all really quite useful for using the WSO2 Secure Vault to store your NTLM password and fetching other configuration from a system registry with properties.

    public class NTLMAuthorisation extends AbstractMediator { 
    
        private String soapAction;
        private String soapEndpoint;
        private String domain;
        private String host;
        private int port;
        private String username;
        private String password;
    
        public boolean mediate(MessageContext context) { 
    
            //Mediation Logic
    
            return true;
    
        }
    
        public void setSoapAction(String _soapAction){
            soapAction = _soapAction;
        }
    
        public String getSoapAction(){
            return soapAction;
        }
    
        public void setSoapEndpoint(String _soapEndpoint){
            soapEndpoint = _soapEndpoint;
        }
    
        public String getSoapEndpoint(){
            return soapEndpoint;
        }
    
        public void setDomain(String _domain){
            domain = _domain;
        }
    
        public String getDomain(){
            return domain;
        }
    
        public void setHost(String _host){
            host = _host;
        }
    
        public String getHost(){
            return host;
        }
    
        public void setPort(int _port){
            port = _port;
        }
    
        public int getPort(){
            return port;
        }
    
        public void setUsername(String _username){
            username = _username;
        }
    
        public String getUsername(){
            return username;
        }
    
        public void setPassword(String _password){
            password = _password;
        }
    
        public String getPassword(){
            return password;
        }
    
    }
    


    The Custom Mediation Logic

    Make sure you created an JCIFS_NTLMScheme class from here and have added the org.samba.jcifs dependency to your Maven dependencies like so:

    
      org.samba.jcifs
      jcifs
      1.3.17
    
    

    Now you can use the following mediate method in your custom mediator class:

    public boolean mediate(MessageContext context) { 
    
        //Build NTLM Authentication Scheme
        AuthPolicy.registerAuthScheme(AuthPolicy.NTLM, JCIFS_NTLMScheme.class);
        HttpTransportProperties.Authenticator auth = new HttpTransportProperties.Authenticator();
        auth.setUsername(username);
        auth.setPassword(password);
        auth.setDomain(domain);
        auth.setHost(host);
        auth.setPort(port);
        ArrayList authPrefs = new ArrayList();
        authPrefs.add(AuthPolicy.NTLM);
        auth.setAuthSchemes(authPrefs);
    
        //Force Authentication - failures will get caught in the catch block
        try {
    
            //Build ServiceClient and set Authorization Options
            ServiceClient serviceClient = new ServiceClient();
            Options options = new Options();
            options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, auth);
            options.setTransportInProtocol(Constants.TRANSPORT_HTTP);
            options.setTo(new EndpointReference(soapEndpoint));
            options.setAction(soapAction);
            serviceClient.setOptions(options);
    
            //Generate an OperationClient from the ServiceClient to execute the request
            OperationClient opClient = serviceClient.createClient(ServiceClient.ANON_OUT_IN_OP);
    
            //Have to translate MsgCtx from Synapse to Axis2
            org.apache.axis2.context.MessageContext axisMsgCtx = new org.apache.axis2.context.MessageContext();  
            axisMsgCtx.setEnvelope(context.getEnvelope());
            opClient.addMessageContext(axisMsgCtx);
    
            //Send the request to the server
            opClient.execute(true);
    
            //Retrieve Result and replace mediation (synapse) context
            SOAPEnvelope result = opClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE).getEnvelope();
            context.setEnvelope(result);
    
        } catch (AxisFault e) {
    
            context.setProperty("ResponseCode", e.getFaultCodeElement().getText());
    
            return false; //This stops the mediation flow, so I think it executes the fault sequence?
    
        }
    
        return true;
    
    }
    


    Package as an OSGi Bundle and Deploy to the Server

    At this stage you should be able to your custom mediator project within the project explorer in WSO2 Developer Studio and from the context menu select Export Project as Deployable Archive. Follow the prompts to save the JAR file somewhere on your system. After generating the JAR file, locate it and transfer it to the [ESB_HOME]/repository/components/dropins directory. You may need to restart the server for it to detect the new external library.


    Using the Custom Mediator

    In your sequence, you should now be able to add a class mediator and reference your custom class using the package name and class name together, for example: org.strainy.ntlmauthorisation.

提交回复
热议问题