/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.filter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.geoserver.security.GeoServerSecurityManager; import org.geoserver.security.config.BasicAuthenticationFilterConfig; import org.geoserver.security.config.SecurityNamedServiceConfig; import org.geoserver.security.impl.GeoServerUser; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.crypto.codec.Hex; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; /** * Named Basic Authentication Filter * * @author mcr * */ public class GeoServerBasicAuthenticationFilter extends GeoServerCompositeFilter implements AuthenticationCachingFilter, GeoServerAuthenticationFilter { private BasicAuthenticationEntryPoint aep; private MessageDigest digest; @Override public void initializeFromConfig(SecurityNamedServiceConfig config) throws IOException { super.initializeFromConfig(config); try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("No MD5 algorithm available!"); } aep= new BasicAuthenticationEntryPoint(); aep.setRealmName(GeoServerSecurityManager.REALM); try { aep.afterPropertiesSet(); } catch (Exception e) { throw new IOException(e); } BasicAuthenticationFilterConfig authConfig = (BasicAuthenticationFilterConfig) config; BasicAuthenticationFilter filter = new BasicAuthenticationFilter(getSecurityManager().authenticationManager(),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 req, ServletResponse res, FilterChain chain) throws IOException, ServletException { req.setAttribute(GeoServerSecurityFilter.AUTHENTICATION_ENTRY_POINT_HEADER, aep); super.doFilter(req, res, chain); } /** * returns username:md5(password:filtername) */ @Override public String getCacheKey(HttpServletRequest request) { if (request.getSession(false)!=null) // no caching if there is an HTTP session return null; String header = request.getHeader("Authorization"); if ((header != null) && header.startsWith("Basic ")) { byte[] base64Token=null; try { base64Token = header.substring(6).getBytes("UTF-8"); } catch (UnsupportedEncodingException e1) { throw new RuntimeException(e1); } String token = new String(Base64.decode(base64Token)); String username = ""; String password = ""; int delim = token.indexOf(":"); if (delim != -1) { username = token.substring(0, delim); password = token.substring(delim + 1); } else { return null; } if (GeoServerUser.ROOT_USERNAME.equals(username)) return null; StringBuffer buff = new StringBuffer(password); buff.append(":"); buff.append(getName()); String digestString = null; try { MessageDigest md = (MessageDigest) digest.clone(); digestString = new String(Hex.encode(md.digest(buff.toString().getBytes("utf-8")))); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } buff = new StringBuffer(username); buff.append(":"); buff.append(digestString); return buff.toString(); } 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; } }