![](/img/trans.png)
[英]Can I have two Spring Security configuration classes: one that protect some API with basic authentication and another protecting APIs with JWT token?
[英]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 “組”,另一個屬於USER和ADMIN “組”。
因此,如果我很好理解,第一個將只能訪問具有 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_MATCHER和ADMIN_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.