2012-04-13 20 views
12

Tôi đã triển khai xác thực LDAP bằng cách sử dụng Spring Security 3.1. Tệp security.xml của tôi cho tệp đó được đăng bên dưới.Xác thực theo địa chỉ IP trong mùa xuân 3.1: Cách thông minh nhất để làm điều đó?

Tôi cần thay đổi quy trình xác thực của mình sao cho nếu người dùng truy cập trang từ Địa chỉ IP trên "danh sách trắng" (được lưu trong bảng cơ sở dữ liệu), thì người dùng đó sẽ tự động được xác thực với Spring 3.1 và sau đó chuyển hướng ra khỏi màn hình đăng nhập (không phải ý tưởng của tôi, tôi đã được nói như vậy).

Nếu người dùng không thuộc một trong những Địa chỉ IP được liệt kê màu trắng, thì họ sẽ bị buộc phải thực hiện xác thực LDAP trên trang đăng nhập.

Tôi mới vào mùa xuân và mùa xuân an ninh vì vậy tôi đã đi đến Spring 3.1 Reference Documentation và đọc tất cả các phần I. Ở đó, tôi đọc lời khuyên rằng nếu bạn có bất kỳ nhu cầu xác thực đặc biệt bạn nên đọc Section II Architecture and Implementation. Tôi đã làm điều đó, rất chậm và ghi chép.

Tuy nhiên, vì tôi mới làm quen với tất cả điều này, tôi không chắc tôi hoàn toàn hiểu những gì tôi cần làm và cách thông minh nhất để thực hiện điều đó là gì.


Cập nhật 3: Tôi đã nhận mã bộ xương để làm việc, sau đây là các tập tin tôi đã kết thúc với


My tùy chỉnh AuthenticationProvider thực hiện để xác thực bằng địa chỉ IP

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

} 

Tệp * -security.xml của tôi

<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> 
+1

Đó thực sự là một ý tưởng tồi. Điều gì xảy ra nếu một trong những địa chỉ được liệt kê trắng là địa chỉ của tường lửa NAT? Sau đó mọi người đứng sau bức tường lửa đó (có thể là hàng trăm người) sẽ tự động được xác thực bất kể họ là ai. –

+1

Điều đó sẽ không xảy ra trong tình huống của chúng tôi và tôi đã được lệnh phải làm điều này. – Steve

+0

Có thể bạn sẽ phải thử nghiệm các phương pháp bạn đã đề cập. Nếu danh sách địa chỉ IP không phải thay đổi động, bạn có thể tải tất cả chúng vào lúc khởi động. –

Trả lời

4

cách tiếp cận của bạn có vẻ âm thanh khá, bạn là đúng trong suy nghĩ rằng mùa xuân sẽ cố gắng mỗi AuthenticationProvider cho đến khi nó được một kết quả thành công, vì vậy trong trường hợp của bạn, bạn sẽ xác định nhà cung cấp dựa trên IP của bạn trước khi cung cấp dịch vụ LDAP.

Tùy thuộc vào thiết lập của bạn, bạn có thể không nhận được đối tượng WebAuthenticationDetails trong lệnh gọi authentication.getDetails() của bạn. Nếu trường hợp này xảy ra, bạn nên thêm số RequestContextListener hoặc RequestContextFilter của Spring vào tệp web.xml của mình. Sau đó, bạn sẽ có thể lấy địa chỉ IP nguồn bằng cách sử dụng lớp RequestContextHolder và gọi RequestContextHolder.getRequestAttributes().

Bạn chỉ cần triển khai AuthenticationProvider, không cần triển khai lớp UserDetailsService, UserDetails hoặc Authentication. Bạn nên trả về null nếu bạn không thể xác thực người dùng qua địa chỉ IP của mình. Trong trường hợp này, Spring sẽ thử nhà cung cấp LDAP. Nếu vì một lý do nào đó mà bạn không muốn truyền nỗ lực vào LDAP, bạn nên ném một AuthenticationException để dừng quá trình và cuối cùng dẫn đến lỗi 403 cho người dùng.

Tôi hy vọng điều này sẽ giúp :)

+0

Tôi đã cập nhật bài đăng gốc của mình theo các nhận xét. Tôi vẫn gặp vấn đề. Cám ơn vì đã nhiệt tình hướng dẫn. – Steve