I have this service that I published on my local machine:
http://joediego.dtdns.net:3000/jcsistemas/rest/cliente/all
If I hit afromentioned URL endpoint, I can get a response with my JSON feed. But when I use another host name such as http://localhost:8081, the service responds with below message:
XMLHttpRequest can not load http: // localhost: 8081 / jcsistemas / rest / customer / all. In the 'Access-Control-Allow-Origin "header is present on the requested resource. Origin 'http: // localhost: 9000' is not allowed Therefore access.
Here is what I tried so far to overcome the same origin policy issue:
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.HttpServletResponse;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
//filter
#Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
#Configuration
#EnableWebMvc
#ComponentScan("my..package...... ")
public class WebAppConfig extends WebMvcConfigurerAdapter {
//configureContentNegotiation
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(true).
ignoreAcceptHeader(true).
useJaf(false).
defaultContentType(MediaType.APPLICATION_JSON).
mediaType("html", MediaType.TEXT_HTML).
mediaType("xml", MediaType.APPLICATION_XML);
}
}
AngualarJS Module configuration:
angular.module('my_module').config(['$routeProvider','$httpProvider',function($routeProvider,$httpProvider) {
//how configure headers here??
}]);
}());
I managed to solve my problem by removing #Component SimpleCorsFilter and adding getServletFilters() method in a WebApplicationInitializer subclass. For to those who use a Java-based application configuration, here down the component declaration:
public MyWebApplicationInitializer implements WebApplicationInitializer
{
# Override
protected Filter[] getServletFilters()
{
return new Filter[] {new MyFilter()}; // MyFilter refers to the filter needed class
}
}
Related
I'm trying to set the SameSite attribute of the JSESSIONID cookie in our JHipster gateway, and upon trying to verify in Chrome, there is nothing showing up under the SameSite column for it.
Possibly of note: we're currently not deployed and running the application locally on HTTP (a localhost address). Running in TLS mode also has the same problem, however.
These are two things I've tried in order to get this working:
The second approach from the first answer here How to enable samesite for jsessionid cookie - a filter that is used in JHipster's SecurityConfiguration.java file in the configure() method.
import java.io.IOException;
import java.util.Collection;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
public class SameSiteFilter implements javax.servlet.Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
addSameSiteCookieAttribute((HttpServletResponse) response); // add SameSite=strict cookie attribute
}
private void addSameSiteCookieAttribute(HttpServletResponse response) {
Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
boolean firstHeader = true;
for (String header : headers) { // there can be multiple Set-Cookie attributes
if (firstHeader) {
response.setHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=Strict"));
firstHeader = false;
continue;
}
response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=Strict"));
}
}
#Override
public void destroy() {
}
}
A CookieSerializer which we got from an internal partner:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.web.http.DefaultCookieSerializer;
import org.springframework.session.web.http.CookieSerializer;
#Configuration
class CookieConfiguration {
#Bean
public static CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setSameSite("Lax");
return serializer;
}
}
Neither of these work. Is there something else we can try for this particular flavor of Spring?
In case you are using Tomcat (i.e. not WebFlux), the following configuration will add SameSite=strict to all cookies, including JSESSIONID:
#Configuration
public class SameSiteCookieConfiguration implements WebMvcConfigurer {
#Bean
public TomcatContextCustomizer configureSameSiteCookies() {
return context -> {
final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
cookieProcessor.setSameSiteCookies("strict");
context.setCookieProcessor(cookieProcessor);
};
}
}
I have a problem with the config about spring-security. So I have made some configuration so far, and I am able to use all API with **GET. But none of the rest API like Delete-PUT-Post.
And for this I am getting an error like below:
The error is 403.
So my configuration is in two classes :
CorsFilter.java
package com.example.rest.webservices.restfulwebservices.basic.auth;
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;
public class CorsFilter implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException
{
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
// if (request.getMethod().equals("OPTIONS"))
// {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Content-Type, Authorization, Content-Length, X-Requested-With");
response.addHeader("Access-Control-Allow-Credentials", "true");
// }
filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void destroy()
{
}
}
and the second class is :
SpringSecurityConfigurationBasicAuth
package com.example.rest.webservices.restfulwebservices.basic.auth;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.session.SessionManagementFilter;
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter {
#Bean
CorsFilter corsFilter() {
CorsFilter filter = new CorsFilter();
return filter;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(corsFilter(), SessionManagementFilter.class);
//http.cors();
http .csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
http.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
// .formLogin().and()
.httpBasic();
}
}
My controller is as below:
ItemController
package com.example.rest.webservices.restfulwebservices.todo;
import java.net.URI;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
#CrossOrigin(origins="http://localhost:4200")
#RestController
public class ItemController {
#Autowired
private ItemService itemService;
#GetMapping(path = "/users/{username}/items")
public List<Item> getAllToDosList(#PathVariable String username){
return itemService.findAll(username);
}
#GetMapping(path = "/users/{username}/item/{id}")
public Item getItem(#PathVariable String username, #PathVariable Integer id){
return itemService.findById(id);
}
#PutMapping("/users/{username}/item/{id}")
public ResponseEntity<Item> updateItem(#PathVariable String username,
#PathVariable Integer id, #RequestBody Item item ){
Item updateditem = itemService.saveItem(item);
return new ResponseEntity<Item>(updateditem, HttpStatus.OK);
}
#PostMapping("/users/{username}/item")
public ResponseEntity<Void> addItem(#PathVariable String username, #RequestBody Item item ){
Item createdItem = itemService.saveItem(item);
URI uri = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
.buildAndExpand(createdItem.getId()).toUri();
return ResponseEntity.created(uri).build();
}
#DeleteMapping(path = "/users/{username}/item/{id}")
public ResponseEntity<Void> removeToDosFromList(#PathVariable String username,
#PathVariable Integer id){
Item todo = itemService.deleteToDoById(id);
if (todo != null)
{
return ResponseEntity.noContent().build();
}
return ResponseEntity.notFound().build();
}
}
And so far this work only for the GET API, Please have a look in the classes, maybe you have more ideas than me, as I have a lack of experience.
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
You are passing OPTIONS method in the argument which is for specifying which method to allow, only OPTIONS type request will be allowed, use GET if you want to allow get requests. If you want to allow all request types just pass "/**" as the argument, with out specifying any method type.
I think the question here is:
do you want to autenticate the user to call some of the paths?
If the answer is no, you should remove this line .anyRequest().authenticated()
if the answer is yes you should specify the urls you want to be authenticated and define the authentication method and make the call with a proper Authorization header
I'm am trying to set up an application that has an Angular front-end and a Maven/Spring Boot backend and have set up my first REST controller. My issue is that when I send a GET HTTP request to the backend from my Angular IDE it returns an error stating:
"Access to XMLHttpRequest at 'http://localhost:8080/api/getData' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I'm confused as I have set up the "doFilter" to accept all requests from any origin so it shouldn't be throwing this error. My code follows:
My APIController:
package com.SSCCoursework.controller;
import com.SSCCoursework.Model.SharePrice;
import com.SSCCoursework.Model.Shares;
import com.SSCCoursework.Model.SharesList;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#CrossOrigin (origins = "http://localhost:4200", maxAge = 3600)
#RestController
public class ApiController
{
File Shares_File = new File("Shares_Data.xml");
ArrayList<Shares> shareList = new ArrayList<Shares>();
#RequestMapping(value="/api/getData", produces="application/JSON")
public Object getData()
{
Shares share1 = new Shares();
SharePrice share1_2 = new SharePrice();
share1.setCompanyName("test");
share1.setCompanySymbol("test");
share1.setNumOfShares(123);
Date date = new Date();
share1.setLastShareUpdate(date);
share1_2.setCurrency("dollar");
share1_2.setValue(12345f);
share1.setSharePrice(share1_2);
shareList.add(share1);
SharesList sharelist = new SharesList();
sharelist.setBookList(shareList);
return share1;
}
}
My SimpleCORSFilter:
package com.SSCCoursework.Security;
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.springframework.stereotype.Component;
#Component
public class SimpleCORSFilter implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException
{
HttpServletResponse res = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, Connection, User-Agent, authorization, sw-useragent, sw-version");
if (req.getMethod().equals("OPTIONS"))
{
res.setStatus(HttpServletResponse.SC_OK);
return;
}
filterChain.doFilter(request, response);
}
#Override
public void destroy()
{
}
}
My Angular code is just trying to use a GET method (this.httpClient.get('http://localhost:8080/api/getData') to print the data to the browser console but the error is preventing it from working. Am I missing a step in my backend?
you can easily define a global cors config just by adding in your main application class where you start your spring boot app
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8080")
.allowedMethods("PUT", "DELETE", "GET", "POST");
}
};
}
for more details take a look here
I have created one app using angular and springboot for basic authentication with spring security but i am getting 401 error ..i am novice in springboot
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
.anyRequest().authenticated()
.and()
//.formLogin().and()
.httpBasic();
}
}
"Access to XMLHttpRequest at 'http://localhost:8080/hello-world/path-variable/MSD' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
I also had the same issue with angulat7 and spring boot I resolved by adding the following configuration
#Configuration
public class SpringDataRestConfiguration extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getCorsRegistry().addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("GET", "POST", "PATCH", "PUT", "DELETE");
}
}
You could try the following
At the top of the controller, you can add #CrossOrigin(origins = "*", allowedHeaders = "*") or customise if required
...
#CrossOrigin(origins = "*", allowedHeaders = "*")
#RestController
public class UserController {
// Methods
}
...
Please try above solution and let me know if this doesnt work
EDIT 1:
You could also try to create a filter with CORS options:
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.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
#Component
#Order(1)
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", "*");
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() {
}
}
Please try with the filters method and let me know if it doesn't work
I am trying to connect angular 6 project with spring boot application. When I run angular project, it constantly gives this error, although I have installed all the dependencies and imports.
I have used following line of code in controller class.
#CrossOrigin(origins = "http://localhost:4200/", maxAge = 3600)
I have also included this SimpleCORSFilter.java file in java folder:
package com.oms;
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", "*");
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() {
}
}
Also I have created proxy.conf.json file in angular project:
{
"/api": {
"target": "http://localhost:8080",
"secure": false
}
}
This file is included like this in angular.json:
"start": "ng serve --proxy-config proxy.conf.json",
Still I am getting this error:
Access to XMLHttpRequest at
'http://localhost:8080/fetchAll' from origin
'http://localhost:4200' has been blocked by CORS policy: Request
header field authorization is not allowed by
Access-Control-Allow-Headers in preflight response.**
I referred such type of queries, but could not get the exact solution.
I am really confused, if there is any error in code? What steps should be taken to resolve this issue?
When you are using Spring Boot, I would suggest you to add a CorsFilter bean in your configurations instead of introducing a CORS filter. Let me know if this helps.
#Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("GET");
config.addAllowedMethod("POST");
config.addAllowedMethod("PUT");
config.addAllowedMethod("DELETE");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
Happy Coding :)
This error is coming because request contains some additional headers which are not mentioned in your CORS filter configuration.
For adding CORS support during development, I generally prefer adding below spring configuration file. You need to have app.cors.enabled key with value true in your application configuration file (application.properties) also to make it work.
import org.springframework.context.annotation.Bean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
#ConditionalOnProperty(name = "app.cors.enabled")
/**
* If the value of the key "app.cors.enabled" is true in application.properties file,
* then only this configuration will be enabled.
*
*/
public class SpringConfig {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*").allowedHeaders("*").allowedOrigins("*").allowedMethods("*")
.allowCredentials(true);
}
};
}
}
Make sure for production environment, you remove app.cors.enabled key from your configuration file or set its value to false. If you need CORS support in production environment also, make sure you use fixed values instead of allowing all values using *
Once you do that, there is no need of #CrossOrigin annotation on your controller.
Issue is with the ordering of filters with spring boot. Add this annotation on your CORSFilter: #Order(Ordered.HIGHEST_PRECEDENCE).
This will make sure that your CORSFilter has highest precendence of execution (most prior).
Please add a servlet filter and add the following code.
It should work.
Adding "Access-Control-Allow-Headers", "*" is mandatory.
Creation of proxy.conf.json is not needed.
#Component
#Order(1)
public class MyProjectFilter implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,DELETE,PUT,OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "*");
response.setHeader("Access-Control-Max-Age", "86400");
chain.doFilter(req, res);
}
}
Because of the spring security, this might happen. You can build a class and include the below-mentioned code.
package com.myapp.springboot.configs;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*").
allowedOrigins("*").
allowedMethods("*").
allowedHeaders("*").
allowCredentials(true);
}
}