Spring MVC redirect user to login page once sessio

2019-07-04 00:54发布

问题:

I have stored a user bean in session as @SessionAttributes({"UserBean"}) in my controller.

My aim is to redirect user to login/error page if session is expired. Following is my code snippet

@RequestMapping(value = "searchOpportunity.htm", method = RequestMethod.GET)
public ModelAndView searchOpportunity(@ModelAttribute("UserBean") UserBean userBean) {
    functionName = "searchOpportunity";
    logger.info("HERE !!! In " + className + " - " + functionName + " ");
    System.out.println("HERE !!! In " + className + " - " + functionName + " ");
    try {
        if (userBean == null) {
            System.out.println(userBean);
            return new ModelAndView("userLogout", "command", null);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new ModelAndView("opportunity/opportunitySearch", "command", new SearchOpportunityBean());
}

However when the session is expired i get the following error.

org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet mintDispatcher threw exception
org.springframework.web.HttpSessionRequiredException: Session attribute 'UserBean' required - not found in session
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.raiseSessionRequiredException(AnnotationMethodHandlerAdapter.java:761)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveModelAttribute(HandlerMethodInvoker.java:758)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:356)
    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
    at java.lang.Thread.run(Unknown Source)

Seems like the controller code is never executed if userbean is expired. What is the reason ? What can be a solution ?

回答1:

Why don't you try this with Spring Security?

<sec:session-management invalid-session-url="/login">
        <sec:concurrency-control expired-url="/login" />
</sec:session-management>

This will redirect to /login page when the user's session is expired or invalid.

Ref: http://docs.spring.io/spring-security/site/docs/3.0.x/reference/springsecurity.html



回答2:

You can do it by the help of HandlerInterceptorAdapter. The preHandle() method should return true if the execution chain should proceed with the next interceptor or the handler( your controller) itself. Else, DispatcherServlet assumes that this interceptor has already dealt with the response itself.

    public class YourInterceptor extends HandlerInterceptorAdapter {
        public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
            UserBean userBean = (UserBean) WebUtils.getSessionAttribute(request, "UserBean");
            if(userBean == null){
                //whatever you want to do
                return throw new ModelAndViewDefiningException(new ModelAndView("userLogout", "command", null));
            }else{
                return true;
            }
        }
    }

and specify this interceptor in your handler mapping definitions as:

    <bean id="yourInterceptor" class="package.YourInterceptor"/>
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="order" value="1" />
            <property name="interceptors">
                <list>
                    <ref bean="yourInterceptor" />
                </list>
            </property>
            <property name="mappings">
                <props>
                    <prop key="/searchOpportunity.htm">YourController</prop>    
                </props>
            </property>
        </bean>