【问题标题】:spring security authentication using ip address and username password使用ip地址和用户名密码的spring安全认证
【发布时间】:2014-04-05 22:41:16
【问题描述】:

我正在使用 loadUserByUsername 方法对用户进行身份验证,但是,我还需要针对允许的 IP 地址进行验证。

但是当我尝试的时候

SecurityContextHolder.getContext().getAuthentication(); 

得到空值。

请指教,我如何在验证用户时访问用户的客户端 IP 地址。

【问题讨论】:

  • 身份验证时为什么需要IP地址。为什么不简单地使用表达式来检查 ip 地址是否具有访问权限。
  • @Deinum,允许的ip地址将分配给用户帐户,而不是固定的ip地址,所以我不能使用表达式。
  • 为什么不能使用表达式? UserDetailsService 仅用于加载用户。如果这是您的自定义用户,您可以编写一个表达式来查看当前 IP 地址是否在允许的 IP 地址列表中。我仍然不明白为什么你不能使用表达式。然而,第一步是在正确的地方解决它,UserDetailsService 不是正确的地方。
  • 我使用了网址stackoverflow.com/questions/10147161/…中提到的类似方法并且工作了

标签: spring spring-security


【解决方案1】:
/**
 * IP address based authentication provider
 */
@Service 
public class IPAddressBasedAuthenticationProvider extends AuthenticationProvider {

     @Override
     public Authentication authenticate(Authentication authentication) throws AuthenticationException {

              final WebAuthenticationDetails details = (WebAuthenticationDetails) auth.getDetails();
              details.getRemoteAddress();
    }
}

【讨论】:

    【解决方案2】:

    您正在实现 UserDetailsS​​ervice 的 loadUserByUsername 方法。

    根据文档 关于 UserDetailsS​​ervice 经常有一些混淆。它纯粹是用户数据的 DAO,除了将数据提供给框架内的其他组件外,不执行任何其他功能。特别是,它不对用户进行身份验证,这是由 AuthenticationManager 完成的。在许多情况下,如果您需要自定义身份验证过程,直接实现 AuthenticationProvider 会更有意义。

    UserDetails userDetails= customUserDetailsService.loadUserByUsername("name"); 
    

    这将给出一个 userDetails 对象。您可以在 loadUserByUsername() 中执行所有与权限相关的代码。如果您想在 Spring Security 中手动设置经过身份验证的用户。按照代码进行操作

     Authentication authentication= new  UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) ;  
                    SecurityContextHolder.getContext().setAuthentication(authentication);
    

    您将从请求标头中获取 IP 地址。

    How can I retrieve IP address from HTTP header in Java

    您可以在 spring 安全过滤器链中的某个地方执行此操作。

    【讨论】:

    • 我可以使用此身份验证获取远程 IP 地址吗?
    【解决方案3】:

    要解决您的问题,您应该实现自定义身份验证提供程序(可以基于 DaoAuthenticationProvider 或者可以从头开始实现等)。此身份验证提供程序应在身份验证管理器提供程序集中注册。此外,此提供程序将具有自动连接的 HttpServletRequest 类型属性,与上下文 http 请求相关。然后,当您通过该提供程序执行客户端身份验证时,您可以通过调用HttpServletRequest.getRemoteAddr() 来获取用户 IP 地址。 代码:

    /**
     * IP address based authentication provider
     */
    @Service 
    public class IPAddressBasedAuthenticationProvider extends AuthenticationProvider {
    
         /**
          * Context http request
          */
         @Autowired
         private HttpServletRequest request;
    
         @Override
         public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    
             String ipAddress = request.getRemoteAddr();
             //do authentication specific stuff (accessing users table in database, etc.)
             //return created authentication object (if user provided valid credentials)
        }
    }
    

    配置:

    <security:http auto-config="true" authentication-manager-ref="authenticationManager" use-expressions="true"/>
    
    <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
     <constructor-arg name="providers">
      <list>
       <ref bean="iPAddressBasedAuthenticationProvider"/>
      </list>
     </constructor-arg>
    </bean>
    

    此外,您还可以添加其他身份验证提供程序(如果需要)。 希望这可以帮助。 友情链接:AuthenticationProvider ProviderManager

    【讨论】:

    • 我使用了url中提到的类似方法stackoverflow.com/questions/10147161/…
    • 如果您已经通过 'UserDetailsS​​ervice' 执行了身份验证,您可以添加额外的 'AuthenticationManager' 来保存 http 请求并获取有效的 'Authentication' 对象,您可以在其中执行您实际需要的操作。或者您可以使用 http 请求扩展“UserDetailsS​​ervice”。因此,重点是创建一个服务,该服务将保存来自一侧的 http 请求和来自另一侧的身份验证数据。
    • 但它已经很老了,还有一点需要注意:除非您注册了监听器 org.springframework.web.context.request.RequestContextListener,否则这将不起作用。
    • 当然,如果你想使用“请求”范围的东西,你应该应用特定的监听器。
    猜你喜欢
    • 2014-02-23
    • 2016-05-10
    • 2012-02-08
    • 2018-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多