Вопрос по ip, spring-security, java – Аутентификация по IP-адресу весной 3.1: самый умный способ сделать это?

12

Я реализовал аутентификацию LDAP с использованием Spring Security 3.1. Мой файл security.xml для этого размещен ниже.

Мне нужно изменить процесс аутентификации таким образом, чтобы, если пользователь зашел на сайт с IP-адреса, указанного в «белом списке» (хранится в таблице базы данных), затем этот пользователь должен автоматически проходить аутентификацию в Spring 3.1 и затем перенаправляться с экрана входа в систему (не моя идея, мне так сказали).

Если пользователь не принадлежит одному из IP-адресов, занесенных в белый список, он / она должны быть вынуждены пройти аутентификацию LDAP на странице входа в систему.

Я новичок в Spring и Spring Security, поэтому я пошел вSpring 3.1 Справочная документация и прочитайте весь Раздел I. Там, я прочитал совет, что если у вас есть какие-либо особые потребности аутентификации, вы должны прочитатьРаздел II Архитектура и реализация, Я делал это очень медленно и делал заметки.

Однако, поскольку я новичок во всем этом, я не уверен, что полностью понимаю, что мне нужно делать, и каков самый умный способ сделать это.

Update 3: I got the skeleton code to work, here are the files I ended up with

My custom AuthenticationProvider implementation for authenticating by IP Address

// 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));
    }

}

My *-security.xml file

<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>
& lt; s: поставщик проверки подлинности ref = & quot; customAuthenticationProvider & quot; / & GT; Добавьте компонент как & lt; идентификатор компонента = & quot; customAuthenticationProvider & quot; класс = & Quot; com.acme.controller.security.authentication.CustomAuthenticationProvider & Quot; / & GT; Ritesh
Это действительно плохая идея. Что если один из адресов из белого списка является адресом брандмауэра NAT? Тогда все за этим брандмауэром (это могут быть сотни людей) будут автоматически аутентифицироваться независимо от того, кто они. Jim Garrison
Это не произойдет в нашей ситуации, и мне было приказано сделать это. Steve
@ Стив Это выглядит хорошо. Возвращать ноль - это нормально. К следующему провайдеру в цепочке будут обращаться, если вы вернете значение null из метода authenticate вашего провайдера. Пожалуйста, посмотрите исходный код LdapUserDetailsManager, чтобы увидеть, можете ли вы использовать его для построения UserDetails (метод loadUserByUsername). Вам не нужно помещать ObjThatImplementsAuthentication в SecurityContextHolder в классе провайдера. Просто убедитесь, что в возвращаемой вами ObjThatImplementsAuthentication есть все, что вам нужно (принципал, данные и полномочия). Ritesh
@Steve Написание класса провайдера это путь. В методе аутентификации класса провайдера, authentication.getDetails (), по умолчанию возвращает WebAuthenticationDetails (static.springsource.org/spring-security/site/docs/3.1.x/apidocs/…). Его метод getRemoteAddress даст вам IP-адрес. Ritesh

Ваш Ответ

1   ответ
3

вы правы, полагая, что Spring будет пробовать каждый AuthenticationProvider до тех пор, пока он не получит успешный результат, поэтому в вашем случае вы должны определить своего IP-провайдера перед LDAP-провайдером.

В зависимости от вашей настройки вы можете не получить объект WebAuthenticationDetails при вызове authentication.getDetails (). Если это так, вы должны добавить Spring'ыRequestContextListener или жеRequestContextFilter на ваш web.xml. После этого вы сможете получить исходный IP-адрес, используя класс RequestContextHolder и вызывая RequestContextHolder.getRequestAttributes ().

Вам нужно только реализовать AuthenticationProvider, нет необходимости реализовывать класс UserDetailsService, UserDetails или Authentication. Вы должны вернуть null, если вы не можете аутентифицировать пользователя по его IP-адресу. В этом случае Spring попробует провайдера LDAP. Если по какой-то причине вы не хотите передавать попытку на LDAP, вы должны сгенерировать исключение AuthenticationException, которое остановит процесс и в конечном итоге приведет к ошибке 403 для пользователя.

Надеюсь, это поможет :)

Я обновил свой оригинальный пост в свете комментариев. У меня все еще есть проблема. Заранее спасибо за любые советы. Steve

Похожие вопросы