Announcement Announcement Module
Collapse
No announcement yet.
Getting WSSE username and password inside PayloadEndpoint? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting WSSE username and password inside PayloadEndpoint?

    Hi everyone,

    I'm implementing a security token service from WS-Trust. Basically I accept one request, a RequestSecurityToken which has included in it a WSSE UsernameToken. Spring-ws is verifying that the username and password exist and match in my user dao nicely. However, I need to return a list of all the requested claims and their values, which implies a second lookup into my user dao (with the same username/password). But I don't know how to get the username and password that were passed along with the soap message!

    I could create my own endpoint I suppose, but then I would essentially just be copying + pasting the code from AbstractDomPayloadEndpoint, but implementing MessageEndpoint... that seems like the wrong approach.

    Another approach I thought about was creating an interceptor... but let's say my interceptor parses out the UsernameToken... how do I pass that information into my endpoint so it's available during invokeInternal??

    Has anyone got any advice? Just fishing for some ideas....

    Thanks,

  • #2
    Just a follow up: there is a workaround described in this thread.

    In order to pass the extracted data from an interceptor and have it accessible from an endpoint, you need an intermediate bean that has scope="request", so in my case I made a bean called UsernamePassword like so
    Code:
    public interface UsernamePassword {
        public String getUsername();
        public void setUsername(String username);
        public void getPassword();
        public void setPassword(String password);
    }
    ...
    public class UsernamePasswordImpl implements UsernamePassword {
        ...
        public String getUsername() {...}
        public void setUsername(String username) {...}
        public void getPassword() {...}
        public void setPassword(String password) {...}
    }
    now, I create that bean in the application context, but give it request scope that each time it is accessed, you really are accessing a unique copy per http request

    Code:
        <bean id="requestScopedUsernamePassword" class="pkg.UsernamePasswordImpl" scope="request">
        	<aop:scoped-proxy/>
        </bean>
    Next, we can create properties in both the interceptor and the endpoint which point that request scoped instance, allowing both instances to "dirty" the internal state of the UsernamePassword object, but be assured they are always accessing the proper one, depending on the http request!

    Code:
    public class MyInterceptor extends EndpointInterceptorAdapter {
        ...
        private UsernamePassword usernamePassword;
        ...
        public void setUsernamePassword(UsernamePassword usernamePassword) {
            this.usernamePassword = usernamePassword;
        }
        public boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception {
            //extract the usernamepassword token from the SOAP headers
            ....
            //this bean will always "point" to the correct one for each request!
            usernamePassword.setUsername(username);
            usernamePassword.setPassword(password);
            ....
        }
    }
    public class MyEndpoint extends AbstractDomPayloadEndpoint {
        ...
        private UsernamePassword usernamePassword;
        ...
        public void setUsernamePassword(UsernamePassword usernamePassword) {
            this.usernamePassword = usernamePassword;
        }
        ...
        protected Element invokeInternal(Element requestElement, Document responseDocument) throws Exception {
            // here you can safely access the correct usernamePassword object!
            lookupStuffInDatabase(usernamePassword.getUsername(), usernamePassword.getPassword());
        }
    }
    Hope this helps.

    The only downside to this approach is that it seems a little unintuitive, and adds a dependency on CGLIB. Also you may need to add a RequestContextListener to your web.xml.

    Code:
    	<listener>
        	<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    	</listener>

    Comment

    Working...
    X