Announcement Announcement Module
Collapse
No announcement yet.
spring security stay on single url at login Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • spring security stay on single url at login

    hi there, here is my case.

    when first time user land to site, they will pointed to login page. (lest say http://ex.com/) and when they successfully login, they'll see the other page with the same url (http://ex.com/

    but, when they open the site on other tab (http://ex.com) they will pointed back to login page.

    my site will only allow one url, the rest will requested through ajax.

    how to implement this case in my site with spring security ?

    its easy to do when deal with conventional servlet. i just need to have 2 method (doGet for showing login page, and doPost for authenticating user and if its valid it will call another view).

  • #2
    What happens if they refresh the same page? Will they be pointed back to the login page again?

    I suppose refreshing the same page, creating a new tab, and closing/reopening the browser should behave the same?

    its easy to do when deal with conventional servlet. i just need to have 2 method (doGet for showing login page, and doPost for authenticating user and if its valid it will call another view).
    You can also do that idea using Spring Controllers. For example:

    Code:
    @RequestMapping(value = "/admin", method = RequestMethod.GET)
        public String getAdminPage() {
        	logger.debug("Received request to show admin page");
        
        	if (SecurityContextHolder.getContext().getAuthentication() != null) {
        		return "redirect:/krams/auth/login";
        	}
        	// Do your work here. Whatever you like
        	// i.e call a custom service to do your business
        	// Prepare a model to be used by the JSP page
        	
        	// This will resolve to /WEB-INF/jsp/adminpage.jsp
        	return "adminpage";
    	}

    Inside the controller, check if the SecurityContextHolder is not null. If not, force them to the login page. And as you mentioned in stackoverflow, you're willing to wait for the session to expire.

    There's a side-effect however. You won't be able to see the page.
    Last edited by skram; Dec 30th, 2010, 09:28 AM.

    Comment


    • #3
      Another possible solution which I have tested and running is to implement a filter and put it in the FilterProxyChain.

      Here's a sample implementation:

      Code:
      public class BlacklistFilter extends OncePerRequestFilter {
      
      	protected static Logger logger = Logger.getLogger("service");
      	private String redirectURI = "/krams/auth/login";
      	
      	@Resource(name="sessionRegistry")
      	private SessionRegistry sessionRegistry;
      
          private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
          private LogoutHandler[] handlers = new LogoutHandler[] {new SecurityContextLogoutHandler()};
      	
      	@Override
      	protected void doFilterInternal(HttpServletRequest request,
      			HttpServletResponse response, FilterChain filterChain)
      			throws ServletException, IOException {
      		
      		logger.debug("Running blacklist filter");
      		
      		HttpSession session = request.getSession(false);
      		
      		if (session != null) {
      			SessionInformation info = sessionRegistry.getSessionInformation(session.getId());
      			
      			if (info != null) {
      				Boolean bool = (Boolean) session.getAttribute("hasLoggedIn");
      		    	if (bool != null) {
      		    		logger.debug("Second time");
      		    		
      		    		logger.debug(request.getRequestURI());
      		    		
      		    		if (request.getRequestURI().equals("/spring-security-prelogin/krams/main/solo") == true) {
      			    		session.removeAttribute("hasLoggedIn");
      			    		
      			    		logger.debug("Expiring session");
      			    		info.expireNow();	
      			    		
      			    		logger.debug("Logout");
      			    		doLogout(request, response);
      			    		
      			    		logger.debug("Redirecting");
      			    		redirectStrategy.sendRedirect(request, response, redirectURI);
      			    		return;
      			    		
      		    		} else {
      		    			
      		    			logger.debug("Url is okay");
      			    		session.setAttribute("hasLoggedIn", new Boolean(true));
      			    		info.refreshLastRequest();
      		    		}
      		    		
      		    	} else {
      		    		logger.debug("First time");
      		    		session.setAttribute("hasLoggedIn", new Boolean(true));
      		    		info.refreshLastRequest();
      		    	}
      			} else {
      				logger.debug("Info is null");
      			}
      		} else {
      			logger.debug("Session is null");
      		}
      		
              // User details are not empty
              logger.debug("Continue with remaining filters");
              filterChain.doFilter(request, response);
      	}
      
      	private void doLogout(HttpServletRequest request, HttpServletResponse response) {
              Authentication auth = SecurityContextHolder.getContext().getAuthentication();
      
              for (int i = 0; i < handlers.length; i++) {
                  handlers[i].logout(request, response, auth);
              }
      	}
      
      	public String getRedirectURI() {
      		return redirectURI;
      	}
      
      	public void setRedirectURI(String redirectURI) {
      		this.redirectURI = redirectURI;
      	}
      	
      }
      This was originally inside a subclass of ConcurrentSessionFilter. But I decided to move the code as a separate filter so as not to pollute the ConcurrentSessionFilter.

      Then inside the http tag, you include a custom-filter tag:
      Code:
      <security:custom-filter ref="blacklistFilter" after="CONCURRENT_SESSION_FILTER"/>
      With a reference to a bean:
      Code:
      <bean id="blacklistFilter" class="org.krams.tutorial.filter.BlacklistFilter" />
      What's the catch? If you create a new tab and enter the main URL, you will be forced to the login-page. If you refresh the page, same behavior. If you close and open the browser, same behavior.

      It's a catch because it's too restrictive. Of course the code above can still be improved since it's just a quick and dirty implementation

      I'm gonna make a guide for this just to show how it's done. Or maybe someone out there may find this useful.

      Comment


      • #4
        from your sample, it will remove the session from the user?
        so then first tab will just invalid?

        but your answer give me insight how to handle case like this.
        i think it can be handled in controller by set session flag like code below.

        Code:
        @RequestMapping(value="/", method=RequestMethod.GET)
            public String login(HttpSession session){
                Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        
                if(principal instanceof UserDetails) {
                    if( session.getAttribute("firstLogin") == null ){
                        return "login";
                    } else {
                        session.setAttribute("firstLogin", true);
                        return "about";
                    }
                }
                return "login";
            }
        in your opinion which implementation is better? using spring security filter or choose the right view in controller?

        i really appreciate your answer skarm. thanks bro.

        Comment


        • #5
          I think for now it's better to do it in the Controller as it's easier to understand and implement.

          It's still best if you can implement it in the Spring Security. However, it's a huge beast.

          Yeah, with the Spring Security implementation I posted above it's gonna expire the session. If I do not expire it, it goes to a never ending loop. It may need more testing and debugging.

          Comment


          • #6
            can we override spring security behavior like this :
            spring security will call view (jsp, tiles, velocity, etc) from the web configuration if login valid. if this can be done with filter, it will be very good solution i think.

            Comment


            • #7
              Originally posted by jeg_bagus View Post
              can we override spring security behavior like this :
              spring security will call view (jsp, tiles, velocity, etc) from the web configuration if login valid. if this can be done with filter, it will be very good solution i think.
              Check this new guide I just uploaded Spring Security - MVC: Implementing a Single Entry Filter Tutorial at http://krams915.blogspot.com/2010/12...ng-single.html

              And see if it fits your requirements. If not, feel free to customize

              Advance Happy New Year!

              Comment


              • #8
                thank you very much skarm. i will follow your blog !

                Comment

                Working...
                X