Java 基于选择的AuthProvider Spring安全性
我已经将Spring安全性配置为同时使用LDAP和基于DB的登录。首先,它尝试通过LDAP登录,如果所需的权限不存在,则转到用户名/密码输入页面Java 基于选择的AuthProvider Spring安全性,java,spring,spring-security,Java,Spring,Spring Security,我已经将Spring安全性配置为同时使用LDAP和基于DB的登录。首先,它尝试通过LDAP登录,如果所需的权限不存在,则转到用户名/密码输入页面 <security:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint"> <security:custom-filter ref="customPreAuthFilter" position="PRE_AUTH_FILTER"/
<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>
我想在顶部添加一个新屏幕,用户需要在两个按钮LDAP或username/pass之间进行选择。我该如何进行
要访问的数据是相同的url,即/home,但ldap和DB用户都应该能够访问。如果查看UsernamePasswordAuthenticationFilter中的代码,则有setDetails方法
发件人:
提供,以便子类可以配置放入
身份验证请求的详细信息属性
从这里开始的想法
您可以在此处设置authtype之类的详细信息,并使用it身份验证提供程序,但要实现您想要的功能,只需做很少的工作
增加细节,希望能有所帮助
CustomUsernamePasswordAuthenticationFilter.java
CustomWebAuthenticationDetailsSource.java
请注意这些课程仅供演示之用
需要自动连接这些类中的实际身份验证提供程序
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);
}
}
WebSecurityConfig.java
下面是authType=jdbc或authType=ldap时的日志
您的过滤器实现是什么样子的?我想知道您是否正在检查要在筛选器中执行哪种身份验证,以及如果身份验证失败,您会怎么做?您是否看到任何错误?如xml中所示,有两个筛选器。第一个是提取用于LDAP检查的头值。第二个是使用过滤器传递第三个值,即验证码。之后,在这两种情况下,getAuthenticationManager.authenticateauthentication;被称为。筛选器不会执行额外操作,而不会将控制权传递给身份验证管理器。这将允许用户在不进行身份验证的情况下进入该页面。是否要根据用户选择更改spring安全配置!?我认为您将无法动态更改配置,但这似乎是一种方法:1。新屏幕2的屏幕高度。设置由您指定的会话标志3。检查该标志并相应地调整过滤器。另一种方法是:编辑答案,根据输入选择验证提供程序,并根据条件重定向到不同的登录页面,如果这是您的原始问题,如果我在创建WebAuthenticationDetails时未找到线程绑定请求怎么办?将其标记为@Component,以便在自定义筛选时找到beancreating@user2501323这是一个问题还是澄清?@Haider不。如果你理解这个概念,我认为你应该能够实现它。
public class CustomAuthenticationDetails extends WebAuthenticationDetails{
private final String authType;
public CustomAuthenticationDetails(HttpServletRequest request) {
super(request);
authType = request.getParameter("authType");
}
public String getAuthType() {
return authType;
}
}
public class CustomWebAuthenticationDetailsSource extends WebAuthenticationDetailsSource {
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
return new CustomAuthenticationDetails(context);
}
}
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);
}
}
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");
}
}
})
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());*/
}
}
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