Announcement Announcement Module
Collapse
No announcement yet.
Login interceptor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Login interceptor

    I'm having a bit of a bad brain day and was hoping someone kind might help me out. It's probably a shocking simple question. I'm using Spring MVC for the first time (I'm used to Struts), and am trying to create the simplest of login mechanisms, inspired by the one in the JPetstore example. Below is my testapp-servlet.xml:

    Code:
    <beans>
    
    	<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    		<property name="prefix" value="/WEB-INF/jsp/"/>
    		<property name="suffix" value=".jsp"/>
    	</bean>
    
    	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    		<property name="interceptors">
    			<list>
    				<ref bean="loginInterceptor"/>
    			</list>
    		</property>
    		<property name="mappings">
    			<props>
    				<prop key="/test.htm">testController</prop>
    				<prop key="/login.htm">loginController</prop>
    			</props>
    		</property>
    	</bean>
    
    	<bean id="loginInterceptor" class="testapp.web.LoginInterceptor"/>
    	
    	<bean name="testController" class="testapp.web.TestController"/>
    	
    	<bean name="loginController" class="testapp.web.LoginController">
    		<property name="dataService" ref="dataService"/>
    	</bean>
    
    </beans>
    What should happen is that the LoginInterceptor checks to see whether there is a valid User object contained in the session, and if not, it throws a ModelAndViewDefiningException which causes Spring to reroute to the login JSP. What should then happen is the login controller takes over and checks the details entered. What is instead happening, of course, is that the LoginInterceptor is kicking in for a second time, detecting that the User object is missing and reroutin to the same JSP. So how do I avoid the LoginInterceptor applying when the URL is /login.htm, which is presumably what I need to do?
    Last edited by jonmor; Dec 19th, 2005, 09:51 AM. Reason: Code needed formatting

  • #2
    You can define more than one urlMapping in the *-servlet.xml file. Have the interceptor associated with the one that doesn't include login.html, and the mapping for login.html won't include the loginInterceptor.

    Having said all of that, I really encourage you to check out Acegi Security (acegisecurity.org). You'll spend a day (or at least a few hours) figuring it out and getting it working, but it'll be well worth it as your appplication grows. And you won't have to worry about maintaining your own home grown security code.

    Cheers,
    Christian

    Comment


    • #3
      Originally posted by cnelson
      You can define more than one urlMapping in the *-servlet.xml file. Have the interceptor associated with the one that doesn't include login.html, and the mapping for login.html won't include the loginInterceptor.
      Thanks, I wondered whether there was something like that.

      Having said all of that, I really encourage you to check out Acegi Security (acegisecurity.org). You'll spend a day (or at least a few hours) figuring it out and getting it working, but it'll be well worth it as your appplication grows. And you won't have to worry about maintaining your own home grown security code.
      I may well come back to Acegi if it looks like I'm going to need anything more than the very simple solution I'm using at present.

      Comment


      • #4
        I usually inject the Interceptor with a Map of URLs not to be "intercepted".

        This way, I can tell the interceptor that the login page should not be intercepted and that's all.

        Maybe there's a more elegant solution.

        Regards,
        Esteve

        PD: Another solution I've used is to use a "directory" for secured controllers. You map the controllers that should be intercepted to an specific "directory" e.g. "/secure/Display.htm". They, modify your interceptor only to check for URLs starting with "/secure".
        Then use a mapping w/o the "secure" directory for your Login controller.

        Comment


        • #5
          Originally posted by eboix
          I usually inject the Interceptor with a Map of URLs not to be "intercepted".

          This way, I can tell the interceptor that the login page should not be intercepted and that's all.
          This is interesting as an example of proper 'Spring thinking', which I'm still not doing fully. The simplest way of dealing with the situation was for my interceptor code to check the URL and ignore it if it was the login URL, but I shied away from that as I really did not want to be hard coding URLs into my code, particularly as it involved repeating something from the config file. The idea of getting Spring to inject that information for me is a much better one.

          Comment


          • #6
            OK, by this time I'm beginning to wonder whether I should have gone for Acegi after all. But the problem I'm having now is actually to do with the way Spring MVC works, which I need to understand for other things, so I could do with a helping hand again...

            I've now changed the LoginController to extend SimpleFormController (partly to get to know form controllers), and as a result I have run into a problem. Previously what was happening was that the interceptor was checking to see if a valid User object existed in the session, and if not, it forwarded to the login.jsp ModelAndView, after recording the original request URL and any query details, so that when the user did log in, they would be taken to the page they had originally intended to get. Now, though, I get a JSP error because I am going direct to the JSP from the interceptor, thus the Errors object and blank User object are not getting set. With the change to a form controller, the login.jsp can only be used via the LoginController.

            Now, I could of course issue a simple redirect in the interceptor's preHandle (rather than throwing a ModelAndViewDefiningException as I do at present), and redirect to the /login.htm page (which is mapped to the LoginController). But how would I then move the user on to their original intended target after a successful login? The only solutions I can think of (like sticking the original URL and query into the session as an attribute to be picked up in the JSP) are kludgy and messy. I am assuming there is a better way. Any suggestions?

            Comment


            • #7
              Answering my own question again here...

              The solution I have adopted (whether it's the best one or not I can't say) is to continue with throwing a ModelAndViewDefiningException, but with a ModelAndView whose view is a RedirectView, and have the target URL+query parameters added as an Object to the ModelAndView. Thus:

              Code:
              	String url = request.getServletPath();
              			String query = request.getQueryString();
              			RedirectView redirectView = new RedirectView(getLoginUrl());
              			redirectView.setContextRelative(true);
              			if (query != null) {
              				url += "?" + query;
              			}
              			ModelAndView modelAndView=new ModelAndView(redirectView);
              			logger.debug("Setting signonForwardAction to " + url);
              			modelAndView.addObject("signonForwardAction", url);
              			throw new ModelAndViewDefiningException(modelAndView);
              Then when the page to which we have been redirected is displayed, the 'signonForwardAction' string is nicely displayed as a query string.

              Comment

              Working...
              X