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.springsecurity3; 020 021 022import java.io.IOException; 023 024import javax.servlet.FilterChain; 025import javax.servlet.ServletException; 026import javax.servlet.ServletRequest; 027import javax.servlet.ServletResponse; 028import javax.servlet.http.HttpServletRequest; 029 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.springframework.beans.factory.annotation.Autowired; 033import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; 034 035import cz.tdp.kshield.client.UserInfo; 036import cz.tdp.kshield.integration.AuthenticationService; 037import cz.tdp.kshield.integration.KShieldContext; 038 039/** 040 * <b>This is central class in springsecurity3 package.</b> You need to define AuthenticationService and AuthenticationFactory beans (usually from package springsecurity3). 041 * You can use your own AuthenticationFactory implementation or extend AuthenticationService if you need do some post or pre processing during authentication process.<br/> 042 * Default implementations depends also on UserDetailsService and AuthenticationDetailsSource.<br/> 043 * <br/> 044 * <b>Example spring configuration:</b> 045<pre>{@code 046 047<bean id="userDetailsService" class="org.springframework.security.core.userdetails.memory.InMemoryDaoImpl"> 048 <property name="userProperties"> 049 <props> 050 <prop key="user1">password</prop> 051 </props> 052 </property> 053</bean> 054 055<bean id="kshieldAuthenticationFactory" class="cz.tdp.kshield.springsecurity3.SpringAuthenticationFactory" autowire="byType" /> 056 057<bean id="kshieldAuthService" class="cz.tdp.kshield.springsecurity3.SpringAuthenticationServiceImpl" autowire="byType"> 058 <constructor-arg value="http://127.0.0.1:8485" /> 059</bean> 060 061<bean id="authenticationDetailsSource" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper" autowire="byType" /> 062 063<bean id="kshieldAuthenticationFilter" class="cz.tdp.kshield.springsecurity3.KShieldPreAuthenticationFilter" autowire="byType"> 064 <property name="authenticationDetailsSource" ref="authenticationDetailsSource" /> 065 <property name="authenticationManager" ref="authenticationManager" /> 066 <property name="authenticationService" ref="kshieldAuthService" /> 067</bean> 068 069}</pre> 070 * 071 * <b>You should add PreAuthenticatedAuthenticationProvider provider to authentication manager configuration and define alias:</b> 072<pre>{@code 073 074<bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider" autowire="byType" /> 075 076<security:authentication-manager alias="authenticatedManager"> 077 <security:authentication-provider ref="preAuthenticatedAuthenticationProvider" /> 078 ... 079</security:authentication-manager> 080 081}</pre> 082 * 083 * <b>Finally you need add custom filter (defined above) to your http element config:</b> 084<pre>{@code 085 086<security:http> 087 ... 088 <security:custom-filter position="PRE_AUTH_FILTER" ref="kshieldAuthenticationFilter" /> 089</security:http> 090 091}</pre> 092 * @see AbstractPreAuthenticatedProcessingFilter 093 */ 094public class KShieldPreAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter 095{ 096 /** 097 * Suffix used in fake use password 098 */ 099 public static final String KSHIELD_PASSWD_SUFFIX = "\034\035\036\037kshield"; 100 101 public KShieldPreAuthenticationFilter() { 102 super(); 103 104 this.setCheckForPrincipalChanges(false); 105 } 106 107 @Override 108 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 109 try { 110 super.doFilter(request, response, chain); 111 } 112 finally { 113 KShieldContext.closeKShieldSession(); 114 } 115 } 116 117 @Override 118 protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { 119 return request.getRemoteAddr()+KSHIELD_PASSWD_SUFFIX; 120 } 121 122 @Override 123 protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { 124 final UserInfo info = authenticationService.createUserInfo(request.getRemoteAddr()); 125 126 if (info != null) { 127 return getPrincipal(info); 128 } 129 130 return null; 131 } 132 133 /** 134 * @param userInfo UserInfo class returned by KeyShield SSO Server client 135 * @return username retrieved from UserInfo 136 */ 137 protected String getPrincipal(UserInfo userInfo) { 138 return userInfo.getUsername(); 139 } 140 141 @Autowired 142 private AuthenticationService authenticationService; 143 144 public void setAuthenticationService(AuthenticationService authService) { 145 this.authenticationService = authService; 146 } 147 148 protected final Log log = LogFactory.getLog(getClass()); 149}