001/* 002 * Copyright (c) 2013 - 2016 TDP Ltd All Rights Reserved. 003 * TDP Ltd grants permission, free of charge, to any person obtaining copies 004 * of this software and its associated documentation files (the "Software"), 005 * to deal in the Software without restriction, including to use, copy, adapt, 006 * publish, distribute, display, perform, sublicense, and sell copies of the 007 * Software, subject to the following condition: You must include the above 008 * copyright notice and this permission notice in all full or partial copies 009 * of the Software. 010 * 011 * TDP LTD PROVIDES THE SOFTWARE "AS IS," WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, 012 * INCLUDING WITHOUT THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 013 * PARTICULAR PURPOSE, AND NON-INFRINGMENT. TDP LTD, THE AUTHORS OF THE SOFTWARE, 014 * AND THE OWNERS OF COPYRIGHT IN THE SOFTWARE ARE NOT LIABLE FOR ANY CLAIM, DAMAGES, 015 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING 016 * FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 017 * THE SOFTWARE. 018 */ 019package cz.tdp.kshield.integration.web; 020 021import java.io.IOException; 022import java.lang.reflect.Constructor; 023 024import javax.servlet.Filter; 025import javax.servlet.FilterChain; 026import javax.servlet.FilterConfig; 027import javax.servlet.ServletException; 028import javax.servlet.ServletRequest; 029import javax.servlet.ServletResponse; 030import javax.servlet.http.HttpServletRequest; 031 032import org.apache.commons.logging.Log; 033import org.apache.commons.logging.LogFactory; 034import org.springframework.beans.BeanWrapper; 035import org.springframework.beans.PropertyAccessorFactory; 036 037import cz.tdp.kshield.integration.KShieldContext; 038import cz.tdp.kshield.integration.ServletAuthenticationService; 039 040 041/** 042 * <b>This is main class of web intergation package.</b><br/> 043 * <br/> 044 * This filter could be used in pure Servlet 2.5 environment and via Spring Framework. You need to position this filter before any authentication check in your application. 045 * Retrieved UserInfo instance is stored in session attribute {@link ServletAuthenticationService#KSHIELD_PRINCIPAL_TOKEN} after successful validation. 046 * You can use this data for furher validation or other authenticanion steps required in your application.<br/> 047 * <b>Example configuration in web.xml:</b> 048<pre>{@code 049 050<filter> 051 <filter-name>KShieldAuthFilter</filter-name> 052 <filter-class>cz.tdp.kshield.integration.web.KShieldAuthenticationFilter</filter-class> 053 <init-param> 054 <param-name>serviceClass</param-name> 055 <param-value>cz.tdp.kshield.integration.DefaultAuthenticationServiceImpl</param-value> 056 </init-param> 057 <init-param> 058 <param-name>serverUrl</param-name> 059 <param-value>http://127.0.0.1:8485</param-value> 060 </init-param> 061</filter> 062 063<filter-mapping> 064 <filter-name>KShieldAuthFilter</filter-name> 065 <url-pattern>*.jsp</url-pattern> 066</filter-mapping> 067 068}</pre> 069 * 070 * @see #init(FilterConfig) 071 * @see DefaultAuthenticationServiceImpl 072 * @see Filter 073 */ 074public class KShieldAuthenticationFilter implements Filter 075{ 076 @Override 077 public void doFilter(ServletRequest request, ServletResponse response, FilterChain filters) throws IOException, ServletException { 078 if (request instanceof HttpServletRequest) { 079 final HttpServletRequest httpReq = (HttpServletRequest)request; 080 081 if (authenticationService.authenticate(httpReq)) { 082 log.info("Authenticated to KeyShield SSO Server"); 083 } 084 } 085 086 try { 087 filters.doFilter(request, response); 088 } 089 finally { 090 KShieldContext.closeKShieldSession(); 091 } 092 } 093 094 @Override 095 public void init(FilterConfig config) throws ServletException { 096 if (authenticationService == null) { 097 // initialize sso authentication service from filter init parameters 098 final String serverUrl = config.getInitParameter("serverUrl"); 099 100 if (serverUrl != null) { 101 final String serviceClassName = config.getInitParameter("serviceClass"); 102 103 if (serviceClassName != null) { 104 try { 105 @SuppressWarnings("unchecked") 106 final Class<ServletAuthenticationService> serviceClass = (Class<ServletAuthenticationService>)Class.forName(serviceClassName); 107 final Constructor<ServletAuthenticationService> constructor = serviceClass.getConstructor(String.class); 108 109 authenticationService = constructor.newInstance(serverUrl); 110 } 111 catch (Exception e) { 112 log.error("Cannot create authentication service", e); 113 throw new ServletException("Failed create kshield authentication service instance", e); 114 } 115 } 116 else { 117 authenticationService = new DefaultAuthenticationServiceImpl(serverUrl); 118 } 119 120 final BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(authenticationService); 121 122 final String apiKey = config.getInitParameter("apiKey"); 123 if (apiKey != null) { 124 wrapper.setPropertyValue("apiKey", apiKey); 125 } 126 127 final String usernameAttr = config.getInitParameter("usernameAttr"); 128 if (usernameAttr != null) { 129 wrapper.setPropertyValue("usernameAttribute", usernameAttr); 130 } 131 132 authenticationService.init(); 133 } 134 else { 135 throw new ServletException("Missing serverUrl init parameter"); 136 } 137 } 138 } 139 140 @Override 141 public void destroy() { 142 //do nothing 143 } 144 145 private ServletAuthenticationService authenticationService; 146 147 public void setAuthenticationService(ServletAuthenticationService authService) { 148 this.authenticationService = authService; 149 } 150 151 private static final Log log = LogFactory.getLog(KShieldAuthenticationFilter.class); 152}