Issue
I am using Spring 2.6.6 and Reactjs for frontend. I have a POST endpoint exposed using a rest controller but is is giving CORS error when api is called
Below is the rest controller
@RestController
@CrossOrigin(origins = "http://localhost:3000", allowedHeaders = "*")
@RequestMapping("/image")
public class ImageUpload {
@Autowired
private ExtractData extractData;
@Autowired
private Gson gson;
@PostMapping("/extract")
public Map<String, ArrayList<String>> upload(
@RequestParam(value = "image") MultipartFile image,
@RequestParam(value = "selectedOptions") String selectedOptions
) throws IOException, TesseractException {
Map<String, Boolean> selectedOptionsMap = gson.fromJson(selectedOptions, Map.class);
byte[] imageData = image.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
try {
BufferedImage bufferedImage = ImageIO.read(bais);
Map<String, ArrayList<String>> resultSet = new HashMap<String, ArrayList<String>>();
resultSet = extractData.extractData(selectedOptionsMap, bufferedImage);
return resultSet;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Also implemented WebMvcConfigurer as follows but this also didn't work:
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/image/**")
.allowedOrigins("http://localhost:3000")
.allowedMethods("GET", "POST")
.allowedHeaders("*")
.allowCredentials(false).maxAge(3600);
}
}
My security configuration class
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService myUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Request headers:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: keep-alive
Content-Length: 110239
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryX8BGweBFqsM2R7hy
Host: localhost:8080
Origin: http://localhost:3000
Referer: http://localhost:3000/
sec-ch-ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36
Response headers:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Connection: keep-alive
Content-Length: 0
Date: Sun, 03 Jul 2022 13:37:57 GMT
Expires: 0
Keep-Alive: timeout=60
Pragma: no-cache
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
Also adding CORS filter implementation did not work
Solution
I was missing http.cors() in the security configuration Changing the configure method as follows solved the problem
@Override
public void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
Answered By - GenZ Dev
Answer Checked By - Senaida (JavaFixing Volunteer)