Results 1 to 8 of 8

Thread: spring security stay on single url at login

  1. #1
    Join Date
    Nov 2010
    Posts
    11

    Default 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. #2
    Join Date
    Dec 2010
    Posts
    315

    Default

    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 at 08:28 AM.

  3. #3
    Join Date
    Dec 2010
    Posts
    315

    Wink

    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.

  4. #4
    Join Date
    Nov 2010
    Posts
    11

    Default

    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.

  5. #5
    Join Date
    Dec 2010
    Posts
    315

    Default

    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.

  6. #6
    Join Date
    Nov 2010
    Posts
    11

    Default

    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.

  7. #7
    Join Date
    Dec 2010
    Posts
    315

    Default

    Quote 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!

  8. #8
    Join Date
    Nov 2010
    Posts
    11

    Default

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

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •