簡體   English   中英

添加'Authorization'標頭會導致Spring Security保護允許的端點

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

所以,我在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();            

    }

}

不應保護/api/v1/notification 如果我在HTTP標頭中調用沒有Authorization: Basic abcd端點,則允許該請求,但是如果我添加Authorization: Basic abcd標頭,則會得到401 http響應代碼。

注意: Basic abcd只是隨機的,因此我的數據庫中沒有這樣的用戶

問題是,為什么在http標頭中添加Authorization...可以再次保護端點安全?

很好的問題,這可能會造成混淆,因為這意味着僅憑錯誤密碼就可以拒絕合法客戶端的頁面,而該頁面在沒有憑據的情況下世界其他地方都可以看到。

實際上,這是設計使然。 一般來說,授權系統需要先知道用戶是誰,然后再知道用戶是否可以執行X,Y或Z操作。 即使使用公共端點,當用戶處於上下文中時,端點的行為也可能會有所不同。 因此,實際上,它們是首先進行身份驗證的獨立系統:如果請求提供憑據,則框架將嘗試對用戶進行身份驗證並相應地接受或拒絕該請求。

一個選項

我意識到您沒有要求解決該問題(您可能對行為完全滿意,並且很好奇),但是您可以使用BasicAuthenticationFilter將其配置為忽略故障,僅針對該端點:

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);
        }
    }
}

然后替換DSL中的過濾器:

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

即使基本身份驗證失敗,這也將允許過濾器鏈繼續。 結果是,在身份驗證失敗的情況下,您將獲得403而不是401。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM