无法使用 Spring Boot 和 Angular 修复 CORS 问题 [重复]
Posted
技术标签:
【中文标题】无法使用 Spring Boot 和 Angular 修复 CORS 问题 [重复]【英文标题】:Unable to fix CORS issue with Spring Boot and Angular [duplicate] 【发布时间】:2020-07-19 06:15:29 【问题描述】:我是 Spring Boot 和 Angular 的新手,正在努力解决 CORS 问题。
我想实现一个全局 CORS 过滤器并尝试实现 CorsFilter、WebMvcConfigurer 并尝试使用 WebMvcConfigurerAdapter 类,但这些方法似乎都不起作用。我知道我错过了一些东西,但不知道是什么。如果有人可以在我的代码中找到解决方案,那将是很大的帮助。
如果有帮助的话,我还实现了基本身份验证并添加了该代码。
这是我的代码。
Angular API 调用
api.service.ts
import Injectable from '@angular/core';
import HttpClient, HttpHeaders from '@angular/common/http';
@Injectable(
providedIn: 'root'
)
export class ApiService
constructor(private httpClient: HttpClient)
userLogin(username: String, password: String)
let postBody =
"username" : username,
"password" : password
;
let httpOptions =
headers : new HttpHeaders(
"Content-Type" : "application/json",
"Authorization" : "Basic " + btoa('myUsername:myPassword')
)
return this.httpClient.post("http://localhost:8080/userLogin", postBody, httpOptions);
这是我的 API 代码。
MainApp.java
@SpringBootApplication
public class MainApp extends SpringBootServletInitializer
public static void main(String... str)
SpringApplication.run(MainApp.class, str);
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)
return builder.sources(MainApp.class);
Config.java
@Configuration
public class Config
@Bean
public CorsFilter corsFilter()
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
configuration.setAllowedMethods(Arrays.asList("POST"));
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
NotebookController.java
@RestController
public class NotebookController
@Autowired
IUsersRepo usersRepo;
@Autowired
INotesRepo notesRepo;
@PostMapping("userLogin")
@ResponseBody
public ResponseEntity<String> userLogin(@RequestParam("username") String username, @RequestParam("password") String password)
ObjectWriter objectWriter = new ObjectMapper().writer().withDefaultPrettyPrinter();
List<Users> usersList = usersRepo.findByUsernameEqualsAndPasswordEquals(username, password);
boolean userVerified = usersList.size() > 0 ? true : false;
HashMap<String, Boolean> outputMap = new HashMap<>();
outputMap.put("authenticated", userVerified);
String outputJson = "";
try
outputJson = objectWriter.writeValueAsString(outputMap);
catch (JsonProcessingException e)
e.printStackTrace();
outputJson = outputJson.toString();
ResponseEntity<String> response = new ResponseEntity<String>(outputJson, HttpStatus.OK);
return response;
Authentication.java
@Configuration
@EnableWebSecurity
public class Authentication extends WebSecurityConfigurerAdapter
@Autowired
AuthenticationEntryPoint authEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception
super.configure(http);
http.cors().and().csrf().disable();
//Authorise all incoming requests
http.authorizeRequests().and().httpBasic();
http.authorizeRequests().anyRequest().authenticated();
//Use AuthenticationEntryPoint to authorise username/password
http.httpBasic().authenticationEntryPoint(authEntryPoint);
@Bean
public CorsFilter corsFilter()
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowCredentials(true);
configuration.setAllowedOrigins(Collections.singletonList("*"));
configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
configuration.setAllowedMethods(Arrays.asList("POST"));
source.registerCorsConfiguration("/**", configuration);
return new CorsFilter(source);
@Bean
public BCryptPasswordEncoder getEncoder()
return new BCryptPasswordEncoder();
@Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception
String username = "myUsername";
String password = "myPassword";
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> mngConfig = authenticationManagerBuilder.inMemoryAuthentication();
mngConfig.withUser(username).password(password).roles("USER");
AuthEntryPoint.java
@Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException
super.commence(request, response, authException);
response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("HTTP Status 401: Unauthorised | " + authException.getMessage());
@Override
public void afterPropertiesSet() throws Exception
setRealmName("Online Notebook");
super.afterPropertiesSet();
请同时查看浏览器控制台。
https://imgur.com/a/hHceJDw
【问题讨论】:
imgur.com/a/hHceJDw 的图像中显示的错误消息说,“预检响应中的访问控制允许标头不允许请求标头字段“授权”” .所以你需要改变你的代码来拥有configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"))
。请不要将错误消息的屏幕截图发布到 Stack Overflow 的问题中。始终以文本形式复制并粘贴错误消息。
@sideshowbarker 非常感谢您的帮助。有效。我也会考虑你的建议。
【参考方案1】:
由于您使用的是 spring security ,因此您可以像下面这样配置 cors 和 spring security ,以便飞行前检查请求通过 spring security。
@Override
protected void configure(HttpSecurity http) throws Exception
http.cors().and()
//other configurations that you want
@Bean
CorsConfigurationSource corsConfigurationSource()
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
//or any domain that you want to restrict to
configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept","Authorization"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
//Add the method support as you like
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
您可能面临的问题是 Spring Security 不会让飞行前检查请求通过并使其失败。如需更多分析,请分享您的浏览器日志或请求中的错误。
从浏览器错误中可以看出,cors 配置不允许您添加到请求的标头 "Authorization"
,因为您在 cors 配置中仅指定了标头 "Origin", "Content-Type", "Accept"
。将 "Authorization"
标头也添加到 cors 配置中,问题应该得到解决。
【讨论】:
我按照您的建议进行了尝试,但仍然遇到同样的错误。我已按照建议更新了 Authentication.java 文件,并在问题中也对其进行了更新。我还在最后添加了浏览器输出。 我也尝试删除 csrf 安全,但效果不佳。 @ChiranjeevJain 将授权标头添加到configuration.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
,它将解决您的问题以上是关于无法使用 Spring Boot 和 Angular 修复 CORS 问题 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
使用 spring-boot:1.5.1 和 spring-cloud-stream 时无法启动 bean 'inputBindingLifecycle'
使用 Gradle 和 Spring Boot 时无法发布到本地 maven 存储库
无法使用 Spring Boot 和 Angular 修复 CORS 问题 [重复]
无法使用 Spring Boot 和 MVC 找到/渲染 JSP 文件
无法将 Spring Data MongoDB + Spring Data JPA 与 Spring Boot 一起使用