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 【参考方案1】:

您的方法似乎很合理,您认为 Spring 会尝试每个 AuthenticationProvider 直到获得成功的结果是正确的,因此在您的情况下,您将在 LDAP 提供程序之前定义基于 IP 的提供程序。

根据您的设置,您可能无法在 authentication.getDetails() 调用中获得 WebAuthenticationDetails 对象。如果是这种情况,您应该将 Spring 的 RequestContextListener 或 RequestContextFilter 添加到您的 web.xml。然后,您将能够通过使用 RequestContextHolder 类并调用 RequestContextHolder.getRequestAttributes() 来获取源 IP 地址。

你应该只需要实现一个AuthenticationProvider,不需要实现一个UserDetailsS​​ervice、UserDetails或Authentication类。如果您无法通过用户的 IP 地址对用户进行身份验证,则应返回 null。在这种情况下,Spring 将尝试 LDAP 提供程序。如果出于某种原因您不想将尝试传递给 LDAP,您应该抛出一个 AuthenticationException ,这将停止该过程并最终导致用户出现 403 错误。

我希望这会有所帮助:)

【讨论】:

我根据 cmets 更新了我的原始帖子。我还是有问题。提前感谢您的任何提示。

以上是关于Spring 3.1 中通过 IP 地址进行身份验证:最聪明的方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Security 中通过 jdbc 身份验证使用自定义登录页面

如何在Linux中通过命令查看域名对应的IP

使用套接字在eclipse android程序中通过IP地址发送消息

vue在手机中通过本机IP地址访问webApp的方法

在 C# 中通过远程处理获取外部 IP 地址

在android中通过firebase进行Facebook登录时身份验证失败