如何禁用解析作为 url 参数传递的登录参数 / 来自 url

应用程序记录所有请求的 s。这意味着,不要使用url参数进行身份验证至关重要,因为这会导致日志充满成对的情况。因此,我已配置为从 中读取参数。这是通过将以下行添加到中来完成的:url(login=abc&password=123)spring-securityrequest-bodyrequest-header

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

正文将是:

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

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

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

有谁知道禁用此选项的技巧吗?最好带有注释。

由于评论,我决定为我的问题添加更多细节。My 配置了 .我有spring-securityWebSecurityConfigurerAdapter

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

这使得在参数和正文中搜索登录数据。我希望禁用在URL中搜索这些参数。Spring


答案 1

这使得Spring在参数和正文中搜索登录数据。我希望禁用在URL中搜索这些参数。

我认为这是不可能的,因为这种行为不是由Spring实现的,也不是由JavaEE本身实现的。

HttpServletRequest.getParameter doc 指出:

将请求参数的值作为 String 返回,如果参数不存在,则返回 null。请求参数是随请求一起发送的额外信息。对于 HTTP servlet,参数包含在查询字符串或发布的表单数据中

但是您可以尝试使用应如下所示的过滤器来更改此内容:

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 Raman提出了另一种使用现有滤波器的解决方案,而不是引入新的滤波器。只有我建议覆盖而不是.obtainUsername()obtainPassword()attemptAuthentication()


答案 2

我想建议一个基于弹簧安全评级器的替代方案,然后按照chimmi的建议提出解决方法。

这个答案也为xenterosbres26答案上提出的问题提供了解决方案。

覆盖现有的用户名密码身份验证过滤器实现

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!");

        }
    }

 }

您需要将自己的实现替换为现有实现(请参阅此处的文档)

@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评论并覆盖了getiveUsername和getpassword
您可以在github中找到源代码。


推荐