Announcement Announcement Module
Collapse
No announcement yet.
Context-relative redirect from within Interceptor? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Context-relative redirect from within Interceptor?

    Hi everyone,

    I have the following requirement: if a user access the page three times within the same session, send them back to the home page, and disable further access for this session.

    I have implemented this login in an interceptor:

    Code:
    public class ThreeStrikesAndYrOutInterceptor extends HandlerInterceptorAdapter {
    	private static final Log logger = LogFactory.getLog(ThreeStrikesAndYrOutInterceptor.class);
    	private static final String N_STRIKES = "N_STRIKES";
    	
    	private String redirect;
    
    	private int incrementStrikes(HttpServletRequest request) {
    		Integer strikesAsInteger = (Integer) WebUtils.getSessionAttribute(request, N_STRIKES);
    		if (strikesAsInteger == null) {
    			strikesAsInteger = new Integer(0);	
    		} else {
    			strikesAsInteger = new Integer(strikesAsInteger.intValue() + 1);
    		}
    		WebUtils.setSessionAttribute(request, N_STRIKES, strikesAsInteger);
    		return strikesAsInteger.intValue();
    	}
    	
    	@Override
    	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    		int strikes = incrementStrikes(request);
    		logger.debug("strike count? " + strikes);
    		if (strikes < 3) {
    			return true;
    		}
    		logger.warn("Detected three accesses in one session - disallowing further requests!");
    		response.sendRedirect(redirect);
    		return false;
    	}
    
    	public void setRedirect(String redirect) {
    		this.redirect = redirect;
    	}
    }
    If i set redirect like this:

    Code:
    <bean name="threeStrikesAndYrOutInterceptor" class="com.equifax.imover.interceptor.ThreeStrikesAndYrOutInterceptor">
        <property name="redirect" value="/overview.do" />
    </bean>
    it redirects me to http://myserver/overview.do which does NOT exist!

    How can I tell it to redirect context-sensitive without hardcoding the path??

    Thank you!

  • #2
    Just as a guess - what do you get if you don't specify a path:
    Code:
    <bean name="threeStrikesAndYrOutInterceptor" class="com.equifax.imover.interceptor.ThreeStrikesAndYrOutInterceptor">
        <property name="redirect" value="overview.do" />
    </bean>
    I would expect it to be relative to the local pages. ie in your servlet.

    Comment


    • #3
      Here's what I did, which I was not happy with:
      Code:
          @Override
          public boolean preHandle(final HttpServletRequest request,
                  final HttpServletResponse response,
                  final Object handler) {
      
              if (log.isDebugEnabled())
                  requestDebug(request);
      
              if (log.isDebugEnabled())
                  servletDebug();
      
              if (request.getServletPath().compareTo("/start.zug") == 0)
                  return (true);
      
              if (userPermissions.isAdmin())
                  return (true);
      
              if (systemStatus.isSystemDown()) {
                  try {
                      response.sendRedirect(serviceUrl(request, systemStatus
                              .getSystemDownView()));
                  }
                  catch (final IOException e) {
                      log.error("exception: {}", e);
                  }
      
                  return (false);
              }
      
              return (true);
          }
      
          private String serviceUrl(final HttpServletRequest request,
                  final String page) {
              final StringBuilder sb = new StringBuilder();
      
              sb.append(request.getScheme());
              sb.append("://");
              sb.append(request.getServerName());
      
              final int port = request.getServerPort();
      
              if (port != 80) {
                  sb.append(":");
                  sb.append(port);
              }
      
              sb.append("/");
              sb.append(request.getContextPath());
      
              sb.append("/");
              sb.append(page);
      
              return (sb.toString());
          }
      
          private void requestDebug(final HttpServletRequest request) {
              log.debug("contextPath: {}", request.getContextPath());
              log.debug("pathInfo: {}", request.getPathInfo());
              log.debug("pathTranslated: {}", request.getPathTranslated());
              log.debug("requestUrl: {}", request.getRequestURL());
              log.debug("requestUri: {}", request.getRequestURI());
              log.debug("servletPath: {}", request.getServletPath());
              log.debug("serverName: {}", request.getServerName());
              log.debug("serverPort: {}", request.getServerPort());
              log.debug("protocol: {}", request.getProtocol());
              log.debug("scheme: {}", request.getScheme());
          }
      The method serviceUrl constructs the url to redirect to. The method systemDownView is incorrectly named; it should be systemDownFile since it's returning a file name, systemDown.jsp, not a view name. When deployed the file systemDown.jsp is in the root of the webapps/<myApp>/ directory along with the index.jsp start file.

      And apparently there are security issues with using the host name that's in the HttpServletRequest object; I think it's supplied by the client (browser or nefarious hacker, as the case may be).

      Comment


      • #4
        lumpynose, not sure if I understand 100%, but respone.sendRedirect() will work with relative redirects e.g. /mypage.jsp provided you give it a context path (no need to do the host/port portion)...

        In my case I solved this issue like so... and I believe you could simplify your serviceUrl method as well:

        Code:
        //turns /mypage.jsp into something like /myapp/mypage.jsp
        private String createRedirectUrl(HttpServletRequest request) {
        	if (redirect.startsWith("/")) {
        		return request.getContextPath() + redirect;
        	} else {
        		return redirect;
        	}
        }
        ...
        	
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        	...
        	logger.warn("Detected three accesses in one session - disallowing further requests!");
        	String redirect = createRedirectUrl(request);
        	logger.debug("Redirecting to " + redirect);
        	response.sendRedirect(redirect);
        	return false;
        }

        Comment


        • #5
          Excellent; thanks!

          Comment

          Working...
          X