Reputation: 515
I have a Spring boot application with a rest controller and an Angular application as frontend. For the moment they are both running in localhost and SpringSecurity is enabled is Spring. Originally I was unable the make a getRequest from Angular to Spring because of Cors. I added @CrossOrigin to my restContoller and now I'm able to do a Get request from angular to Spring. Now I have the same problem with post request. I want to send some form data from angular to Spring but I always get an error in Chrome. I added @CrossOrigin here as well but I still have the problem. If I try a post request with postmen it's working just fine
zone.js:3243 Access to XMLHttpRequest at 'localhost:8080/rest/contact' from origin 'http://localhost:4200' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
contact.component.ts:51 HttpErrorResponse {headers: HttpHeaders, status: 0, statusText: "Unknown Error", url: "localhost:8080/rest/contact", ok: false, …}
This is my security configuration:
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure (AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors();
http
.authorizeRequests()
.antMatchers("/admin/**").authenticated()//.hasAnyRole("ADMIN","USER")
.and().formLogin().loginPage("/login").permitAll()
.and().logout();
http.csrf().disable();
//http.headers().frameOptions().disable();
}
private PasswordEncoder getPasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return encode(charSequence).equals(s);
}
};
}
}
My Cors configuration:
@Configuration
public class CorsConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
My rest controller:
@RestController()
@CrossOrigin(origins = "http://localhost:4200/**", maxAge = 3600)
public class GymRestController {
private final GymRepository gymRepository;
GymRestController (GymRepository gymRepository) {
this.gymRepository = gymRepository;
}
@GetMapping("/rest/gyms")
public List<Gym> findAll() {
return gymRepository.findAll();
}
@PostMapping ("/rest/contact")
public void submitContact(@RequestBody ContactForm contactForm) {
System.out.println(contactForm);
}
}
and my on submit method in angular
onSubmit() {
this.submitted = true;
if (this.messageForm.invalid) {
return;
}
this.success = true;
this.contactModel.fromName = this.messageForm.get('name').value;
this.contactModel.fromMail = this.messageForm.get('email').value;
this.contactModel.subject = this.messageForm.get('subject').value;
this.contactModel.message = this.messageForm.get('message').value;
let url = "http://localhost:8080/rest/contact";
// let url = "https://cors.io/?localhost:8080/rest/contact"
this.http.post(url, this.contactModel).subscribe(
res => console.log("success"),
error => console.log(error),
() => console.log("complete")
);
}
I've been trying for 3 days to get this working without any luck Any help would be appreciated
Upvotes: 5
Views: 9148
Reputation: 515
I finally found the solution. I had to enable cors in Spring Security and disable csrf
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.authorizeRequests()
.antMatchers("/admin/**").authenticated()//.hasAnyRole("ADMIN","USER")
.and().formLogin().loginPage("/login").permitAll()
.and().logout();
http.csrf().disable();
http.headers().frameOptions().disable();
}
I had to removed @CrossOrigin from the controller and I added the following configuration:
@Configuration
public class CorsConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("http://localhost:4200");
}
};
}
}
Upvotes: 5
Reputation: 677
Following on Spring io link : https://spring.io/blog/2015/06/08/cors-support-in-spring-framework
If you are using Spring Boot, it is recommended to just declare a WebMvcConfigurer bean as following:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
You can easily change any properties, as well as only apply this CORS configuration to a specific path pattern:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://domain2.com")
.allowedMethods("PUT", "DELETE","POST")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
Above you can replace http://domain2.com with your localhost or required host/url.
Upvotes: 0