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 3.1.4 和 ShaPasswordEncoder 弃用
如何使用 Spring Security 3.1.3 和 JSF 创建一个 Bean 来验证我的登录表单