My server application built with springboot keeps giving CORS error, I have tried all I can and even downgraded the to java 11 from java 17 but still not working.
I keep getting this when i try to test with safari console.
[blocked] The page at https://www.google.com/?client=safari&channel=mac_bm was not allowed to display insecure content from http://localhost:3000/api/v1/userapi/auth/app-status.
and this
Not allowed to request resource
and this
Fetch API cannot load http://localhost:3000/api/v1/userapi/auth/app-status due to access control checks.
here is a sample of my web security configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final TokenProvider tokenProvider;
private final CustomAuthenticationProvider customAuthenticationProvider;
private final UserModelDetailsService userModelDetailsService;
private final MyCORSFilter corsFilter;
private final JwtAuthenticationEntryPoint authenticationErrorHandler;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new DBAuthenticationProvider(userModelDetailsService));
auth.authenticationProvider(customAuthenticationProvider);
}
#Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js", "/h2-console/**");
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().cors().configurationSource(corsConfigurationSource()).and()
.addFilterBefore(corsFilter, ChannelProcessingFilter.class)
.exceptionHandling()
.authenticationEntryPoint(authenticationErrorHandler)
.accessDeniedHandler(jwtAccessDeniedHandler)
.and()
.headers()
.frameOptions()
.sameOrigin()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/", "/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js", "/h2-console/**").permitAll()
.antMatchers("/documentation/**", "/swagger-resources/**", "/v3/**", "/swagger-ui.html", "/swagger-ui/**").permitAll()
.anyRequest().authenticated()
.and()
.apply(securityConfigurerAdapter());
}
private JWTConfigurer securityConfigurerAdapter() {
return new JWTConfigurer(tokenProvider);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*");
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
and also i tried using custom filter, still did not work.
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCORSFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
System.out.println("i am here 000");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PATCH, PUT, HEAD");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "*");
if ("OPTIONS".equals(request.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
I created spring boot service using with Keycloak. And I implemented login end-point. When I logged in the service over Postman, I can connect to keycloak and take token. And I can use this token on other request calls succesfully. When I logged in it with angular I still the token but request returns 403 error every time in spring boot. When I use the same token in postman, there is no problem.
KeycloakSecurityConfig
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Value("${server.servlet.context-path}")
public String contextPath;
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**",
"/auth/login").permitAll()
.anyRequest().authenticated()
.and().cors()
.and().csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Bean
#Override
protected KeycloakAuthenticationProcessingFilter keycloakAuthenticationProcessingFilter() throws Exception {
KeycloakAuthenticationProcessingFilter filter = new KeycloakAuthenticationProcessingFilter(this.authenticationManagerBean());
filter.setSessionAuthenticationStrategy(this.sessionAuthenticationStrategy());
filter.setAuthenticationFailureHandler(new CustomKeycloakAuthenticationFailureHandler());
return filter;
}
#Bean
public KeycloakConfigResolver keycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
application.yaml
keycloak:
realm: <realm_name>
auth-server-url: http://localhost:8287/auth/
resource: mm-service-1
credentials:
secret: bla-bla-bla
use-resource-role-mappings: false
cors: true
bearer-only: true
enabled: true
public-client: true
JwtInteceptor
#Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private accountService: AccountService) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add account header with jwt if user is logged in and request is to the api url
const user = this.accountService.userValue;
const isLoggedIn = user && user.token;
const isApiUrl = request.url.startsWith(Constants.SERVER_BASE_PATH);
console.log('REQUEST: ', request);
if (isLoggedIn && isApiUrl) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${user.token}`,
'withCredentials': `true`,
'Access-Control-Allow-Credentials': `true`,
}
});
}
console.log('NEW REQUEST: ', request);
return next.handle(request);
}
}
Get request on Angular
getListMachine(): void {
this.machineApi.listMachine(null, null, null, null, null, 'response')
.pipe(takeUntil(this.unsubscribeAll))
.subscribe((res: any) => {
const resHeader = res.headers;
this.totalRows = resHeader.get('X-Total-Count');
this.machineInfos = res.body;
}, (err) => {
console.error('Err:', err);
});
}
Origin Config
#Configuration
public class ApiOriginCorsConfigurer {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS")
.allowedOriginPatterns("*")
.exposedHeaders(
"Content-Type",
"Accept",
"Authorization",
"link",
"content-range",
"x-total-count",
"location",
"etag",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Credentials")
.allowedHeaders("*")
.allowCredentials(true)
;
}
};
}
}
Postman request
Angular Request
Finally, I found problem. I disabled cors of the keycloak and it works. But When I want to use cors, I don't know what to do.
If i were you i will add this line logging.level.org.springframework.security=debug to application.properties and then observe the behavior of your app with CORS or without it.
Hope that will help you.
If the same token works in postman; probably angular application is the problem.
Check your "Authorization" header in request with angular
I am trying to call REST endpoints on one application (spring-boot application) from another (angularjs). The applications are running on the following hosts and ports.
REST application, using spring boot, http://localhost:8080
HTML application, using angularjs, http://localhost:50029
I am also using spring-security with the spring-boot application. From the HTML application, I can authenticate to the REST application, but, thereafter, I still cannot access any REST endpoint. For example, I have an angularjs service defined as follows.
adminServices.factory('AdminService', ['$resource', '$http', 'conf', function($resource, $http, conf) {
var s = {};
s.isAdminLoggedIn = function(data) {
return $http({
method: 'GET',
url: 'http://localhost:8080/api/admin/isloggedin',
withCredentials: true,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
};
s.login = function(username, password) {
var u = 'username=' + encodeURI(username);
var p = 'password=' + encodeURI(password);
var r = 'remember_me=1';
var data = u + '&' + p + '&' + r;
return $http({
method: 'POST',
url: 'http://localhost:8080/login',
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
};
return s;
}]);
The angularjs controller looks like the following.
adminControllers.controller('LoginController', ['$scope', '$http', 'AdminService', function($scope, $http, AdminService) {
$scope.username = '';
$scope.password = '';
$scope.signIn = function() {
AdminService.login($scope.username, $scope.password)
.success(function(d,s) {
if(d['success']) {
console.log('ok authenticated, call another REST endpoint');
AdminService.isAdminLoggedIn()
.success(function(d,s) {
console.log('i can access a protected REST endpoint after logging in');
})
.error(function(d, s) {
console.log('huh, error checking to see if admin is logged in');
$scope.reset();
});
} else {
console.log('bad credentials?');
}
})
.error(function(d, s) {
console.log('huh, error happened!');
});
};
}]);
On the call to http://localhost:8080/api/admin/isloggedin, I get a 401 Unauthorized.
On the REST application side, I have a CORS filter that looks like the following.
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class CORSFilter implements Filter {
#Override
public void destroy() { }
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:50029");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Auth-Token");
response.setHeader("Access-Control-Allow-Credentials", "true");
if(!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig config) throws ServletException { }
}
My spring security configuration looks like the following.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
private JsonAuthSuccessHandler jsonAuthSuccessHandler;
#Autowired
private JsonAuthFailureHandler jsonAuthFailureHandler;
#Autowired
private JsonLogoutSuccessHandler jsonLogoutSuccessHandler;
#Autowired
private AuthenticationProvider authenticationProvider;
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private PersistentTokenRepository persistentTokenRepository;
#Value("${rememberme.key}")
private String rememberMeKey;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/", "/admin", "/css/**", "/js/**", "/fonts/**", "/api/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(jsonAuthSuccessHandler)
.failureHandler(jsonAuthFailureHandler)
.permitAll()
.and()
.logout()
.deleteCookies("remember-me", "JSESSIONID")
.logoutSuccessHandler(jsonLogoutSuccessHandler)
.permitAll()
.and()
.rememberMe()
.userDetailsService(userDetailsService)
.tokenRepository(persistentTokenRepository)
.rememberMeCookieName("REMEMBER_ME")
.rememberMeParameter("remember_me")
.tokenValiditySeconds(1209600)
.useSecureCookie(false)
.key(rememberMeKey);
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(authenticationProvider);
}
}
All the handlers are doing is writing out a JSON response like {success: true} based on if the user logged in, failed to authenticate, or logged out. The RestAuthenticationEntryPoint looks like the following.
#Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException ex)
throws IOException, ServletException {
resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
Any ideas on what I am missing or doing wrong?
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class SimpleCORSFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
public SimpleCORSFilter() {
log.info("SimpleCORSFilter init");
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
No need extra define this filter just add this class. Spring will be scan and add it for you. SimpleCORSFilter.
Here is the example: spring-enable-cors
I had been into the similar situation. After doing research and testing, here is my findings:
With Spring Boot, the recommended way to enable global CORS is to declare within Spring MVC and combined with fine-grained #CrossOrigin configuration as:
#Configuration
public class CorsConfig {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
.allowedHeaders("*");
}
};
}
}
Now, since you are using Spring Security, you have to enable CORS at Spring Security level as well to allow it to leverage the configuration defined at Spring MVC level as:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
Here is very excellent tutorial explaining CORS support in Spring MVC framework.
UPDATE (Sep 13, 2022):
With latest version of Spring 5 and above, you have to use WebMvcConfigurer as below:
#EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
}
}
If you want to enable CORS without using filters or without config file just add
#CrossOrigin
to the top of your controller and it work.
To build on other answers above, in case you have a Spring boot REST service application (not Spring MVC) with Spring security, then enabling CORS via Spring security is enough (if you use Spring MVC then using a WebMvcConfigurer bean as mentioned by Yogen could be the way to go as Spring security will delegate to the CORS definition mentioned therein)
So you need to have a security config that does the following:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
//other http security config
http.cors().configurationSource(corsConfigurationSource());
}
//This can be customized as required
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
List<String> allowOrigins = Arrays.asList("*");
configuration.setAllowedOrigins(allowOrigins);
configuration.setAllowedMethods(singletonList("*"));
configuration.setAllowedHeaders(singletonList("*"));
//in case authentication is enabled this flag MUST be set, otherwise CORS requests will fail
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
This link has more information on the same: https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors
Note:
Enabling CORS for all origins (*) for a prod deployed application may not always be a good idea.
CSRF can be enabled via the Spring HttpSecurity customization without any issues
In case you have authentication enabled in the app with Spring (via a UserDetailsService for example) then the configuration.setAllowCredentials(true); must be added
Tested for Spring boot 2.0.0.RELEASE (i.e., Spring 5.0.4.RELEASE and Spring security 5.0.3.RELEASE)
Im using spring boot 2.1.0 and what worked for me was to
A. Add cors mappings by:
#Configuration
public class Config implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
}
B. Add below configuration to my HttpSecurity for spring security
.cors().configurationSource(new CorsConfigurationSource() {
#Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Collections.singletonList("*"));
config.addAllowedOrigin("*");
config.setAllowCredentials(true);
return config;
}
})
Also in case of a Zuul proxy you can use this INSTEAD OF A and B (just use HttpSecurity.cors() to enable it in Spring security):
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
This works for me:
#Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
//...
#Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.cors().configurationSource(new CorsConfigurationSource() {
#Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Collections.singletonList("*"));
config.addAllowedOrigin("*");
config.setAllowCredentials(true);
return config;
}
});
//...
}
//...
}
This is what worked for me.
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors();
}
}
#Configuration
public class WebConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedMethods("*")
.allowedHeaders("*")
.allowedOrigins("*")
.allowCredentials(true);
}
}
For me the only thing that worked 100% when spring security is used was to skip all the additional fluff of extra filters and beans and whatever indirect "magic" people kept suggesting that worked for them but not for me.
Instead just force it to write the headers you need with a plain StaticHeadersWriter:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
// your security config here
.authorizeRequests()
.antMatchers(HttpMethod.TRACE, "/**").denyAll()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and().httpBasic()
.and().headers().frameOptions().disable()
.and().csrf().disable()
.headers()
// the headers you want here. This solved all my CORS problems!
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", "*"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "POST, GET"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Max-Age", "3600"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Credentials", "true"))
.addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization"));
}
}
This is the most direct and explicit way I found to do it. Hope it helps someone.
Step 1
By annotating the controller with #CrossOrigin annotation will allow the CORS configurations.
#CrossOrigin
#RestController
public class SampleController {
.....
}
Step 2
Spring already has a CorsFilter even though You can just register your own CorsFilter as a bean to provide your own configuration as follows.
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); // Provide list of origins if you want multiple origins
config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
config.setAllowCredentials(true);
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
If originally your program doesn't use spring security and can't afford for a code change, creating a simple reverse proxy can do the trick. In my case, I used Nginx with the following configuration:
http {
server {
listen 9090;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
#
# Tell client that this pre-flight info is valid for 20 days
#
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
proxy_pass http://localhost:8080;
}
}
}
My program listens to :8080.
REF: CORS on Nginx
In our Spring Boot app, we have set up CorsConfigurationSource like this.
Sequence of adding allowedOrigns first and then setting applyPermitDefaultValues() let Spring set up default values for allowed headers, exposed headers, allowed methods, etc. so we don't have to specify those.
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:8084"));
configuration.applyPermitDefaultValues();
UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
configurationSource.registerCorsConfiguration("/**", configuration);
return configurationSource;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**")
.access("#authProvider.validateApiKey(request)")
.anyRequest().authenticated()
.and().cors()
.and().csrf().disable()
.httpBasic().authenticationEntryPoint(authenticationEntryPoint);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
check this one:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
...
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
...
}
Extending WebSecurityConfigurerAdapter class and overriding configure() method in your #EnableWebSecurity class would work : Below is sample class
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf().disable()
.exceptionHandling();
http.headers().cacheControl();
#Override
public CorsConfiguration getCorsConfiguration(final HttpServletRequest request) {
return new CorsConfiguration().applyPermitDefaultValues();
}
});
}
}
This answer copies the #abosancic answer but adds extra safety to avoid CORS exploit.
Tip 1: Do not reflect the incoming Origin as is without checking the list of allowed hosts to access.
Tip 2: Allow credentialed request only for whitelisted hosts.
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
#Component
public class SimpleCORSFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
private List<String> allowedOrigins;
public SimpleCORSFilter() {
log.info("SimpleCORSFilter init");
allowedOrigins = new ArrayList<>();
allowedOrigins.add("https://mysafeorigin.com");
allowedOrigins.add("https://itrustthissite.com");
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String allowedOrigin = getOriginToAllow(request.getHeader("Origin"));
if(allowedOrigin != null) {
response.setHeader("Access-Control-Allow-Origin", allowedOrigin);
response.setHeader("Access-Control-Allow-Credentials", "true");
}
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
public String getOriginToAllow(String incomingOrigin) {
if(allowedOrigins.contains(incomingOrigin.toLowerCase())) {
return incomingOrigin;
} else {
return null;
}
}
}
Just Make a single class like, everything will be fine with this:
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class MyCorsConfig implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, enctype");
response.setHeader("Access-Control-Max-Age", "3600");
if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(req, res);
}
}
#Override
public void destroy() {
}
#Override
public void init(FilterConfig config) throws ServletException {
}
}
This is what has worked for me in order to disable CORS between Spring boot and React
#Configuration
public class CorsConfig implements WebMvcConfigurer {
/**
* Overriding the CORS configuration to exposed required header for ussd to work
*
* #param registry CorsRegistry
*/
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(4800);
}
}
I had to modify the Security configuration also like below:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.cors().configurationSource(new CorsConfigurationSource() {
#Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Collections.singletonList("*"));
config.addAllowedOrigin("*");
config.setAllowCredentials(true);
return config;
}
}).and()
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().authenticated()
.and().httpBasic()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().exceptionHandling().accessDeniedHandler(apiAccessDeniedHandler());
}
I was suprised to only find Eduardo Dennis pointing to the up-to-date solution which is much simpler & doesn't involve the need to write your own Filter classes: It's using the
org.springframework.web.bind.annotation.CrossOrigin annotation on your Controllers
and including and().cors() to your Spring Security configuration.
That's all you have to do!
You can use the #CrossOrigin annotation like this:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/api")
#CrossOrigin
public class BackendController {
...
}
If you want to configure allowedHeaders, methods, origins and so on, you can simply add those values to the annotation like this: #CrossOrigin(origins = "http://localhost:50029", maxAge = 3600).
Using the #CrossOrigin annotation, the Spring Security configuration becomes extremely easy. Simply add and().cors() to your WebSecurityConfig.java class:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.and().cors()
...
}
That's all! You may delete your Filter/CORSFilter classes. If you want to add a global configuration, you can declare a CorsConfigurationSource also. See this great answer or this blog post by Sébastien Deleuze). There's also clearly stated by the Spring developers:
This approach supersedes the filter-based approach previously
recommended.
Therefore the accepted answer is outdated. Here's also a fully working example project: https://github.com/jonashackt/microservice-api-spring-boot
To enable CORS Globally you need to make changes in two places:
1. Spring Boot:
#Configuration
public class CorsConfiguration extends WebMvcConfigurationSupport {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedMethods("*")
.allowCredentials(true);
}
}
You can do the same in WebMvcConfigurerAdapter, or create bean of WebMvcConfigurer.
2. Spring Security
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll() //Permits your preflight request
}
Works as on Spring Boot 2.3.3.RELEASE
The simple way is to create a bean in your spring boot application class(class with #SpringBootApplication) as below:
Note! i specified "http://localhost:4200" below on "setAllowedOrigins()" because am running the application on localhost and using angular default port.
#Bean
public CorsFilter corsFilter(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
corsConfiguration.setAllowedHeaders(Arrays.asList("Origin","Access-Control-Allow-Origin","Content-Type",
"Accept", "Authorization", "Origin, Accept", "X-Requested-With",
"Access-Control-Request-Method", "Access-Control-Request-Headers"));
corsConfiguration.setExposedHeaders(Arrays.asList("Origin", "Content-Type", "Accept","Authorization",
"Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST","PUT","DELETE","OPTIONS"));
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
You can use this annotation on every restController class in sprıng boot
#CrossOrigin("*")
if you are using spring security you need to use this on any class with extended extends WebSecurityConfigurerAdapter
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
package tiny.url.urlshortner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#SpringBootApplication
public class UrlshortnerApplication {
public static void main(String[] args) {
SpringApplication.run(UrlshortnerApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
.allowedHeaders("*");
}
};
}
}
I know this question already spreading all over the stackoverflow, but this one quite different.
I got an error when trying to hit a java API using axios, with below way,
axios
.get("http://127.0.0.1:8090/api/v1/homescreen")
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
}
Axios configuration were
axios.defaults.headers.common['Content-Type'] =
'application/x-www-form-urlencoded';
axios.defaults.headers.common['Authorization'] = 'Bearer
eyJhbGciOiJIUzI1N';
axios.defaults.headers.common['Ack'] = 'MTIwNzIwMjBL==' ;
Already tried with axios.defaults.headers.common['Content-Type'] = application/json; and got the same error.
The error was
Access to XMLHttpRequest at 'http://127.0.0.1:8090/api/v1/homescreen'
from origin 'http://localhost:8080' has been blocked by CORS policy:
Request header field ack is not allowed by
Access-Control-Allow-Headers in preflight response.
Now in the server side i already configure it like this
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#Order(Ordered.LOWEST_PRECEDENCE)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
public SecurityConfig() {
super();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.cors().configurationSource(corsConfigurationSource()).and().csrf().disable()
.exceptionHandling().and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.GET, "/api/v1/cache/**").permitAll()
.antMatchers("/api/v1/**").authenticated().and().authorizeRequests()
.and().httpBasic();
}
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers",
"Access-Control-Allow-Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers",
"Origin", "Cache-Control", "Content-Type", "Authorization", "Ack", "ack", "ackwhatever", "goddamnack"));
configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS).antMatchers("/api/v1/login/*");
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
even in the spring filter i put the header allowance
public class HttpRequestAuditFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger("access");
private static final int MAX_PAYLOAD_LENGTH = 10000;
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
if ((request instanceof HttpServletRequest)
&& !(request instanceof ContentCachingRequestWrapper)) {
request = new ContentCachingRequestWrapper((HttpServletRequest) request);
}
HttpServletResponse responseQ = (HttpServletResponse) response;
HttpServletRequest requestQ = (HttpServletRequest) request;
try {
responseQ.setHeader("Access-Control-Allow-Origin", "*");
responseQ.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
responseQ.setHeader("Access-Control-Max-Age", "3600");
responseQ.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, content-type, ack, Ack");
responseQ.setHeader("Access-Control-Expose-Headers", "x-requested-with, authorization, content-type, ack, Ack");
if ("OPTIONS".equalsIgnoreCase(requestQ.getMethod())) {
responseQ.setStatus(HttpServletResponse.SC_OK);
} else {
chain.doFilter(requestQ, responseQ);
}
} finally {
if (requestQ instanceof HttpServletRequest) {
performRequestAudit((HttpServletRequest) requestQ);
}
}
}
public void performRequestAudit(HttpServletRequest httpRequest) {
ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(httpRequest, ContentCachingRequestWrapper.class);
String payload = "";
if (wrapper != null) {
byte[] requestBuffer = wrapper.getContentAsByteArray();
if (requestBuffer.length > 0) {
int length = Math.min(requestBuffer.length, MAX_PAYLOAD_LENGTH);
try {
payload = new String(requestBuffer,
0, length, wrapper.getCharacterEncoding());
} catch (UnsupportedEncodingException unex) {
payload = "[Unsupported-Encoding]";
}
}
}
LOG.trace("{}|{}", payload, wrapper.getHeaderNames());
}
}
When i try with curl i got the response even in the mobile app its work perfectly, only with browser that got error (the browser itself already --disable-web-security).
Any help and explanation will be apreciated.
Instead of providing the cors configuration class manually, let it be a bean and let spring take it up automatically, also remove the lowest order so that your configuration does not get overridden. Also remove the spring filter that you created to manually add the headers in the response as when configured correctly spring security will automatically add those headers in response. #EnableGlobalMethodSecurity can be used along with any #Configuration annotated classes but try like :
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
public SecurityConfig() {
super();
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.GET, "/api/v1/cache/**").permitAll()
.antMatchers("/api/v1/**").authenticated().and().authorizeRequests()
.and().httpBasic();
}
#Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers",
"Access-Control-Allow-Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers",
"Origin", "Cache-Control", "Content-Type", "Authorization", "Ack", "ack", "ackwhatever", "goddamnack"));
configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
#Override
public void configure(final WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS).antMatchers("/api/v1/login/*");
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(customAuthenticationProvider);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
If this doesn't work separate out the method level security configurations to another configuration class and keep the web security as a separate connfiguration.
As described in CORS preflight request fails due to a standard header if you send requests to OPTIONS endpoints with the Origin and Access-Control-Request-Method headers set then they get intercepted by the Spring framework, and your method does not get executed. The accepted solution is the use #CrossOrigin annotations to stop Spring returning a 403. However, I am generating my API code with Swagger Codegen and so I just want to disable this and implement my OPTIONS responses manually.
So can you disable the CORS interception in Spring?
For newer versions of spring boot:
#Configuration
public class WebConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
}
The Kotlin way
#Configuration
class WebConfiguration : WebMvcConfigurer {
override fun addCorsMappings(registry: CorsRegistry) {
registry.addMapping("/**").allowedMethods("*")
}
}
From their documentation:
If you are using Spring Web MVC
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
If you are using Spring Boot:
#Configuration
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
}
Yuriy Yunikov answer is correct as well. But I don't like the "custom" filter.
In case you have Spring Web Security which causes you trouble. Check this SO Answer.
Try to add a following filter (you can customize it for you own needs and methods supported):
#Component
public class CorsFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, HEAD");
response.addHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
response.addHeader("Access-Control-Expose-Headers", "Access-Control-Allow-Origin, Access-Control-Allow-Credentials");
response.addHeader("Access-Control-Allow-Credentials", "true");
response.addIntHeader("Access-Control-Max-Age", 10);
filterChain.doFilter(request, response);
}
}
I use Spring Security in my Spring Boot application and enable access from specific domains (or from all domains).
My WebSecurityConfig:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// ...
#Override
protected void configure(HttpSecurity http) throws Exception {
// add http.cors()
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers("/get/**").permitAll()
.antMatchers("/update/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.httpBasic(); // Authenticate users with HTTP basic authentication
// REST is stateless
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
// To enable CORS
#Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("https://www.yourdomain.com")); // www - obligatory
// configuration.setAllowedOrigins(ImmutableList.of("*")); //set access from all domains
configuration.setAllowedMethods(ImmutableList.of("GET", "POST", "PUT", "DELETE"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Sometimes is needed to clear browser history before testing.
Detailed information may be seen here:
http://appsdeveloperblog.com/crossorigin-restful-web-service/
Just for those who use Angular. From Angular I run requests to backend:
export class HttpService {
username = '..';
password = '..';
host = environment.api;
uriUpdateTank = '/update/tank';
headers: HttpHeaders = new HttpHeaders({
'Content-Type': 'application/json',
Authorization: 'Basic ' + btoa(this.username + ':' + this.password)
});
constructor(private http: HttpClient) {
}
onInsertTank(tank: Tank) {
return this.http.put(this.host + this.uriUpdateTank, tank, {
headers: this.headers
})
.pipe(
catchError(this.handleError)
);
}
...
}
Old version.
In my Spring Boot application no other ways worked then this:
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with, x-auth-token");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
try {
chain.doFilter(req, res);
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
System.out.println("Pre-flight");
response.setHeader("Access-Control-Allowed-Methods", "POST, GET, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "authorization, content-type,x-auth-token, " +
"access-control-request-headers, access-control-request-method, accept, origin, authorization, x-requested-with");
response.setStatus(HttpServletResponse.SC_OK);
}
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}
Try this one if you have at least Java 8:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
}
}
Previous answers almost all about ENABLING CORS, this worked for me to disable.
#Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*");
}
};
}
}
None of the above worked for me. Here is how I did it for Spring-Boot 2.6.7 and Java 18.
(I know I will have to look this up myself the next time I have to set up a spring backend again):
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
}
#Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
Spring MVC
https://docs.spring.io/spring-framework/docs/5.3.13/reference/html/web.html#mvc-cors-global-java
#Configuration(proxyBeanMethods = false)
#EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*").allowedHeaders("*");
}
}
Spring Boot
https://docs.spring.io/spring-boot/docs/2.5.7/reference/htmlsingle/#features.developing-web-applications.spring-mvc.cors
#Configuration(proxyBeanMethods = false)
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(final CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*").allowedHeaders("*");
}
};
}
}
Spring Security ( with Spring MVC or Spring Boot)
If using Spring Security, set following configuration additionally:
https://docs.spring.io/spring-security/site/docs/5.5.3/reference/html5/#cors
#Configuration(proxyBeanMethods = false)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(final HttpSecurity http) throws Exception {
// ...
// see also: https://docs.spring.io/spring-security/site/docs/5.5.3/reference/html5/#csrf-when
http.csrf().disabled();
// if Spring MVC is on classpath and no CorsConfigurationSource is provided,
// Spring Security will use CORS configuration provided to Spring MVC
http.cors(Customizer.withDefaults());
}
}
I use spring boot and this is solved my problem.
I am using React for front-end.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
public class CorsConfig extends WebMvcConfigurerAdapter {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
};
}
}