/* * Copyright (C) 2007 - 2013 GeoSolutions S.A.S. * http://www.geo-solutions.it * * GPLv3 + Classpath exception * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.geoserver.geoserver.authentication.filter; import java.io.IOException; import java.util.ArrayList; import java.util.List; 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.HttpServletRequest; import org.apache.commons.codec.binary.Base64; import org.geoserver.geofence.services.RuleReaderService; import org.geoserver.geofence.services.dto.AuthUser; import org.geoserver.geoserver.authentication.auth.GeoFenceAuthenticationProvider; import org.geoserver.geoserver.authentication.auth.GeoFenceSecurityProvider; import org.geoserver.security.GeoServerSecurityManager; import org.geoserver.security.config.SecurityNamedServiceConfig; import org.geoserver.security.filter.GeoServerAuthenticationFilter; import org.geoserver.security.filter.GeoServerCompositeFilter; import org.geoserver.security.filter.GeoServerSecurityFilter; import org.geoserver.security.impl.GeoServerRole; import org.geotools.util.logging.Logging; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; /** * * @author ETj (etj at geo-solutions.it) */ public class GeoFenceAuthFilter // extends GeoServerSecurityFilter extends GeoServerCompositeFilter implements GeoServerAuthenticationFilter { static final Logger LOGGER = Logging.getLogger(GeoFenceAuthFilter.class); private RuleReaderService ruleReaderService; private GeoFenceSecurityProvider geofenceAuth; // static final String ROOT_ROLE = "ROLE_ADMINISTRATOR"; // static final String ANONYMOUS_ROLE = "ROLE_ANONYMOUS"; static final String USER_ROLE = "ROLE_USER"; private BasicAuthenticationEntryPoint aep; @Override public void initializeFromConfig(SecurityNamedServiceConfig config) throws IOException { super.initializeFromConfig(config); GeoFenceAuthFilterConfig cfg = (GeoFenceAuthFilterConfig) config; // anything to set here? maybe the cache config aep= new BasicAuthenticationEntryPoint(); aep.setRealmName(GeoServerSecurityManager.REALM); try { aep.afterPropertiesSet(); } catch (Exception e) { throw new IOException(e); } // BasicAuthenticationFilterConfig authConfig = (BasicAuthenticationFilterConfig) config; SecurityNamedServiceConfig authCfg = securityManager.loadAuthenticationProviderConfig("geofence"); GeoFenceAuthenticationProvider geofenceAuthProvider = geofenceAuth.createAuthenticationProvider(authCfg); BasicAuthenticationFilter filter = new BasicAuthenticationFilter(geofenceAuthProvider ,aep); // if (authConfig.isUseRememberMe()) { // filter.setRememberMeServices(securityManager.getRememberMeService()); // GeoServerWebAuthenticationDetailsSource s = new GeoServerWebAuthenticationDetailsSource(); // filter.setAuthenticationDetailsSource(s); // } filter.afterPropertiesSet(); getNestedFilters().add(filter); } @Override public AuthenticationEntryPoint getAuthenticationEntryPoint() { return aep; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setAttribute(GeoServerSecurityFilter.AUTHENTICATION_ENTRY_POINT_HEADER, aep); super.doFilter(request, response, chain); // Authentication auth = SecurityContextHolder.getContext().getAuthentication(); // if (auth == null) { // doAuth(request, response); // } else { // LOGGER.fine("Found existing Authentication in context: " + auth); // } // // chain.doFilter(request, response); } private void doAuth(ServletRequest request, ServletResponse response) { BasicUser basicUser = getBasicAuth(request); AuthUser authUser = null; if(basicUser != null) { LOGGER.fine("Checking auth for user " + basicUser.name); authUser = ruleReaderService.authorize(basicUser.name, basicUser.pw); if(authUser == null) { LOGGER.info("Could not authenticate user " + basicUser.name); } } else { LOGGER.fine("No basicauth"); } if(authUser != null) { LOGGER.fine("Found user " + authUser); List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(); authorities.add(GeoServerRole.AUTHENTICATED_ROLE); if(authUser.getRole() == AuthUser.Role.ADMIN) { authorities.add(GeoServerRole.ADMIN_ROLE); authorities.add(new SimpleGrantedAuthority("ADMIN")); // needed for REST?!? } else { authorities.add(new SimpleGrantedAuthority(USER_ROLE)); // ?? } UsernamePasswordAuthenticationToken upa = new UsernamePasswordAuthenticationToken(basicUser.name, basicUser.pw, authorities); SecurityContextHolder.getContext().setAuthentication(upa); } else { LOGGER.fine("Anonymous access"); // // Authentication authentication = new AnonymousAuthenticationToken("geoserver", "null", // Arrays.asList(new GrantedAuthority[] { new SimpleGrantedAuthority(ANONYMOUS_ROLE) })); // SecurityContextHolder.getContext().setAuthentication(authentication); } } /** * Simple username+password container */ class BasicUser { String name; String pw; public BasicUser(String name, String pw) { this.name = name; this.pw = pw; } } /** * Reads username and password from Basic auth headers. * @return a BasicUser instance, or null if no basic auth detected. */ private BasicUser getBasicAuth(ServletRequest request) { HttpServletRequest httpRequest = (HttpServletRequest) request; String header = ((httpRequest.getHeader("Authorization") != null) ? httpRequest.getHeader("Authorization") : httpRequest.getHeader("X-CUSTOM-USERID")); if (header != null) { String base64Token = header.startsWith("Basic ") ? header.substring(6) : header; String token = new String(Base64.decodeBase64(base64Token.getBytes())); int delim = token.indexOf(":"); String username = null; String password = null; if (delim != -1) { username = token.substring(0, delim); password = token.substring(delim + 1); } else { username = header; password = null; } return new BasicUser(username, password); } else { return null; } } /** * @see org.geoserver.security.filter.GeoServerAuthenticationFilter#applicableForHtml() */ // @Override public boolean applicableForHtml() { return true; } /** * @see org.geoserver.security.filter.GeoServerAuthenticationFilter#applicableForServices() */ // @Override public boolean applicableForServices() { return true; } public void setRuleReaderService(RuleReaderService ruleReaderService) { this.ruleReaderService = ruleReaderService; } public void setGeofenceAuth(GeoFenceSecurityProvider geofenceAuth) { this.geofenceAuth = geofenceAuth; } }