簡體   English   中英

我可以混合使用基本身份驗證和 JWT 令牌身份驗證來保護單個 Spring 引導項目的 API 嗎?

[英]Can I mix both basic authentication and JWT token authentication to protect APIs of a single Spring Boot project?

我是 Spring Security 的新手,我正在開發一個 Spring 引導項目,該項目使用基本身份驗證來保護某些 API。 我從一個現有的教程代碼(一個 Udemy 課程)開始,試圖將其適應我自己的用例。

在這個項目中,我有這個SecurityConfiguration用於配置基本身份驗證。

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
    private static String REALM = "REAME";
    
    private static final String[] USER_MATCHER = { "/api/utenti/cerca/**"};
    private static final String[] ADMIN_MATCHER = { "/api/utenti/inserisci/**", "/api/utenti/elimina/**" };

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
            http.csrf().disable()
                .authorizeRequests()
                .antMatchers(USER_MATCHER).hasAnyRole("USER")
                .antMatchers(ADMIN_MATCHER).hasAnyRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .httpBasic().realmName(REALM).authenticationEntryPoint(getBasicAuthEntryPoint()).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
    
    @Bean
    public AuthEntryPoint getBasicAuthEntryPoint()
    {
        return new AuthEntryPoint();
    }

    /* To allow Pre-flight [OPTIONS] request from browser */
    @Override
    public void configure(WebSecurity web) 
    {
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder()
    {
        return new BCryptPasswordEncoder();
    };

    @Bean
    @Override
    public UserDetailsService userDetailsService()
    {
        UserBuilder users = User.builder();

        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        manager.createUser(users
                .username("ReadUser")
                .password(new BCryptPasswordEncoder().encode("BimBumBam_2018"))
                .roles("USER").build());

        manager.createUser(users
                .username("Admin")
                .password(new BCryptPasswordEncoder().encode("MagicaBula_2018"))
                .roles("USER", "ADMIN").build());

        return manager;
    }
}

所以據我了解:

這里定義了普通用戶可以訪問的 API 列表和管理員用戶可以訪問的 API 列表:

private static final String[] USER_MATCHER = { "/api/utenti/cerca/**"};
private static final String[] ADMIN_MATCHER = { "/api/utenti/inserisci/**", "/api/utenti/elimina/**" };

Into the previous configure() method basically it is stating that the API URL matching with the USER_MATCHER are accessible by logged user having role USER while API having URL matching ADMIN_MATCHER are accessible by logged user having role ADMIN . 這種解釋正確嗎?

最后, UserDetailsS ervice bean 簡單地定義了兩個用戶:一個屬於USER “組”,另一個屬於USERADMIN “組”。

因此,如果我很好理解,第一個將只能訪問具有 enpoint URL /api/utenti/cerca/的 API 而第二個將能夠訪問具有端點 URL /api/的 API utenti/inserisci/ ** 和/api/ utenti/elimina/ **

我的推理正確嗎?

現在我懷疑:進入這個項目的 controller class 我定義了這個方法:

@RestController
@RequestMapping("api/users")
@Log
public class UserController {
    
    @Autowired
    UserService userService;
    
    //@Autowired
    //private BCryptPasswordEncoder passwordEncoder;
    
    //@Autowired
    //private ResourceBundleMessageSource errMessage;
    
    @GetMapping(value = "/test", produces = "application/json")
    public ResponseEntity<String> getTest() throws NotFoundException  {
        
        log.info(String.format("****** getTest() START *******"));
        
        return new ResponseEntity<String>("TEST", HttpStatus.OK);
        
    }
    
    ..............................................................................................................
    ..............................................................................................................
    ..............................................................................................................
}

如您所見,此方法處理對localhost:8019/api/users/test端點的GET請求。

這個端點 URL 不在與受保護端點相關的前兩個列表中的任何一個中(它既不在USER_MATCHER列表中,也不在ADMIN_MATCHER列表中。所以我希望這個端點沒有受到保護並且每個人都可以訪問。但是執行前面的請求使用 PostMan,我收到此錯誤消息:

HTTP Status 401 : Full authentication is required to access this resource

所以基本上在我看來,如果這個端點不屬於任何受保護的端點列表,它無論如何都會以某種方式受到保護(在我看來,至少用戶必須經過身份驗證(事實上嘗試前一個用戶我可以獲得預期的output,所以這應該意味着端點不受用戶規則的保護,但它受到保護而不是經過身份驗證的訪問)。

為什么? 也許它取決於以前的configure()方法設置,特別是這一行?

.anyRequest().authenticated()

如果有可能以某種方式禁用來實現這樣的事情:

  • 如果被調用端點屬於前兩個列表之一( USER_MATCHERADMIN_MATCHER )--> 用戶必須經過身份驗證並且需要具有正確的角色。

  • 如果一個被調用的端點不屬於前面的列表之一 --> 每個人都可以訪問,也不是經過身份驗證的用戶。

這種方法有意義還是我失去了什么?

我借此機會還問您另一個信息:您是否認為可以配置此特定項目的 Spring 安全性,以使用基本身份驗證保護某些特定端點,並使用 JWT 身份驗證保護一些其他特定端點。

Sone 進一步注釋以解釋為什么最后一個問題。 該項目是一個微服務,目前被另一個微服務使用(用於生成 JWT 令牌)以獲取用戶信息。 (另一個微服務調用此項目的 API 以接收用戶信息,因此它可以生成將在我的應用程序中使用的 JWT 令牌。這兩個微服務之間的通信必須使用基本身份驗證)。

由於該項目包含用於 map 的所有實體類,這些表與我的數據庫上的用戶相關,我的想法是將該項目也用於通用用戶管理,因此它可以包括以下功能:添加一個全新的用戶,更改現有用戶、獲取所有用戶列表、搜索特定用戶等。

這些新的 API 將受到 JWT 令牌的保護,因為每個 API 都可以從在系統上具有不同權限的特定用戶類型調用。

所以我問在這種情況下是否可以毫無問題地添加 2 種不同類型的身份驗證(檢索用戶的 API 的基本身份驗證,以便其他微服務可以獲取此信息)和所有其他 API 的 JWT 身份驗證。 為新的用戶管理微服務創建一個全新的項目是有意義的還是更好?

因此,如果我很好理解,第一個將只能訪問具有端點 URL /api/utenti/cerca/** 的 API,而第二個將能夠訪問具有端點 URL /api/ 的 API utenti/inserisci/** 和 /api/utenti/elimina/**

是的。

為什么? 也許它取決於以前的 configure() 方法設置,特別是這一行?

是的,當使用.anyRequest().authenticated()時,任何未匹配的請求都必須進行身份驗證。

如果一個被調用的端點不屬於前面的列表之一 --> 每個人都可以訪問,也不是經過身份驗證的用戶。

您可以通過執行anyRequest().permitAll()來實現這一點。 但這不是很安全,因為您允許訪問所有其他端點,相反,您應該使用anyRequest().authenticated()並允許手動訪問特定端點,如下所示:

http
                .authorizeRequests()
                .antMatchers(USER_MATCHER).hasAnyRole("USER")
                .antMatchers(ADMIN_MATCHER).hasAnyRole("ADMIN")
                .antMatchers("/api/users/test").permitAll()
                .anyRequest().authenticated()
                ...

暫無
暫無

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

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