As per the new requirement i have created custom UsernamePasswordAuthenticationFilter to capture additional parameters from the login page. As expected my config was working fine. I'm able to retrieve additional parameters in filter and saving to session. But after adding my custom filter to config, the session management is not working. Previous i was allowing only one session per user by setting max sessions values to 1. It is not working now, application is allowing same user to login multiple times. I'm sure that it is happening only after integrating custom UsernamePasswordAuthenticationFilter to my config. Below is my spring security config.
http.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login.html")
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.logoutSuccessUrl("/login.html")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout.html"))
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.and()
.sessionManagement()
.maximumSessions(1)
.expiredUrl("/multiplesessions.html")
.sessionRegistry(getSessionRegistry());
http.addFilterBefore(customUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
@Bean
public SessionRegistry getSessionRegistry() {
return new SessionRegistryImpl();
}
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(dsnyUserDetailsService);
provider.setPasswordEncoder(passwordEncoder());
auth.authenticationProvider(provider);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new StandardPasswordEncoder();
}
@Bean(name = "myAuthenticationManager")
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
DsnyUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter() throws Exception {
DsnyUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter = new DsnyUsernamePasswordAuthenticationFilter();
customUsernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManagerBean());
customUsernamePasswordAuthenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login.html", "POST"));
return customUsernamePasswordAuthenticationFilter;
}
Am i missing any thing here?
I resolved this problem by adding custom ConcurrentSessionFilter. Here is the code if any one wants.
http.sessionManagement().sessionAuthenticationStrategy(concurrentSession());
http.addFilterBefore(concurrentSessionFilter(), ConcurrentSessionFilter.class);
@Bean
public CompositeSessionAuthenticationStrategy concurrentSession() {
ConcurrentSessionControlAuthenticationStrategy concurrentAuthenticationStrategy = new ConcurrentSessionControlAuthenticationStrategy(getSessionRegistry());
concurrentAuthenticationStrategy.setMaximumSessions(1);
//concurrentAuthenticationStrategy.setExceptionIfMaximumExceeded(true);
List<SessionAuthenticationStrategy> delegateStrategies = new ArrayList<SessionAuthenticationStrategy>();
delegateStrategies.add(concurrentAuthenticationStrategy);
delegateStrategies.add(new SessionFixationProtectionStrategy());
delegateStrategies.add(new RegisterSessionAuthenticationStrategy(getSessionRegistry()));
CompositeSessionAuthenticationStrategy authenticationStrategy = new CompositeSessionAuthenticationStrategy(delegateStrategies);
return authenticationStrategy;
}
@Bean
ConcurrentSessionFilter concurrentSessionFilter() {
CustomSessionInformationExpiredStrategy redirectStrategy = new CustomSessionInformationExpiredStrategy("/pub/multiplesessions.html");
CustomConcurrentSessionFilter concurrentSessionFilter = new CustomConcurrentSessionFilter(getSessionRegistry(), redirectStrategy);
return concurrentSessionFilter;
}
CustomSessionInformationExpiredStrategy.java
public class CustomSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {
private Logger log = Logger.getLogger(this.getClass().getName());
private String expiredUrl = "";
public CustomSessionInformationExpiredStrategy(String expiredUrl) {
this.expiredUrl = expiredUrl;
}
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent) throws IOException, ServletException {
log.info("Redirecting to session expired page");
HttpServletRequest request = sessionInformationExpiredEvent.getRequest();
HttpServletResponse response = sessionInformationExpiredEvent.getResponse();
request.getSession();// creates a new session
response.sendRedirect(request.getContextPath() + expiredUrl);
}
}
CustomConcurrentSessionFilter.java, no custom code here.
public class CustomConcurrentSessionFilter extends ConcurrentSessionFilter {
public CustomConcurrentSessionFilter(SessionRegistry sessionRegistry) {
super(sessionRegistry);
}
public CustomConcurrentSessionFilter(SessionRegistry sessionRegistry, SessionInformationExpiredStrategy sessionInformationExpiredStrategy) {
super(sessionRegistry, sessionInformationExpiredStrategy);
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
super.doFilter(req, res, chain);
}
}