【问题标题】:Spring Security - retrieve user IP, browser info and requested pageSpring Security - 检索用户 IP、浏览器信息和请求页面
【发布时间】:2011-12-11 22:25:29
【问题描述】:

我们使用RequestHeaderAuthenticationFilter 作为预认证策略,PreAuthenticatedAuthenticationProvider 作为认证提供者。要求之一是使用以下信息将所有成功登录存储到数据库。由于UserDetailsService 类中没有用户 IP 地址和其他请求相关信息,检索此信息并存储在 db 中的最佳策略是什么?

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    所有信息都可以通过HttpServletRequest 获得。您可以通过以下方式获得它:

    依赖注入

    最简单的方法是将 servlet 请求直接注入您的 UserDetailsService: 类:

    public MyDetailsService implements UserDetailsService {
    
      @Autowired
      private HttpServletRequest request;
    
      //...
    
    }
    

    (根据 OP 的建议)记得将以下监听器添加到您的 web.xml:

    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    

    更新:这是因为 Spring 注入了实现HttpServletRequest 的特殊作用域代理,因此您可以从单例作用域MyDetailsService 访问请求作用域的请求“bean”。在后台,对request 参数的每次调用都会路由到org.springframework.web.context.request.RequestContextHolder#requestAttributesHolder ThreadLocal,您也可以直接访问它。如您所见,Spring 在范围规则方面非常灵活。它只是工作。

    RequestContextHolder

    另一种方法是使用RequestContextHolder:

    HttpServletRequest request = 
      ((ServletRequestAttributes) RequestContextHolder.
        currentRequestAttributes()).
        getRequest();
    

    延伸阅读:

    【讨论】:

    • 感谢 Tomasz 的回复,我还没有尝试过您的解决方案,但有一个问题.. 自定义 UserDetailsS​​ervice 不是会话范围的 bean 吗?我认为只有在有新会话或现有会话过期时才会创建这种类型的对象。如果它确实是一个会话范围的 bean,那么我们如何注入一个请求范围的 HttpServletRequest?如果 UserDetailsS​​ervice 是基于请求的,那么如何调用 loadUser..() 方法不是针对每个请求?
    • @Tomasz,这行得通吗? UserDetailsS​​ervice 通常是请求范围的 bean 吗?
    • @rrkwells, @Peter Mularien:UserDetailsService 应该始终是单例,HttpServletRequest 是请求范围的。这要归功于透明地应用了额外的 Spring scoped-proxy 魔法。另请参阅我的更新。别担心,试试吧:-)。
    • @Tomasz.. 很抱歉没有早点回复.. 我今天刚刚测试了您的第一个解决方案,它按预期工作。我只需要在 web.xml 文件中添加请求上下文侦听器。非常感谢您的帮助。
    • 很高兴我能帮上忙,我已将RequestContextListener 添加到我的完整答案中,谢谢!
    【解决方案2】:

    这可能是个好方法:

    1) 创建一个扩展 SavedRequestAwareAuthenticationSuccessHandler 的类

    public class MyCustomSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws ServletException, IOException {
    

    2) 将“成功处理程序”分配给您的安全过滤器:

    <beans:bean id="myFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
            <beans:property name="authenticationManager" ref="authenticationManager"/>
            <beans:property name="authenticationFailureHandler" ref="failureHandler" />
                   <beans:property name="authenticationSuccessHandler" ref="successHandler" />
        </beans:bean>
    
    <beans:bean id="successHandler" class="yourPackage.MyCustomSuccessHandler" >
            <beans:property name="defaultTargetUrl" value="/index.html" /> 
            <beans:property name="alwaysUseDefaultTargetUrl" value="true"/> 
        </beans:bean>
    

    【讨论】:

      猜你喜欢
      • 2011-09-25
      • 2014-10-27
      • 2010-10-13
      • 2017-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      相关资源
      最近更新 更多