【发布时间】:2012-04-26 04:35:29
【问题描述】:
我已经使用 Spring Security 3.1 实现了 LDAP 身份验证。我的 security.xml 文件发布在下面。
我需要更改我的身份验证过程,以便如果用户从“白名单”(保存在数据库表中)上的 IP 地址访问站点,则该用户应自动通过 Spring 3.1 进行身份验证,然后重定向远离登录屏幕(不是我的想法,有人告诉我这样做)。
如果用户不是来自列入白名单的 IP 地址之一,那么她/他应该被强制在登录页面上通过 LDAP 身份验证。
我是 Spring 和 Spring Security 的新手,所以我去了 Spring 3.1 Reference Documentation 并阅读了第 I 部分的所有内容。在那里,我阅读了建议,如果您有任何特殊的身份验证需求,您应该阅读 Section II Architecture and Implementation。我这样做了,非常缓慢并记笔记。
但是,由于我对这一切都不熟悉,我不确定我是否完全了解我需要做什么以及最聪明的方法是什么。
更新 3:我得到了框架代码,这是我最终得到的文件
用于通过 IP 地址进行身份验证的自定义 AuthenticationProvider 实现
// Authentication Provider To Authenticate By IP Address With Allowed IPs
// Stored in a db table
package acme.com.controller.security;
//import acme.com.controller.security.CustomUserInfoHolder;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.apache.log4j.Logger;
public class CustomIPAddressAuthenticationProvider implements AuthenticationProvider
{
private static final Logger logger = Logger.getLogger(CustomIPAddressAuthenticationProvider.class);
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
WebAuthenticationDetails wad = null;
String userIPAddress = null;
boolean isAuthenticatedByIP = false;
// Get the IP address of the user tyring to use the site
wad = (WebAuthenticationDetails) authentication.getDetails();
userIPAddress = wad.getRemoteAddress();
logger.debug("userIPAddress == " + userIPAddress);
// Compare the user's IP Address with the IP address in the database
// stored in the USERS_AUTHENTICATED_BY_IP table & joined to the
// USERS tabe to make sure the IP Address has a current user
//isAuthenticatedByIP = someDataObject.hasIPAddress(userIPAddress);
isAuthenticatedByIP = true;
// Authenticated, the user's IP address matches one in the database
if (isAuthenticatedByIP)
{
logger.debug("isAuthenticatedByIP is true, IP Addresses match");
UserDetails user = null;
UsernamePasswordAuthenticationToken result = null;
result = new UsernamePasswordAuthenticationToken("John Principal",
"PlaceholderPWE");
result.setDetails(authentication.getDetails());
return result;
}
// Authentication didn't happen, return null to signal that the
// AuthenticationManager should move on to the next Authentication provider
return null;
}
@Override
public boolean supports(Class<? extends Object> authentication)
{
// copied it from AbstractUserDetailsAuthenticationProvider
return(UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
我的 *-security.xml 文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="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.1.xsd">
<s:http pattern="/login*" security="none"/>
<s:http pattern="/search*" security="none"/>
<s:http pattern="/css/**" security="none"/>
<s:http pattern="/js/**" security="none"/>
<s:http pattern="/images/**" security="none"/>
<s:http auto-config="true" use-expressions="true">
<s:intercept-url pattern="/**" access="isAuthenticated()" />
<s:form-login login-page="/login"
authentication-failure-url="/loginfailed" />
<s:logout logout-success-url="/logout" />
</s:http>
<s:ldap-server url = "ldap://ldap-itc.smen.acme.com:636/o=acme.com"/>
<bean id="customIPAddressAuthenticationProvider" class="com.acme.controller.security.CustomIPAddressAuthenticationProvider" />
<s:authentication-manager>
<!-- Proposed: Custom Authentication Provider: Try To Authenticate BY IP Address First, IF NOT, Authenticate WiTh THE LDAP Authentication Provider -->
<s:authentication-provider ref="customIPAddressAuthenticationProvider" />
<s:ldap-authentication-provider user-dn-pattern="uid={0},ou=People"/>
</s:authentication-manager>
</beans>
【问题讨论】:
-
这真是个坏主意。如果白名单地址之一是 NAT 防火墙的地址怎么办?然后防火墙后面的每个人(可能是数百人)都将自动进行身份验证,无论他们是谁。
-
在我们的情况下不会发生这种情况,我已被命令这样做。
-
@Steve 编写提供程序类是要走的路。在提供者类的身份验证方法中,authentication.getDetails() 默认返回 WebAuthenticationDetails(static.springsource.org/spring-security/site/docs/3.1.x/apidocs/…)。它的方法 getRemoteAddress 会给你 IP 地址。
-
@Steve 看起来不错。返回 null 是完全可以的。如果您从提供者的身份验证方法返回 null,则将咨询链中的下一个提供者。请查看 LdapUserDetailsManager 的源代码,看看是否可以使用它来构建 UserDetails(方法 loadUserByUsername)。您不必将 ObjThatImplementsAuthentication 放在提供程序类的 SecurityContextHolder 中。只需确保您返回的 ObjThatImplementsAuthentication 具有您需要的一切(主体、详细信息和权限)。
-
添加一个 bean
标签: java authentication spring-security ip