Spring 3.1 中通过 IP 地址进行身份验证:最聪明的方法是啥?
Posted
技术标签:
【中文标题】Spring 3.1 中通过 IP 地址进行身份验证:最聪明的方法是啥?【英文标题】:Authenticating By IP Address In Spring 3.1: Smartest Way To Do That?Spring 3.1 中通过 IP 地址进行身份验证:最聪明的方法是什么? 【发布时间】: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您的方法似乎很合理,您认为 Spring 会尝试每个 AuthenticationProvider 直到获得成功的结果是正确的,因此在您的情况下,您将在 LDAP 提供程序之前定义基于 IP 的提供程序。
根据您的设置,您可能无法在 authentication.getDetails() 调用中获得 WebAuthenticationDetails 对象。如果是这种情况,您应该将 Spring 的 RequestContextListener 或 RequestContextFilter 添加到您的 web.xml。然后,您将能够通过使用 RequestContextHolder 类并调用 RequestContextHolder.getRequestAttributes() 来获取源 IP 地址。
你应该只需要实现一个AuthenticationProvider,不需要实现一个UserDetailsService、UserDetails或Authentication类。如果您无法通过用户的 IP 地址对用户进行身份验证,则应返回 null。在这种情况下,Spring 将尝试 LDAP 提供程序。如果出于某种原因您不想将尝试传递给 LDAP,您应该抛出一个 AuthenticationException ,这将停止该过程并最终导致用户出现 403 错误。
我希望这会有所帮助:)
【讨论】:
我根据 cmets 更新了我的原始帖子。我还是有问题。提前感谢您的任何提示。以上是关于Spring 3.1 中通过 IP 地址进行身份验证:最聪明的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Security 中通过 jdbc 身份验证使用自定义登录页面