我正在开发一个项目,我正在使用Spring Security,它可以很好地从DB验证用户。
现在我需要的是我想使用LDAP和保持现有数据库身份验证来验证用户。
另外,我不能通过使用Spring安全性来使用标准的LDAP身份验证方式,因为我只有一个函数调用来通过类似的方法来验证用户是否存在,
com.company.ldap.Authentication auth = new com.company.ldap.Authentication();
int status = auth.authenticate(userName, userPassword);
如果我收到状态为1,那么用户将被验证,否则不会。
因此,对于这种情况,我创建了单独的URL“/ j_spring_facebook_security_check”(此处名称为facebook,但实际上是用于LDAP)
我的applicationContext-Security文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">
<security:http auto-config="true" use-expressions="true" access-denied-page="/accessDenied.jsp">
<security:form-login login-page="/index.jsp"
default-target-url="/jsp/home.jsp"
authentication-failure-handler-ref="authenticationFailureHandler" />
<security:intercept-url pattern="/jsp/listInBetweenPlaces.jsp"
access="permitAll" />
<security:intercept-url pattern="/jsp/home.jsp"
access="permitAll" />
<security:intercept-url pattern="/jsp/*"
access="isAuthenticated()" />
<security:logout logout-url="/j_spring_security_logout" logout-success-url="/index.jsp?logout=success"
invalidate-session="true" />
<security:custom-filter before="FORM_LOGIN_FILTER"
ref="facebookAuthenticationFilter" />
</security:http>
<bean id="facebookAuthenticationFilter" class="org.springframework.security.facebook.FacebookAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name = "authenticationSuccessHandler">
<bean class = "org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
<property name = "defaultTargetUrl" value = "/jsp/home.jsp" />
<property name = "alwaysUseDefaultTargetUrl" value = "true" />
</bean>
</property>
<property name = "authenticationFailureHandler">
<bean class = "org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name = "defaultFailureUrl" value = "/fb/failure.jsp" />
</bean>
</property>
</bean>
<bean id="ldapAuthenticationProvider" class="org.springframework.security.facebook.FacebookAuthenticationProvider">
<property name="roles" value="ROLE_FACEBOOK_USER" />
</bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="customUserDetailsService">
<security:password-encoder hash="md5" />
</security:authentication-provider>
<security:authentication-provider ref="ldapAuthenticationProvider">
</security:authentication-provider>
</security:authentication-manager>
<bean id="customUserDetailsService" class="com.abc.carpool.authentication.CustomUserDetailsService">
</bean>
</beans>
FacebookAuthenticationFilter.java
public class FacebookAuthenticationFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
@Autowired
CarpoolService carpoolService=null;
public CarpoolService getCarpoolService() {
return carpoolService;
}
public void setCarpoolService(CarpoolService carpoolService) {
this.carpoolService = carpoolService;
}
public static final String DEFAULT_FILTER_PROCESS_URL = "/j_spring_facebook_security_check";
private ApplicationContext ctx;
protected FacebookAuthenticationFilter() {
super(DEFAULT_FILTER_PROCESS_URL);
}
public Authentication attemptAuthentication(HttpServletRequest req,
HttpServletResponse res) throws AuthenticationException,
IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
String userName = request.getParameter("j_username");
String userPassword = request.getParameter("j_password");
System.out.println("Username and pswd is :"+userName + " " + userPassword);
System.out.println("SYS PATH :"+System.getenv("MC_ENV_PATH"));
User user = null;
try{
com.abc.ldap.Authentication auth = new com.abc.ldap.Authentication();
int status = auth.authenticate(userName, userPassword);
//int status=2;
if(status==1){
//CREATE NEW USER AND SAVE IN DB
}
}else{
throw new UsernameNotFoundException("Incorrect Email Id or Password.");
}
System.out.println("status is :"+status);
}catch (Exception e) {
System.out.println("Exception is "+e.getMessage());
e.printStackTrace();
return null;
}
System.out.println("FacebookAuthenticationFilter.attemptAuthentication() :"+userName + " " + userPassword);
UsernamePasswordAuthenticationToken upatToken = new UsernamePasswordAuthenticationToken(userName, userPassword);
AuthenticationManager authenticationManager = getAuthenticationManager();
Authentication auth = authenticationManager.authenticate(upatToken);
return auth;
}
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
this.ctx = ctx;
}
}
FacebookAuthenticationProvider .java
public class FacebookAuthenticationProvider implements AuthenticationProvider {
private String[] roles;
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
System.out.println("FacebookAuthenticationProvider.authenticate()");
return authentication;
}
public boolean supports(Class<? extends Object> authentication) {
boolean supports = true;
return supports;
}
public void setRoles(String[] roles) {
this.roles = roles;
}
public String[] getRoles() {
return roles;
}
}
在上面的情况下,一切正常,Control将进入Filter类并使用LDAP验证用户,如果用户存在,那么我将用户一个副本保存到我的数据库,并希望继续正常流程。
实际上当我打电话时
Authentication auth = authenticationManager.authenticate(upatToken);
来自FacebookAuthenticationFilter,control,转到CustomUserDetailsService类。
我的需求是CustomUserDetailsService仅用于数据库身份验证,我不希望控制权去那里。
如何以一种很好的方式实现这一目标。
答案 0 :(得分:0)
AuthenticationProvider.supports(Class<? extends Object> authentication)
可以帮到你。此时,您将UsernamePasswordAuthenticationToken
用于两种情况(DB和LDAP)。两个身份验证提供程序都支持此类型,因此使用它在LDAP的情况下,尝试添加自定义身份验证对象:
public class CustomLdapAuthenticationToken extends AbstractAuthenticationToken {
然后在FacebookAuthenticationFilter
而不是UsernamePasswordAuthenticationToken
中使用它。
更改FacebookAuthenticationProvider.supports(...)
实施:
public boolean supports(Class<? extends Object> authentication) {
boolean result = false;
if(authentication instanceof CustomLdapAuthenticationToken) {
result = true;
}
return result;
}
从此刻起,每个身份验证提供程序将仅处理相应的身份验证请求。