简体   繁体   English

Spring安全性:添加定制过滤器时,不允许访问资源

[英]Spring security: Cannot permit access to resource when adding custom filter

I have following configuration for my spring security 我的弹簧安全性具有以下配置

http
    // if I gonna comment adding filter it's gonna work as expected
    .addFilterBefore(tokenAuthenticationFilter, BasicAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/rest/_health")
            .permitAll()

            .anyRequest()
            .authenticated()

            .and()
            .csrf()
            .disable();

So without custom filter everything works as expected - I have access to /rest/_health and access denied to everything else. 因此,如果没有自定义过滤器,一切都会按预期工作-我可以访问/ rest / _health,但不能访问其他任何东西。

But when I'm adding this filter - matchers don't work and filter works even for 'permitAll' resources. 但是,当我添加此过滤器时-匹配器不起作用,即使对于'permitAll'资源,过滤器也可以工作。

Code from my filter looks like this: 来自我的过滤器的代码如下所示:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    try {
        String token = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);

        Authentication authentication = authenticationManager.authenticate(
                new TokenBasedAuthentication(token)
        );

        SecurityContextHolder.getContext().setAuthentication(authentication);

        chain.doFilter(request, response);
    } catch (AuthenticationException ex) {
        authenticationEntryPoint.commence(httpRequest, httpResponse, ex);
    }
}

Any suggestions? 有什么建议么?

In my configuration (that extends WebSecurityConfigurerAdapter), I did it in this way: 在我的配置(扩展了WebSecurityConfigurerAdapter)中,我是通过以下方式完成的:

        http.csrf().disable().
            addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
            .antMatchers("/login*", "/logout*").permitAll().anyRequest()
            .authenticated()
        .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/secured/index")
                .failureUrl("/login?error=true").permitAll()
        .and()
            .logout()
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .deleteCookies("JSESSIONID")
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login")
                .permitAll();

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/static/**", "/webjars/**", "/error*");
}

Maybe not perfect, but it works. 也许并不完美,但它确实有效。

The filter is executed before the checks on the endpoints. 在检查端点之前执行过滤器。 In your case the unsuccesful authentication aborts the filter chain and let the access point handle the rest. 在您的情况下,不成功的身份验证将中止筛选器链,并让访问点处理其余部分。 Whith this you do not allow anonymous access at all. 您根本不允许匿名访问。 You need to set the Authentication to null to indicate that an anonymous user is accessing the endpoint. 您需要将Authentication设置为null,以指示匿名用户正在访问端点。

Try the following: 请尝试以下操作:

    Authentication authentication = null;
    String token = httpRequest.getHeader(HttpHeaders.AUTHORIZATION);
    //check if not anonymous and preceed with authentication
    if (token != null && !token.isEmpty()) {
        try {

            authentication = authenticationManager.authenticate(
                new TokenBasedAuthentication(token));

        } catch (AuthenticationException ex) {
            //illigal access atempt
            authenticationEntryPoint.commence(httpRequest, httpResponse, ex);
        }
    }
    SecurityContextHolder.getContext().setAuthentication(authentication);
    chain.doFilter(request, response);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM