Spring Security 3.1.3 请求查询字符串被剥离

Posted

技术标签:

【中文标题】Spring Security 3.1.3 请求查询字符串被剥离【英文标题】:Spring Security 3.1.3 request querystring stripped 【发布时间】:2014-02-25 21:57:13 【问题描述】:

我正在使用 Spring Security 3.1.3 保护我的应用程序,并且我需要允许用户通过第三方应用程序中的链接登录。

但是,第三方应用程序中的链接将重定向到特定资源,而不是用户希望的登录页面 访问将被定义为查询字符串参数。因此,例如,链接的形式为://server.com/app/build/panel.jsp?resourceid='blah'

当用户单击此链接时,他们应该被带到我的 Spring Security 配置中定义的登录页面,如果经过身份验证,则应该重定向 到包含查询字符串参数的原始链接。 querystring 参数对用户的身份验证方式没有影响 只是资源的 id。

现在,除了查询字符串之外,这一切都可以正常工作,在进入请求处理流程之前,它会被 Spring Security 剥离。

这显示在 Spring Security 的调试输出中;

org.springframework.security.web.savedrequest.HttpSessionRequestCache: DefaultSavedRequest 添加到 Session: DefaultSavedRequest[http://server.com:8080/app/build/panel.jsp]

即,查询字符串未保存,resourceid='blah' 已被删除。

注意,我目前正在使用 Ant 匹配。我不需要实际匹配查询字符串。

在 Spring Security 的早期版本中,您似乎可以根据这篇文章使用 BeanPostProcessor 来影响这种行为, Spring Security - Url with request parameters rules ignored。但是方法 DefaultFilterInvocationSecurityMetadataSource.setStripQueryStringFromUrls() 已从Spring Security 3.1.3 中删除。

如何配置 Spring Security 以不从原始请求中删除查询字符串?这样当用户在登录后被重定向到 原URL的querystring参数会保留吗?

非常感谢 霍华德

【问题讨论】:

我已经调试了当前版本(3.2.3)并发现了同样的事情。 RequestWrapper 的 javaDoc 中有一个启发性的评论:参数(如 RFC 2396 中定义)从请求的 servletPath 和 pathInfo 值的路径段中剥离。但是,我也注意到,当请求到达包装器时,容器似乎已经将它们剥离(在我的例子中是 Tomcat 7)。 您找到解决方案了吗?我在使用 RememberMe 登录时遇到了同样的问题。我在一封带有两个参数的电子邮件中有一个退出链接。如果没有 RememberMe cookie 或用户已经登录,则它可以工作。如果有有效的 cookie 并且用户未登录,则在成功登录 RememberMe 后重定向请求之前,参数会被剥离。跨度> 据我所知,问题归结于查询字符串中有某些字符。对于这个应用程序,我正在处理从 AngularJS 前端接收的查询字符串,并且该查询字符串还包含 AngularJS 页面导航,它由 # 表示。所以查询字符串类似于 //server/app/some-page?#new-issue/。 # char 的存在似乎意味着整个查询字符串都被剥离了。您的查询字符串中有任何特殊字符吗? 我发现了问题——我的错,不是 Spring Security。我的自定义 RememberMeSuccessHandler 正在执行重定向,但未附加查询字符串。查询字符串绝对可以通过request.getQueryString() 获得。 @LWK69 你能把它添加为答案,这样这个问题就不会出现在未回答的问题列表中吗? 【参考方案1】:

基本上是成功的处理程序。

你可以看看这个例子:

@Override
protected void configure(HttpSecurity http) throws Exception 
    http
      .authorizeRequests()
      .antMatchers("/login*")
      .permitAll()
      .anyRequest()
      .authenticated()
      .and()
      .formLogin()
      .successHandler(new RefererAuthenticationSuccessHandler());

更多信息:http://www.baeldung.com/spring-security-redirect-login

【讨论】:

发帖人已经回答了这个问题:编码错误-见cmets【参考方案2】:

你可以从 SuccessHandler 得到它

SecurityConfiguration 类

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 
@Autowired
SuccessHandler getSuccessHandler;

@Override
protected void configure(HttpSecurity http) throws Exception 
    http.authorizeRequests()

    .antMatchers("/dashboard/**",               
            "/feedback/**"
            ).access("hasRole('ROLE_SYSTEM_ADMIN') or hasRole('ROLE_COMPANY_ADMIN')")

    .and().formLogin().loginPage("/login").successHandler(getSuccessHandler)
    .loginProcessingUrl("/login").usernameParameter("ssoId").passwordParameter("password")      
    .and().csrf()
    .and().exceptionHandling().accessDeniedPage("/Access_Denied")
    .and()
    .sessionManagement().invalidSessionUrl("/login").maximumSessions(1).expiredUrl("/login").and().sessionAuthenticationErrorUrl("/login").sessionFixation().migrateSession()
    .sessionCreationPolicy(SessionCreationPolicy.ALWAYS); //always, IF_REQUIRED,never ,stateless    

    http.logout()
    .logoutUrl("/logout")
    .logoutSuccessUrl("/login")
    .invalidateHttpSession(true)
    .permitAll();


 @Override
  public void configure(WebSecurity web) throws Exception 
    web
    .ignoring()     
    .antMatchers("/static/**")
    .antMatchers("/images/**");       
     

SuccessHandler 类

@Component
public class SuccessHandler implements AuthenticationSuccessHandler 


@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
    Authentication authentication) throws IOException, ServletException 

    HttpSession session = request.getSession();
    response.sendRedirect(request.getContextPath() + "/dashboard/index");


【讨论】:

【参考方案3】:

对于类似问题的其他人,请参阅链接: https://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html

提取:当应用程序部署在不从这些值中去除路径参数的容器中时,攻击者可能会将它们添加到请求的 URL 以使模式匹配成功或意外失败。

但是,这种剥离是为了牢固地保护登录模式匹配。这并不意味着查询参数在 HTTP 请求中不可用,它们应该是。

【讨论】:

以上是关于Spring Security 3.1.3 请求查询字符串被剥离的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security教程

Spring security 3.1.4 和 ShaPasswordEncoder 弃用

如何使用 Spring Security 3.1.3 和 JSF 创建一个 Bean 来验证我的登录表单

Spring Security入门(3-7)Spring Security处理页面的ajax请求

spring.security 禁止 curl 发布请求

Spring-Security-Oauth整合Spring-Security,拦截器