Selection based AuthProvider Spring Security
I have configured Spring security to work with both LDAP and DB based login. First it tries to login via LDAP and if required permissions is not there then it takes to username/password entry page.
<security:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:custom-filter ref="customPreAuthFilter" position="PRE_AUTH_FILTER"/> // This is for LDAP
<security:custom-filter ref="customAuthFilter" position="FORM_LOGIN_FILTER"/> // This is for DB Based
/** intercept urls
**/
</security:http>
I want to add a new screen on the top and user need to select between the two button LDAP or username/pass. How do I proceed?
The data to be accessed is the same url i.e. /home but both ldap and DB users should be able to access.
java spring spring-security
|
show 2 more comments
I have configured Spring security to work with both LDAP and DB based login. First it tries to login via LDAP and if required permissions is not there then it takes to username/password entry page.
<security:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:custom-filter ref="customPreAuthFilter" position="PRE_AUTH_FILTER"/> // This is for LDAP
<security:custom-filter ref="customAuthFilter" position="FORM_LOGIN_FILTER"/> // This is for DB Based
/** intercept urls
**/
</security:http>
I want to add a new screen on the top and user need to select between the two button LDAP or username/pass. How do I proceed?
The data to be accessed is the same url i.e. /home but both ldap and DB users should be able to access.
java spring spring-security
How is yourFilter
implementation looks like? I am wondering if you are checking what kind of authentication to be executed infilter
and what do you do if authentication fails? are you seeing any error?
– secret super star
Nov 19 '18 at 9:50
As seen in the xml, there are 2 filters. First one is to extract the header value for LDAP check. Second one am using filter for passing a 3rd value i.e. captcha. after that in both cases the getAuthenticationManager().authenticate(authentication); is called. Filter doesn't perform extra actions rather than passing control to auth manager
– Akhil K Nambiar
Nov 19 '18 at 11:05
<intercept-url pattern="/home*" access="permitAll" /> this will allow users to enter that page with out authentication.
– shadow
Nov 22 '18 at 5:47
You want to change "spring security config" based on user selection!? I think you won't be able to "change the config dynamically", but what seems an approach: 1. "permitAll" for the "new screen" 2. set a (session) flag (designated by you) 3. check that flag and adjust your filters accordingly ..and another approach 'd be: multiple security configurations
– xerx593
Nov 22 '18 at 8:31
Edited the answer to select auth provider based on input and redirect to different login page based on condition, if this was your original question
– secret super star
Nov 23 '18 at 11:54
|
show 2 more comments
I have configured Spring security to work with both LDAP and DB based login. First it tries to login via LDAP and if required permissions is not there then it takes to username/password entry page.
<security:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:custom-filter ref="customPreAuthFilter" position="PRE_AUTH_FILTER"/> // This is for LDAP
<security:custom-filter ref="customAuthFilter" position="FORM_LOGIN_FILTER"/> // This is for DB Based
/** intercept urls
**/
</security:http>
I want to add a new screen on the top and user need to select between the two button LDAP or username/pass. How do I proceed?
The data to be accessed is the same url i.e. /home but both ldap and DB users should be able to access.
java spring spring-security
I have configured Spring security to work with both LDAP and DB based login. First it tries to login via LDAP and if required permissions is not there then it takes to username/password entry page.
<security:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<security:custom-filter ref="customPreAuthFilter" position="PRE_AUTH_FILTER"/> // This is for LDAP
<security:custom-filter ref="customAuthFilter" position="FORM_LOGIN_FILTER"/> // This is for DB Based
/** intercept urls
**/
</security:http>
I want to add a new screen on the top and user need to select between the two button LDAP or username/pass. How do I proceed?
The data to be accessed is the same url i.e. /home but both ldap and DB users should be able to access.
java spring spring-security
java spring spring-security
edited Nov 19 '18 at 6:52
Akhil K Nambiar
asked Nov 13 '18 at 7:10
Akhil K NambiarAkhil K Nambiar
1,741113774
1,741113774
How is yourFilter
implementation looks like? I am wondering if you are checking what kind of authentication to be executed infilter
and what do you do if authentication fails? are you seeing any error?
– secret super star
Nov 19 '18 at 9:50
As seen in the xml, there are 2 filters. First one is to extract the header value for LDAP check. Second one am using filter for passing a 3rd value i.e. captcha. after that in both cases the getAuthenticationManager().authenticate(authentication); is called. Filter doesn't perform extra actions rather than passing control to auth manager
– Akhil K Nambiar
Nov 19 '18 at 11:05
<intercept-url pattern="/home*" access="permitAll" /> this will allow users to enter that page with out authentication.
– shadow
Nov 22 '18 at 5:47
You want to change "spring security config" based on user selection!? I think you won't be able to "change the config dynamically", but what seems an approach: 1. "permitAll" for the "new screen" 2. set a (session) flag (designated by you) 3. check that flag and adjust your filters accordingly ..and another approach 'd be: multiple security configurations
– xerx593
Nov 22 '18 at 8:31
Edited the answer to select auth provider based on input and redirect to different login page based on condition, if this was your original question
– secret super star
Nov 23 '18 at 11:54
|
show 2 more comments
How is yourFilter
implementation looks like? I am wondering if you are checking what kind of authentication to be executed infilter
and what do you do if authentication fails? are you seeing any error?
– secret super star
Nov 19 '18 at 9:50
As seen in the xml, there are 2 filters. First one is to extract the header value for LDAP check. Second one am using filter for passing a 3rd value i.e. captcha. after that in both cases the getAuthenticationManager().authenticate(authentication); is called. Filter doesn't perform extra actions rather than passing control to auth manager
– Akhil K Nambiar
Nov 19 '18 at 11:05
<intercept-url pattern="/home*" access="permitAll" /> this will allow users to enter that page with out authentication.
– shadow
Nov 22 '18 at 5:47
You want to change "spring security config" based on user selection!? I think you won't be able to "change the config dynamically", but what seems an approach: 1. "permitAll" for the "new screen" 2. set a (session) flag (designated by you) 3. check that flag and adjust your filters accordingly ..and another approach 'd be: multiple security configurations
– xerx593
Nov 22 '18 at 8:31
Edited the answer to select auth provider based on input and redirect to different login page based on condition, if this was your original question
– secret super star
Nov 23 '18 at 11:54
How is your
Filter
implementation looks like? I am wondering if you are checking what kind of authentication to be executed in filter
and what do you do if authentication fails? are you seeing any error?– secret super star
Nov 19 '18 at 9:50
How is your
Filter
implementation looks like? I am wondering if you are checking what kind of authentication to be executed in filter
and what do you do if authentication fails? are you seeing any error?– secret super star
Nov 19 '18 at 9:50
As seen in the xml, there are 2 filters. First one is to extract the header value for LDAP check. Second one am using filter for passing a 3rd value i.e. captcha. after that in both cases the getAuthenticationManager().authenticate(authentication); is called. Filter doesn't perform extra actions rather than passing control to auth manager
– Akhil K Nambiar
Nov 19 '18 at 11:05
As seen in the xml, there are 2 filters. First one is to extract the header value for LDAP check. Second one am using filter for passing a 3rd value i.e. captcha. after that in both cases the getAuthenticationManager().authenticate(authentication); is called. Filter doesn't perform extra actions rather than passing control to auth manager
– Akhil K Nambiar
Nov 19 '18 at 11:05
<intercept-url pattern="/home*" access="permitAll" /> this will allow users to enter that page with out authentication.
– shadow
Nov 22 '18 at 5:47
<intercept-url pattern="/home*" access="permitAll" /> this will allow users to enter that page with out authentication.
– shadow
Nov 22 '18 at 5:47
You want to change "spring security config" based on user selection!? I think you won't be able to "change the config dynamically", but what seems an approach: 1. "permitAll" for the "new screen" 2. set a (session) flag (designated by you) 3. check that flag and adjust your filters accordingly ..and another approach 'd be: multiple security configurations
– xerx593
Nov 22 '18 at 8:31
You want to change "spring security config" based on user selection!? I think you won't be able to "change the config dynamically", but what seems an approach: 1. "permitAll" for the "new screen" 2. set a (session) flag (designated by you) 3. check that flag and adjust your filters accordingly ..and another approach 'd be: multiple security configurations
– xerx593
Nov 22 '18 at 8:31
Edited the answer to select auth provider based on input and redirect to different login page based on condition, if this was your original question
– secret super star
Nov 23 '18 at 11:54
Edited the answer to select auth provider based on input and redirect to different login page based on condition, if this was your original question
– secret super star
Nov 23 '18 at 11:54
|
show 2 more comments
1 Answer
1
active
oldest
votes
If you look at code in UsernamePasswordAuthenticationFilter
there is setDetails
method.
from docs:
Provided so that subclasses may configure what is put into the
authentication request's details property.
Idea from here
Provision to change ldap/Ad provider url at run time
You can set the details like authtype here and use it authentication provider, But to achieve the things you would lik adds little more work.
Adding details and hope it helps.
CustomUsernamePasswordAuthenticationFilter.java
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
@Component
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
private static final Logger logger = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
@Autowired
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager)
// TODO Auto-generated method stub
super.setAuthenticationManager(authenticationManager);
@Autowired
@Override
public void setAuthenticationDetailsSource(
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource)
super.setAuthenticationDetailsSource(authenticationDetailsSource);
@Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest)
String authType = request.getParameter("authType");
logger.info("authType ",authType);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
But this is not sufficient you would need to extend WebAuthenticationDetails
.
Reason is WebAuthenticationDetails
provides only remote IP address
and sessionId
so, to add authType we need to extend this class.
You have to extend WebAuthenticationDetailsSource
to return CustomAuthenticationDetails
as shown below.
CustomAuthenticationDetails.java
public class CustomAuthenticationDetails extends WebAuthenticationDetails
private final String authType;
public CustomAuthenticationDetails(HttpServletRequest request)
super(request);
authType = request.getParameter("authType");
public String getAuthType()
return authType;
CustomWebAuthenticationDetailsSource.java
public class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context)
return new CustomAuthenticationDetails(context);
Please note these classes for demo purpose only.
Need to autowire
actual authentication providers in these classes.
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.stereotype.Component;
@Component
public class AuthenicationProviderJdbcLdapImpl implements AuthenticationProvider
// you need to autowire jdbc auth provider
@Autowired(required = false)
DaoAuthenticationProvider authenticationProvider;
//you need to autowire ldap auth provider
@Autowired(required = false)
LdapAuthenticationProvider ldapAuthenticationProvider;
protected static class User
private final String userId;
private final String password;
public User(String userId,String password)
this.userId = userId;
this.password = password;
public String getUserId()
return userId;
public String getPassword()
return password;
@Override
public String toString()
return "User [userId=" + userId + ", password=" + password + "]";
private final static Logger logger = LoggerFactory.getLogger(AuthenicationProviderJdbcLdapImpl.class);
private static final List<User> users1 = Arrays.asList(new User("admin1", "password"),new User("admin2", "password"));
private static final List<User> users2 = Arrays.asList(new User("admin3", "password"),new User("admin4", "password"));
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
CustomAuthenticationDetails details = (CustomAuthenticationDetails) authentication.getDetails();
String authType = details.getAuthType();
logger.info("authType ",authType);
if("jdbc".equalsIgnoreCase(authType))
logger.info("perfrom jdbc authentication");
//perform your authentication using jdbc
//the below is just for explaination
return performAuthentication(authentication, users1);
else if("ldap".equalsIgnoreCase(authType))
logger.info("perfrom ldap authentication");
//perform your authentication using ldap
//the below is just for explaination
return performAuthentication(authentication, users2);
return null;
private Authentication performAuthentication(Authentication authentication,List<User> users)
String credential = (String) authentication.getCredentials();
String userId = authentication.getName();
for(User user: users)
if(user.getUserId().equals(userId)&& user.getPassword().equals(credential))
authentication = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),authentication.getAuthorities());
return authentication;
return null;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(UsernamePasswordAuthenticationToken.class);
If you would need to redirect different login page (not sure, if you have the requirement) you register AuthenticationFailureHandler
shown in security config. Here it is redirected to login and login1 based on condition.
http.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
WebSecurityConfig.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
@Bean
public AuthenticationManager getAuthenticationManager() throws Exception
return super.authenticationManagerBean();
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired()
AuthenicationProviderJdbcImpl authenicationProviderJdbcImpl;
@Autowired()
AuthenicationProviderLdapImpl authenicationProviderLdapImpl;
@Autowired
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception
http.addFilterAt(customUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration","/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()//.successHandler(authenticationSuccessHandler)
.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
.and()
.logout()
.permitAll();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authenicationProviderLdapImpl).authenticationProvider(authenicationProviderJdbcImpl);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
/*auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());*/
The below is from logs when authType = jdbc
or authType=ldap
login called
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] stomUsernamePasswordAuthenticationFilter : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom jdbc authentication
login called
login1 called
login1 called
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] stomUsernamePasswordAuthenticationFilter : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom ldap authentication returning true in ldap
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53275645%2fselection-based-authprovider-spring-security%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you look at code in UsernamePasswordAuthenticationFilter
there is setDetails
method.
from docs:
Provided so that subclasses may configure what is put into the
authentication request's details property.
Idea from here
Provision to change ldap/Ad provider url at run time
You can set the details like authtype here and use it authentication provider, But to achieve the things you would lik adds little more work.
Adding details and hope it helps.
CustomUsernamePasswordAuthenticationFilter.java
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
@Component
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
private static final Logger logger = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
@Autowired
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager)
// TODO Auto-generated method stub
super.setAuthenticationManager(authenticationManager);
@Autowired
@Override
public void setAuthenticationDetailsSource(
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource)
super.setAuthenticationDetailsSource(authenticationDetailsSource);
@Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest)
String authType = request.getParameter("authType");
logger.info("authType ",authType);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
But this is not sufficient you would need to extend WebAuthenticationDetails
.
Reason is WebAuthenticationDetails
provides only remote IP address
and sessionId
so, to add authType we need to extend this class.
You have to extend WebAuthenticationDetailsSource
to return CustomAuthenticationDetails
as shown below.
CustomAuthenticationDetails.java
public class CustomAuthenticationDetails extends WebAuthenticationDetails
private final String authType;
public CustomAuthenticationDetails(HttpServletRequest request)
super(request);
authType = request.getParameter("authType");
public String getAuthType()
return authType;
CustomWebAuthenticationDetailsSource.java
public class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context)
return new CustomAuthenticationDetails(context);
Please note these classes for demo purpose only.
Need to autowire
actual authentication providers in these classes.
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.stereotype.Component;
@Component
public class AuthenicationProviderJdbcLdapImpl implements AuthenticationProvider
// you need to autowire jdbc auth provider
@Autowired(required = false)
DaoAuthenticationProvider authenticationProvider;
//you need to autowire ldap auth provider
@Autowired(required = false)
LdapAuthenticationProvider ldapAuthenticationProvider;
protected static class User
private final String userId;
private final String password;
public User(String userId,String password)
this.userId = userId;
this.password = password;
public String getUserId()
return userId;
public String getPassword()
return password;
@Override
public String toString()
return "User [userId=" + userId + ", password=" + password + "]";
private final static Logger logger = LoggerFactory.getLogger(AuthenicationProviderJdbcLdapImpl.class);
private static final List<User> users1 = Arrays.asList(new User("admin1", "password"),new User("admin2", "password"));
private static final List<User> users2 = Arrays.asList(new User("admin3", "password"),new User("admin4", "password"));
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
CustomAuthenticationDetails details = (CustomAuthenticationDetails) authentication.getDetails();
String authType = details.getAuthType();
logger.info("authType ",authType);
if("jdbc".equalsIgnoreCase(authType))
logger.info("perfrom jdbc authentication");
//perform your authentication using jdbc
//the below is just for explaination
return performAuthentication(authentication, users1);
else if("ldap".equalsIgnoreCase(authType))
logger.info("perfrom ldap authentication");
//perform your authentication using ldap
//the below is just for explaination
return performAuthentication(authentication, users2);
return null;
private Authentication performAuthentication(Authentication authentication,List<User> users)
String credential = (String) authentication.getCredentials();
String userId = authentication.getName();
for(User user: users)
if(user.getUserId().equals(userId)&& user.getPassword().equals(credential))
authentication = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),authentication.getAuthorities());
return authentication;
return null;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(UsernamePasswordAuthenticationToken.class);
If you would need to redirect different login page (not sure, if you have the requirement) you register AuthenticationFailureHandler
shown in security config. Here it is redirected to login and login1 based on condition.
http.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
WebSecurityConfig.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
@Bean
public AuthenticationManager getAuthenticationManager() throws Exception
return super.authenticationManagerBean();
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired()
AuthenicationProviderJdbcImpl authenicationProviderJdbcImpl;
@Autowired()
AuthenicationProviderLdapImpl authenicationProviderLdapImpl;
@Autowired
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception
http.addFilterAt(customUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration","/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()//.successHandler(authenticationSuccessHandler)
.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
.and()
.logout()
.permitAll();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authenicationProviderLdapImpl).authenticationProvider(authenicationProviderJdbcImpl);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
/*auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());*/
The below is from logs when authType = jdbc
or authType=ldap
login called
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] stomUsernamePasswordAuthenticationFilter : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom jdbc authentication
login called
login1 called
login1 called
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] stomUsernamePasswordAuthenticationFilter : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom ldap authentication returning true in ldap
add a comment |
If you look at code in UsernamePasswordAuthenticationFilter
there is setDetails
method.
from docs:
Provided so that subclasses may configure what is put into the
authentication request's details property.
Idea from here
Provision to change ldap/Ad provider url at run time
You can set the details like authtype here and use it authentication provider, But to achieve the things you would lik adds little more work.
Adding details and hope it helps.
CustomUsernamePasswordAuthenticationFilter.java
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
@Component
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
private static final Logger logger = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
@Autowired
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager)
// TODO Auto-generated method stub
super.setAuthenticationManager(authenticationManager);
@Autowired
@Override
public void setAuthenticationDetailsSource(
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource)
super.setAuthenticationDetailsSource(authenticationDetailsSource);
@Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest)
String authType = request.getParameter("authType");
logger.info("authType ",authType);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
But this is not sufficient you would need to extend WebAuthenticationDetails
.
Reason is WebAuthenticationDetails
provides only remote IP address
and sessionId
so, to add authType we need to extend this class.
You have to extend WebAuthenticationDetailsSource
to return CustomAuthenticationDetails
as shown below.
CustomAuthenticationDetails.java
public class CustomAuthenticationDetails extends WebAuthenticationDetails
private final String authType;
public CustomAuthenticationDetails(HttpServletRequest request)
super(request);
authType = request.getParameter("authType");
public String getAuthType()
return authType;
CustomWebAuthenticationDetailsSource.java
public class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context)
return new CustomAuthenticationDetails(context);
Please note these classes for demo purpose only.
Need to autowire
actual authentication providers in these classes.
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.stereotype.Component;
@Component
public class AuthenicationProviderJdbcLdapImpl implements AuthenticationProvider
// you need to autowire jdbc auth provider
@Autowired(required = false)
DaoAuthenticationProvider authenticationProvider;
//you need to autowire ldap auth provider
@Autowired(required = false)
LdapAuthenticationProvider ldapAuthenticationProvider;
protected static class User
private final String userId;
private final String password;
public User(String userId,String password)
this.userId = userId;
this.password = password;
public String getUserId()
return userId;
public String getPassword()
return password;
@Override
public String toString()
return "User [userId=" + userId + ", password=" + password + "]";
private final static Logger logger = LoggerFactory.getLogger(AuthenicationProviderJdbcLdapImpl.class);
private static final List<User> users1 = Arrays.asList(new User("admin1", "password"),new User("admin2", "password"));
private static final List<User> users2 = Arrays.asList(new User("admin3", "password"),new User("admin4", "password"));
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
CustomAuthenticationDetails details = (CustomAuthenticationDetails) authentication.getDetails();
String authType = details.getAuthType();
logger.info("authType ",authType);
if("jdbc".equalsIgnoreCase(authType))
logger.info("perfrom jdbc authentication");
//perform your authentication using jdbc
//the below is just for explaination
return performAuthentication(authentication, users1);
else if("ldap".equalsIgnoreCase(authType))
logger.info("perfrom ldap authentication");
//perform your authentication using ldap
//the below is just for explaination
return performAuthentication(authentication, users2);
return null;
private Authentication performAuthentication(Authentication authentication,List<User> users)
String credential = (String) authentication.getCredentials();
String userId = authentication.getName();
for(User user: users)
if(user.getUserId().equals(userId)&& user.getPassword().equals(credential))
authentication = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),authentication.getAuthorities());
return authentication;
return null;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(UsernamePasswordAuthenticationToken.class);
If you would need to redirect different login page (not sure, if you have the requirement) you register AuthenticationFailureHandler
shown in security config. Here it is redirected to login and login1 based on condition.
http.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
WebSecurityConfig.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
@Bean
public AuthenticationManager getAuthenticationManager() throws Exception
return super.authenticationManagerBean();
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired()
AuthenicationProviderJdbcImpl authenicationProviderJdbcImpl;
@Autowired()
AuthenicationProviderLdapImpl authenicationProviderLdapImpl;
@Autowired
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception
http.addFilterAt(customUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration","/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()//.successHandler(authenticationSuccessHandler)
.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
.and()
.logout()
.permitAll();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authenicationProviderLdapImpl).authenticationProvider(authenicationProviderJdbcImpl);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
/*auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());*/
The below is from logs when authType = jdbc
or authType=ldap
login called
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] stomUsernamePasswordAuthenticationFilter : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom jdbc authentication
login called
login1 called
login1 called
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] stomUsernamePasswordAuthenticationFilter : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom ldap authentication returning true in ldap
add a comment |
If you look at code in UsernamePasswordAuthenticationFilter
there is setDetails
method.
from docs:
Provided so that subclasses may configure what is put into the
authentication request's details property.
Idea from here
Provision to change ldap/Ad provider url at run time
You can set the details like authtype here and use it authentication provider, But to achieve the things you would lik adds little more work.
Adding details and hope it helps.
CustomUsernamePasswordAuthenticationFilter.java
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
@Component
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
private static final Logger logger = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
@Autowired
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager)
// TODO Auto-generated method stub
super.setAuthenticationManager(authenticationManager);
@Autowired
@Override
public void setAuthenticationDetailsSource(
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource)
super.setAuthenticationDetailsSource(authenticationDetailsSource);
@Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest)
String authType = request.getParameter("authType");
logger.info("authType ",authType);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
But this is not sufficient you would need to extend WebAuthenticationDetails
.
Reason is WebAuthenticationDetails
provides only remote IP address
and sessionId
so, to add authType we need to extend this class.
You have to extend WebAuthenticationDetailsSource
to return CustomAuthenticationDetails
as shown below.
CustomAuthenticationDetails.java
public class CustomAuthenticationDetails extends WebAuthenticationDetails
private final String authType;
public CustomAuthenticationDetails(HttpServletRequest request)
super(request);
authType = request.getParameter("authType");
public String getAuthType()
return authType;
CustomWebAuthenticationDetailsSource.java
public class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context)
return new CustomAuthenticationDetails(context);
Please note these classes for demo purpose only.
Need to autowire
actual authentication providers in these classes.
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.stereotype.Component;
@Component
public class AuthenicationProviderJdbcLdapImpl implements AuthenticationProvider
// you need to autowire jdbc auth provider
@Autowired(required = false)
DaoAuthenticationProvider authenticationProvider;
//you need to autowire ldap auth provider
@Autowired(required = false)
LdapAuthenticationProvider ldapAuthenticationProvider;
protected static class User
private final String userId;
private final String password;
public User(String userId,String password)
this.userId = userId;
this.password = password;
public String getUserId()
return userId;
public String getPassword()
return password;
@Override
public String toString()
return "User [userId=" + userId + ", password=" + password + "]";
private final static Logger logger = LoggerFactory.getLogger(AuthenicationProviderJdbcLdapImpl.class);
private static final List<User> users1 = Arrays.asList(new User("admin1", "password"),new User("admin2", "password"));
private static final List<User> users2 = Arrays.asList(new User("admin3", "password"),new User("admin4", "password"));
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
CustomAuthenticationDetails details = (CustomAuthenticationDetails) authentication.getDetails();
String authType = details.getAuthType();
logger.info("authType ",authType);
if("jdbc".equalsIgnoreCase(authType))
logger.info("perfrom jdbc authentication");
//perform your authentication using jdbc
//the below is just for explaination
return performAuthentication(authentication, users1);
else if("ldap".equalsIgnoreCase(authType))
logger.info("perfrom ldap authentication");
//perform your authentication using ldap
//the below is just for explaination
return performAuthentication(authentication, users2);
return null;
private Authentication performAuthentication(Authentication authentication,List<User> users)
String credential = (String) authentication.getCredentials();
String userId = authentication.getName();
for(User user: users)
if(user.getUserId().equals(userId)&& user.getPassword().equals(credential))
authentication = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),authentication.getAuthorities());
return authentication;
return null;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(UsernamePasswordAuthenticationToken.class);
If you would need to redirect different login page (not sure, if you have the requirement) you register AuthenticationFailureHandler
shown in security config. Here it is redirected to login and login1 based on condition.
http.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
WebSecurityConfig.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
@Bean
public AuthenticationManager getAuthenticationManager() throws Exception
return super.authenticationManagerBean();
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired()
AuthenicationProviderJdbcImpl authenicationProviderJdbcImpl;
@Autowired()
AuthenicationProviderLdapImpl authenicationProviderLdapImpl;
@Autowired
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception
http.addFilterAt(customUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration","/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()//.successHandler(authenticationSuccessHandler)
.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
.and()
.logout()
.permitAll();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authenicationProviderLdapImpl).authenticationProvider(authenicationProviderJdbcImpl);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
/*auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());*/
The below is from logs when authType = jdbc
or authType=ldap
login called
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] stomUsernamePasswordAuthenticationFilter : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom jdbc authentication
login called
login1 called
login1 called
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] stomUsernamePasswordAuthenticationFilter : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom ldap authentication returning true in ldap
If you look at code in UsernamePasswordAuthenticationFilter
there is setDetails
method.
from docs:
Provided so that subclasses may configure what is put into the
authentication request's details property.
Idea from here
Provision to change ldap/Ad provider url at run time
You can set the details like authtype here and use it authentication provider, But to achieve the things you would lik adds little more work.
Adding details and hope it helps.
CustomUsernamePasswordAuthenticationFilter.java
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;
@Component
public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter
private static final Logger logger = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
@Autowired
@Override
public void setAuthenticationManager(AuthenticationManager authenticationManager)
// TODO Auto-generated method stub
super.setAuthenticationManager(authenticationManager);
@Autowired
@Override
public void setAuthenticationDetailsSource(
AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource)
super.setAuthenticationDetailsSource(authenticationDetailsSource);
@Override
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest)
String authType = request.getParameter("authType");
logger.info("authType ",authType);
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
But this is not sufficient you would need to extend WebAuthenticationDetails
.
Reason is WebAuthenticationDetails
provides only remote IP address
and sessionId
so, to add authType we need to extend this class.
You have to extend WebAuthenticationDetailsSource
to return CustomAuthenticationDetails
as shown below.
CustomAuthenticationDetails.java
public class CustomAuthenticationDetails extends WebAuthenticationDetails
private final String authType;
public CustomAuthenticationDetails(HttpServletRequest request)
super(request);
authType = request.getParameter("authType");
public String getAuthType()
return authType;
CustomWebAuthenticationDetailsSource.java
public class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context)
return new CustomAuthenticationDetails(context);
Please note these classes for demo purpose only.
Need to autowire
actual authentication providers in these classes.
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
import org.springframework.stereotype.Component;
@Component
public class AuthenicationProviderJdbcLdapImpl implements AuthenticationProvider
// you need to autowire jdbc auth provider
@Autowired(required = false)
DaoAuthenticationProvider authenticationProvider;
//you need to autowire ldap auth provider
@Autowired(required = false)
LdapAuthenticationProvider ldapAuthenticationProvider;
protected static class User
private final String userId;
private final String password;
public User(String userId,String password)
this.userId = userId;
this.password = password;
public String getUserId()
return userId;
public String getPassword()
return password;
@Override
public String toString()
return "User [userId=" + userId + ", password=" + password + "]";
private final static Logger logger = LoggerFactory.getLogger(AuthenicationProviderJdbcLdapImpl.class);
private static final List<User> users1 = Arrays.asList(new User("admin1", "password"),new User("admin2", "password"));
private static final List<User> users2 = Arrays.asList(new User("admin3", "password"),new User("admin4", "password"));
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
CustomAuthenticationDetails details = (CustomAuthenticationDetails) authentication.getDetails();
String authType = details.getAuthType();
logger.info("authType ",authType);
if("jdbc".equalsIgnoreCase(authType))
logger.info("perfrom jdbc authentication");
//perform your authentication using jdbc
//the below is just for explaination
return performAuthentication(authentication, users1);
else if("ldap".equalsIgnoreCase(authType))
logger.info("perfrom ldap authentication");
//perform your authentication using ldap
//the below is just for explaination
return performAuthentication(authentication, users2);
return null;
private Authentication performAuthentication(Authentication authentication,List<User> users)
String credential = (String) authentication.getCredentials();
String userId = authentication.getName();
for(User user: users)
if(user.getUserId().equals(userId)&& user.getPassword().equals(credential))
authentication = new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(),authentication.getAuthorities());
return authentication;
return null;
@Override
public boolean supports(Class<?> authentication)
return authentication.equals(UsernamePasswordAuthenticationToken.class);
If you would need to redirect different login page (not sure, if you have the requirement) you register AuthenticationFailureHandler
shown in security config. Here it is redirected to login and login1 based on condition.
http.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
WebSecurityConfig.java
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
return new BCryptPasswordEncoder();
@Bean
public AuthenticationManager getAuthenticationManager() throws Exception
return super.authenticationManagerBean();
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired()
AuthenicationProviderJdbcImpl authenicationProviderJdbcImpl;
@Autowired()
AuthenicationProviderLdapImpl authenicationProviderLdapImpl;
@Autowired
CustomUsernamePasswordAuthenticationFilter customUsernamePasswordAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception
http.addFilterAt(customUsernamePasswordAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration","/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()//.successHandler(authenticationSuccessHandler)
.failureHandler(new AuthenticationFailureHandler()
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException
String whichPage = request.getParameter("whichPage");
System.out.println("inside login failure handler "+whichPage);
if("login1".equals(whichPage))
response.sendRedirect(request.getContextPath() +"/login1");
else
response.sendRedirect(request.getContextPath() +"/login");
)
.and()
.logout()
.permitAll();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
auth.authenticationProvider(authenicationProviderLdapImpl).authenticationProvider(authenicationProviderJdbcImpl);
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
/*auth.userDetailsService(userDetailsService)
.passwordEncoder(bCryptPasswordEncoder());*/
The below is from logs when authType = jdbc
or authType=ldap
login called
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] stomUsernamePasswordAuthenticationFilter : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : authType jdbc
2018-11-23 17:45:25.606 INFO 7232 --- [nio-8080-exec-6] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom jdbc authentication
login called
login1 called
login1 called
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] stomUsernamePasswordAuthenticationFilter : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : authType ldap
2018-11-23 17:45:42.435 INFO 7232 --- [nio-8080-exec-5] c.t.a.AuthenicationProviderJdbcLdapImpl : perfrom ldap authentication returning true in ldap
edited Nov 23 '18 at 12:17
answered Nov 19 '18 at 10:23
secret super starsecret super star
977114
977114
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53275645%2fselection-based-authprovider-spring-security%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
How is your
Filter
implementation looks like? I am wondering if you are checking what kind of authentication to be executed infilter
and what do you do if authentication fails? are you seeing any error?– secret super star
Nov 19 '18 at 9:50
As seen in the xml, there are 2 filters. First one is to extract the header value for LDAP check. Second one am using filter for passing a 3rd value i.e. captcha. after that in both cases the getAuthenticationManager().authenticate(authentication); is called. Filter doesn't perform extra actions rather than passing control to auth manager
– Akhil K Nambiar
Nov 19 '18 at 11:05
<intercept-url pattern="/home*" access="permitAll" /> this will allow users to enter that page with out authentication.
– shadow
Nov 22 '18 at 5:47
You want to change "spring security config" based on user selection!? I think you won't be able to "change the config dynamically", but what seems an approach: 1. "permitAll" for the "new screen" 2. set a (session) flag (designated by you) 3. check that flag and adjust your filters accordingly ..and another approach 'd be: multiple security configurations
– xerx593
Nov 22 '18 at 8:31
Edited the answer to select auth provider based on input and redirect to different login page based on condition, if this was your original question
– secret super star
Nov 23 '18 at 11:54