Adding 'Authorization' header causes Spring Security to secure a permitted endpoint

♀尐吖头ヾ 提交于 2020-12-12 09:22:23

问题


So, I have this in my WebSecurityConfigurerAdapter

public class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                // Use this configuration for endpoints starting with 'api'
                .antMatcher("/api/**")
                // Do not secure endpoints receiving callbacks
                .authorizeRequests().antMatchers(""/api/v1/notification").permitAll()
                // Allow only users with role "ROLE_API"
                .anyRequest().hasRole(Users.UserRoles.ROLE_API.role.replace("ROLE_", ""))
                .and()
                .httpBasic()
                .and()
                // Do not create any sessions
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                // Disable csrf
                .csrf().disable();            

    }

}

which should not secure /api/v1/notification. If I call that endpoint without Authorization: Basic abcd in the HTTP header the request is permitted, but if I add the Authorization: Basic abcd header, I get a 401 http response code.

NB: Basic abcd is just random so no such user is in my database

The question is why adding Authorization... in the http header makes the endpoint secured again?


回答1:


Good question, this can be kind of confusing since it means that a legitimate client, just with a bad password, could be denied a page that the rest of the world can see without credentials.

Actually, it's by design. Generally speaking, an authorization system would need to know who the user is before knowing whether the user can do X, Y, or Z operation. And even with a public endpoint, it's possible that the endpoint may behave differently when a user is in context. So, really, they are separate systems with authentication coming first: If a request presents credentials, then the framework will try and authenticate the user and accept or deny the request accordingly.

An option

I realize you didn't ask for how to address it (you may be completely satisfied with the behavior and just curious), but one thing you can do with BasicAuthenticationFilter is configure it to ignore failures, just for that endpoint:

static class IgnoreFailuresBasicAuthenticationFilter extends BasicAuthenticationFilter {
    private final BasicAuthenticationFilter everythingElse;

    public IgnoreFailuresBasicAuthenticationFilter(BasicAuthenticationFilter everythingElse) {
        super(everythingElse.getAuthenticationManager());
        this.everythingElse = everythingElse;
    }

    protected void doFilterInternal(request, response, chain) {
        if ("/api/v1/notification".equals(request.getPathInfo())) {
            super.doFilterInternal(request, response, chain);
        } else {
            this.everythingElse.doFilterInternal(request, response, chain);
        }
    }
}

And then replace the filter in the DSL:

http
    .httpBasic()
        .withObjectPostProcessor(
            new ObjectPostProcessor<BasicAuthenticationFilter>() {
                public BasicAuthenticationFilter postProcess(BasicAuthenticationFilter filter) {
                    return new IgnoreFailuresBasicAuthenticationFilter(filter);
                }
            });

What this will do is allow the filter chain to continue, even though Basic authentication failed. The consequence would be that, in the case authentication fails, you'd get a 403 instead of a 401.



来源:https://stackoverflow.com/questions/55398826/adding-authorization-header-causes-spring-security-to-secure-a-permitted-endpo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!