如何禁用parsing作为URL参数/从URL传递的login参数

应用程序logging所有请求的url 。 这意味着,不使用url参数进行身份validation是非常重要的,因为这会导致日志满满的情况(login=abc&password=123) 。 因为这个原因,我configuration了spring-securityrequest-body读取参数。 这是通过将以下行添加到request-header

 'Content-Type': 'application/x-www-form-urlencoded' 

身体将是:

 {'login':'admin', 'password':'password'} 

这很好,但QA迫使我禁用通过URL参数进行身份validation的可能性。 目前,对以下URL的POST也将进行身份validation:

 https://example.com/foo?login=admin&password=password 

有谁知道一个技巧来禁用此选项? 最好用注释。

由于评论我决定添加一些更多的细节,我的问题。 我的spring-security使用WebSecurityConfigurerAdapterconfiguration。 我有

 http.usernameParameter("login") .passwordParameter("password") (...) 

这使得Spring在参数和正文中searchlogin数据。 我希望禁用searchURL中的这些参数。

这使得Spring在参数和正文中searchlogin数据。 我希望禁用searchURL中的这些参数。

我相信这是不可能的,因为这个行为不是由Spring而是由JavaEE本身实现的。

HttpServletRequest.getParameter doc指出:

以Stringforms返回请求参数的值;如果参数不存在,则返回null。 请求参数是与请求一起发送的额外信息。 对于HTTP Servlet, 参数包含在查询string或发布的表单数据中

但你可以尝试改变这个filter应该看起来像这样:

 public class DisableGetAuthFiler extends OncePerRequestFilter { ... @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter( new HttpServletRequestWrapper(request) { @Override public String getParameter(String name) { if (("login".equals(name) && getQueryString().contains("login")) || ("password".equals(name) && getQueryString().contains("password"))) { return null; } else { return super.getParameter(name); } } }, response ); } } 

编辑 Haim拉曼提出了另一种解决scheme ,使用现有的filter,而不是引入一个新的。 只有我会build议覆盖obtainUsername()obtainPassword()而不是attemptAuthentication()

据我所知,直觉就像jhan所说的,适当的解决scheme是使用注解@RequestMapping(value="/login", method="RequestMethod.POST") 。 然后,无论用户使用哪个parameter passingURL,URL和URI都将默认为/ login。 这就是logging器将logging的内容。 不是用户名和密码对,而是"http://localhost:8080/login" ,或者你的端口号。

我想build议一个基于spring-security rater的替代scheme,然后是chimmi提出的解决方法。

这个答案提供了一个解决scheme,由xenterosbuild议在bres26答案以及

覆盖现有的UsernamePasswordAuthenticationFilter实现

 public class ImprovedUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Override protected String obtainUsername(HttpServletRequest request) { final String usernameParameter = getUsernameParameter(); validateQueryParameter(request, usernameParameter); return super.obtainUsername(request); } @Override protected String obtainPassword(HttpServletRequest request) { final String passwordParameter = getPasswordParameter(); validateQueryParameter(request, passwordParameter); return super.obtainPassword(request); } private void validateQueryParameter(HttpServletRequest request, String parameter) { final String queryString = request.getQueryString(); if (!StringUtils.isEmpty(queryString)) { if (queryString.contains(parameter)) throw new AuthenticationServiceException("Query parameters for login are a prohibit, use message body only!"); } } } 

您需要用现有的实现来replace自己的实现(请参阅文档)

 @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/", "/home","/login").permitAll() .anyRequest().authenticated() .and() .logout() .permitAll() .and() //Replace FORM_LOGIN_FILTER with your own custom implementation .addFilterAt(improvedUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class) .exceptionHandling() .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login")) .and() //disable csrf to allow easy testing .csrf().disable(); } @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER"); } public UsernamePasswordAuthenticationFilter improvedUsernamePasswordAuthenticationFilter() throws Exception { UsernamePasswordAuthenticationFilter authFilter = new ImprovedUsernamePasswordAuthenticationFilter(); authFilter.setRequiresAuthenticationRequestMatcher( new AntPathRequestMatcher("/login", "POST") ); authFilter .setAuthenticationManager(authenticationManager()); authFilter .setAuthenticationSuccessHandler( new SavedRequestAwareAuthenticationSuccessHandler() ); authFilter .setAuthenticationFailureHandler( new SimpleUrlAuthenticationFailureHandler("/login?error") ); return authFilter; } } 

优点 :基于弹簧安全性和灵活的变化。
缺点 :不幸的是我发现Spring Java Config很难设置和读取

编辑:我接受了chimmi评论和重写getsUsername和obtainPassword
你可以在github中find源代码。

你可以通过修改UsernamePasswordAuthenticationFilterRequestMatcher来实现。 例如:

 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .formLogin() .withObjectPostProcessor(new ObjectPostProcessor<UsernamePasswordAuthenticationFilter>() { @Override public <O extends UsernamePasswordAuthenticationFilter> O postProcess( O filter) { AntPathRequestMatcher pathMatcher = new AntPathRequestMatcher("/login", "POST"); RequestMatcher noQuery = new RequestMatcher() { @Override public boolean matches(HttpServletRequest request) { return request.getQueryString() == null; } }; AndRequestMatcher matcher = new AndRequestMatcher(Arrays.asList(pathMatcher, noQuery)); filter.setRequiresAuthenticationRequestMatcher(matcher); return filter; } }) .and() ... } } 

:下面的要求不会阻止发出GET请求(并因此泄漏凭证)。 确保这不会发生,这真的取决于用户界面。

这很好,但QA迫使我禁用通过URL参数进行身份validation的可能性。