這是 Spring Security 配置的典型部分:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().and().cors().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/login", "/api/v1/auth/**").permitAll();
http.authorizeRequests().anyRequest().authenticated();
}
我有問題http.authorizeRequests().anyRequest().authenticated()。
添加后,當我呼叫不存在的端點時,例如:GET: /api/v1/not-existing,我收到403而不是預期的404回應。
我想保護我的所有資源,但我想在呼叫不存在的資源時得到 404。
我該如何解決?
uj5u.com熱心網友回復:
我對這種行為沒有意見。如果用戶未通過身份驗證,何必擔心告訴他有關您系統的更多資訊。就像如果一個用戶沒有權限查看你的硬碟,為什么要讓他可以發現你的硬碟目錄樹結構。
如果真的要回傳 404,則需要自定義AuthenticationEntryPoint并AccessDeniedHandler在ExceptionTranslationFilter. 如果用戶沒有足夠的權限訪問端點(即AccessDeniedException發生),它們都會被呼叫。前者用于匿名用戶,后者用于非匿名用戶(即認證成功但沒有足夠權限的用戶)
他們的默認實作(即Http403ForbiddenEntryPoint和AccessDeniedHandlerImpl)現在都簡單地回傳 403 。您必須自定義它們,以便它們首先檢查是否有現有的端點來服務當前HttpServletRequest,如果沒有則回傳 404。您可以通過在HandlerMapping內部回圈DispatcherServlet并檢查是否有任何HandlerMapping可以處理當前HttpServletRequest.
首先創建一個執行此檢查的物件:
public class HttpRequestEndpointChecker {
private DispatcherServlet servlet;
public HttpRequestEndpointChecker(DispatcherServlet servlet) {
this.servlet = servlet;
}
public boolean isEndpointExist(HttpServletRequest request) {
for (HandlerMapping handlerMapping : servlet.getHandlerMappings()) {
try {
HandlerExecutionChain foundHandler = handlerMapping.getHandler(request);
if (foundHandler != null) {
return true;
}
} catch (Exception e) {
return false;
}
}
return false;
}
}
然后自定義AuthenticationEntryPoint并AccessDeniedHandler使用此物件進行檢查:
public class MyAccessDeniedHandler extends AccessDeniedHandlerImpl {
private HttpRequestEndpointChecker endpointChecker;
public MyAccessDeniedHandler(HttpRequestEndpointChecker endpointChecker) {
this.endpointChecker = endpointChecker;
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
if (!endpointChecker.isEndpointExist(request)) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Resource not found");
} else {
super.handle(request, response, accessDeniedException);
}
}
}
public class MyAuthenticationEntryPoint extends Http403ForbiddenEntryPoint {
private HttpRequestEndpointChecker endpointChecker;
public MyAuthenticationEntryPoint(HttpRequestEndpointChecker endpointChecker) {
this.endpointChecker = endpointChecker;
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
if (!endpointChecker.isEndpointExist(request)) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, "Resource not found");
} else {
super.commence(request, response, authException);
}
}
}
并配置它們:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DispatcherServlet dispatcherServlet;
@Autowired
private HttpRequestEndpointChecker endpointChecker;
@Override
protected void configure(HttpSecurity http) throws Exception {
..............
..............
http.exceptionHandling()
.authenticationEntryPoint(new MyAuthenticationEntryPoint(endpointChecker))
.accessDeniedHandler(new MyAccessDeniedHandler(endpointChecker));
}
@Bean
public HttpRequestEndpointChecker endpointChecker() {
return new HttpRequestEndpointChecker(dispatcherServlet);
}
}
uj5u.com熱心網友回復:
在我看來,您唯一的選擇如下:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().and().cors().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/login", "/api/v1/auth/**").permitAll();
http.authorizeRequests().antMatchers(all-your-endpoints).authenticated();
http.authorizeRequests().anyRequest().permitAll();
}
您需要all-your-endpoints使用匹配所有端點的正則運算式或多個正則運算式替換。事實上,你甚至可以擺脫,http.authorizeRequests().antMatchers("/login", "/api/v1/auth/**").permitAll();除非你真的想明確說明它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/367302.html
