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}