org.geonode.security.GeoNodeCookieProcessingFilter.java Source code

Java tutorial

Introduction

Here is the source code for org.geonode.security.GeoNodeCookieProcessingFilter.java

Source

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
 * This code is licensed under the GPL 2.0 license, availible at the root
 * application directory.
 */
package org.geonode.security;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.geoserver.security.GeoServerSecurityFilterChainProxy;
import org.geoserver.security.filter.GeoServerAuthenticationFilter;
import org.geoserver.security.filter.GeoServerSecurityFilter;
import org.geoserver.security.impl.GeoServerUser;
import org.geotools.util.logging.Logging;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * A processing filter that will inspect the cookies and look for the GeoNode single sign on one. If
 * that is found, GeoNode will be interrogated to gather the user privileges.
 * 
 * @author Andrea Aime - OpenGeo
 * @author Gabriel Roldan - OpenGeo
 */
public class GeoNodeCookieProcessingFilter extends GeoServerSecurityFilter
        implements GeoServerAuthenticationFilter {
    static final Logger LOGGER = Logging.getLogger(GeoNodeCookieProcessingFilter.class);
    static final String GEONODE_COOKIE_NAME = "sessionid";

    /**
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
        // nothing to do here
    }

    /**
     * 
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
     *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        final HttpServletRequest httpRequest = (HttpServletRequest) request;

        final SecurityContext securityContext = SecurityContextHolder.getContext();
        final Authentication existingAuth = securityContext.getAuthentication();

        final String gnCookie = getGeoNodeCookieValue(httpRequest);

        final boolean alreadyAuthenticated = existingAuth != null && existingAuth.isAuthenticated();
        final boolean anonymous = existingAuth == null || existingAuth instanceof AnonymousAuthenticationToken;
        // if logging in via geoserver web form, we want to short circuit the cookie
        // check below which might get triggered with an anon geonode cookie
        // the result looks like the login worked but because we replace the
        // auth below, it functionaly fails
        final boolean loggedInWithPassword = existingAuth instanceof UsernamePasswordAuthenticationToken
                && alreadyAuthenticated;
        final boolean hasPreviouslyValidatedGeoNodeCookie = (existingAuth instanceof GeoNodeSessionAuthToken)
                && existingAuth.getCredentials().equals(gnCookie);

        if (hasPreviouslyValidatedGeoNodeCookie)
            existingAuth.setAuthenticated(true);

        // if we still need to authenticate and we find the cookie, consult GeoNode for
        // an authentication
        final boolean authenticationRequired = (!alreadyAuthenticated || anonymous
                || !hasPreviouslyValidatedGeoNodeCookie);

        if (!loggedInWithPassword && authenticationRequired && gnCookie != null) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine(
                        "Found GeoNode cookie - checking if we have the authorizations in cache or if we have to reload from GeoNode");
            }
            try {
                Object principal = existingAuth == null ? null : existingAuth.getPrincipal();
                Collection<? extends GrantedAuthority> authorities = existingAuth == null ? null
                        : existingAuth.getAuthorities();
                Authentication authRequest = new GeoNodeSessionAuthToken(principal, gnCookie, authorities);
                final Authentication authResult = getSecurityManager().authenticate(authRequest);
                LOGGER.log(Level.FINE, "authResult : {0}", authResult);
                securityContext.setAuthentication(authResult);
            } catch (AuthenticationException e) {
                // we just go ahead and fall back on basic authentication
                LOGGER.log(Level.WARNING, "Error connecting to the GeoNode server for authentication purposes", e);
            }
        }

        // move forward along the chain
        chain.doFilter(request, response);
    }

    private String getGeoNodeCookieValue(HttpServletRequest request) {
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Inspecting the http request looking for the GeoNode Session ID.");
        }
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine("Found " + cookies.length + " cookies!");
            }
            for (Cookie c : cookies) {
                if (GEONODE_COOKIE_NAME.equals(c.getName())) {
                    if (LOGGER.isLoggable(Level.FINE)) {
                        LOGGER.fine("Found GeoNode cookie: " + c.getValue());
                    }
                    return c.getValue();
                }
            }
        } else {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine("Found no cookies!");
            }
        }

        return null;
    }

    public boolean applicableForHtml() {
        return true;
    }

    public boolean applicableForServices() {
        return true;
    }
}