У меня есть внутренний сервер, созданный на Java с Spring Boot, Security и Web, и клиент, созданный с помощью Angular.
В настоящее время я пытаюсь сделать простой запрос под localhost:8080/resource.
Контроллер для этого адреса показан ниже:
@RestController
public class IndexController {
@CrossOrigin
@RequestMapping("/resource")
public Map<String, Object> home() {
Map<String, Object> model = new HashMap<String, Object>();
model.put("id", UUID.randomUUID().toString());
model.put("content", "Hello World");
return model;
}
}
А клиент Angular (та часть, которая выполняет запрос) таков:
import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
public title = "Security Client";
public greeting = {};
constructor(private http: HttpClient) {
http.get("http://localhost:8080/resource").subscribe(data => this.greeting = data);
}
}
Проблема с использованием только того, что было показано, заключается в том, что я получаю ошибку CORS.
Будь то удаление Spring Security с моего pom.xml или добавление этой конфигурации:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/resource").permitAll();
}
}
Решает проблему.
Я хочу знать, почему я получаю ошибку CORS вместо 401 Unauthorized при доступе к адресу, который требует аутентификации пользователя.




Согласно документации по весенней загрузке:
For security reasons, browsers prohibit AJAX calls to resources outside the current origin. For example, you could have your bank account in one tab and evil.com in another. Scripts from evil.com should not be able to make AJAX requests to your bank API with your credentials — for example withdrawing money from your account!
Cross-Origin Resource Sharing (CORS) is a W3C specification implemented by most browsers that lets you specify what kind of cross-domain requests are authorized, rather than using less secure and less powerful workarounds based on IFRAME or JSONP.
Вы получаете эту ошибку, потому что вам нужно добавить фильтр в конфигурацию безопасности. В конфигурации добавьте:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors()
.and()
.authorizeRequests().antMatchers("/resource").permitAll();
}
В этот же файл следует добавить:
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH",
"DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type",
"x-auth-token"));
configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
Это отлично работает для меня.
Я предполагаю, что это происходит из-за того, что фильтр cors обрабатывается перед фильтром аутентификации.
What I wanna know is why I am getting an CORS error instead of a 401 Unauthorized when accessing an address that demands user authentication.
Вы получаете эту ошибку, потому что перед вашим фактическим запросом (POST, GET...) браузер выполняет предварительный запрос (ОПЦИИ), чтобы проверить, действительно ли вызываемый сервер может обрабатывать запросы CORS.
Во время этого запроса Access-Control-Request-Method и Access-Control-Request-Header проверяются, и в заголовок добавляется некоторая другая информация.
Вы получаете ошибку CORS, потому что ваш фактический запрос даже не выполнен, если проверка CORS не удалось по запросу OPTIONS.
Вы можете проверить блок-схему того, как работает проверка CORS здесь
Интересным моментом является то, что вы получите статус ошибки HTTP, такой как 401, только во время предполетного запроса, когда сервер не авторизован для ответа на запрос OPTIONS.
Но почему без него я получаю ошибку CORS вместо 401?