How to Fix the problem of No 'Access-Control-Allow-Origin' in a SpringBoot+Vuejs app build with Gradle plugin

huangapple go评论71阅读模式
英文:

How to Fix the problem of No 'Access-Control-Allow-Origin' in a SpringBoot+Vuejs app build with Gradle plugin

问题

在我本地使用嵌入式 H2 数据库工作时,问题没有出现;但一旦部署到 Heroku 并创建一个使用所有数据的 PostgreSQL 数据库后,问题就出现了。实际上,应用程序无法识别请求中带来的标头,导致以下响应:

跨源请求到'https://xxxxxx.herokuapp.com/bikes/all'从起源'http://localhost:8082'被阻止,因为 CORS 策略:请求的资源上没有'Access-Control-Allow-Origin'标头。如果不透明的响应满足您的需求,请将请求模式设置为'no-cors',以禁用带有 CORS 的资源。

Spring 使用的依赖项如下:

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-data-rest'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	//runtimeOnly 'com.h2database:h2'
	compile("org.postgresql:postgresql")
......

在我的应用属性中,为了在部署到 Heroku 时连接到数据库,我进行了以下初始化:

### ----- 将此部分注释以在本地工作!从这里开始... -----
spring.jackson.serialization.fail-on-empty-beans=false
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=${JDBC_DATABASE_URL}
spring.datasource.username=${JDBC_DATABASE_USERNAME}
spring.datasource.password=${JDBC_DATABASE_PASSWORD}
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

然后在我的应用程序类中,我启用了所有与 web 安全相关的内容,包括允许的来源,我将其声明为(*):

@Configuration
@EnableWebSecurity
class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
	// ...
}

@Configuration
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// ...
	}

	@Bean
	public CorsConfigurationSource corsConfigurationSource() {
		final CorsConfiguration configuration = new CorsConfiguration();
		// ...
		final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}
}

在前端中调用操作时,我尝试了三种不同的请求头设置,但问题仍然存在:

const url = "xxxxxxxxx.herokuapp.com/";

fetchAllBikesJson({ commit }) {
   fetch(url + "bikes/all", {
     credentials: "include",

     // Option 1
     headers: {
       "Access-Control-Allow-Origin": "*"
     },

     // Option 2
     headers: {
       "Access-Control-Allow-Origin": "http://localhost:8082"
     },

     // Option 3 (No headers)
     method: "GET",
  })
    .then((response) => {
      return response.json();
    })
    .then((response) => {
      // ...
      commit("setAllBikesJson", response);
    })
    .catch((error) => {
      // ...
    });
},

你还提供了在网络控制台中捕获的错误视图截图,以及 Network 选项卡下的截图。

英文:

in this app im doing when i work in local with a h2-embeded database , the problem doesnt shows up, and only appears once i deploy to heroku and create a Postgresql database which use all the data from h2.
Literall y the app doesnt recognize the headers brought form the request , throwing as respopnse

Access to fetch at 'https://xxxxxx.herokuapp.com/bikes/all' from origin 'http://localhost:8082'
 has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the 
requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors'
 to fetch the resource with CORS disabled.

The dependencies used for spring are:


dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-data-rest'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	//runtimeOnly 'com.h2database:h2'
	compile("org.postgresql:postgresql") 
......

and in my app properties in order to connect with that database once is deployed to Heroku , i initialize this:

### ----- COMMENT THIS PART TO WORK IN LOCAL! FROM HERE... -----
spring.jackson.serialization.fail-on-empty-beans=false
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=${JDBC_DATABASE_URL}
spring.datasource.username=${JDBC_DATABASE_USERNAME}
spring.datasource.password=${JDBC_DATABASE_PASSWORD}
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

Then on my application class , i do enable all referring to web security included the allowed origins which i declared as (*)


@Configuration
@EnableWebSecurity
class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {
	@Autowired
	UserRepository userRepository;
	@Override
	public void init(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(inputName-> {
			User user = userRepository.findByUserName(inputName);
			if (user != null) {
				return new org.springframework.security.core.userdetails.User(user.getUserName(), user.getUserPassword(),
						AuthorityUtils.createAuthorityList("USER"));
			} else {
				throw new UsernameNotFoundException("Unknown user: " + inputName);
			}
		});
	}
}

@Configuration
@EnableWebSecurity
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.cors();///de heroku tambien
		http.authorizeRequests()
				.antMatchers("/bikes/all").permitAll()
								.antMatchers("/bikes/user/register").permitAll()
				.antMatchers("/h2-console/**").permitAll()
				.antMatchers("/rest/**").hasAuthority("ADMIN")
				.antMatchers("/**").hasAuthority("USER")
				.anyRequest().fullyAuthenticated();
		
		http.formLogin()
				.usernameParameter("name")
				.passwordParameter("password")
				.loginPage("/bikes/login");
		http.logout().logoutUrl("/api/logout");
		http.csrf().disable();
		http.exceptionHandling().authenticationEntryPoint((req, res, exc) -> res.sendError(HttpServletResponse.SC_UNAUTHORIZED));
		http.formLogin().successHandler((req, res, auth) -> clearAuthenticationAttributes(req));
		http.formLogin().failureHandler((req, res, exc) -> res.sendError(HttpServletResponse.SC_UNAUTHORIZED));
		http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
		http.headers().frameOptions().sameOrigin();
	}

	private void clearAuthenticationAttributes(HttpServletRequest request) {
		HttpSession session = request.getSession(false);
		if (session != null) {
			session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
		}
	}
	@Bean
	public CorsConfigurationSource corsConfigurationSource() {
		final CorsConfiguration configuration = new CorsConfiguration();
		
		configuration.setAllowedOrigins(Arrays.asList("*"));
		configuration.setAllowedMethods(Arrays.asList("HEAD",
				"GET", "POST", "PUT", "DELETE", "PATCH"));
		
		configuration.setAllowCredentials(true);
		
		configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
		final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}

Even as alternative isntead of (*), i specified the exact origin might be allowed , iin this case

http://localhost:8082(cause im doing the request of my front from local)

But neither works

In my front end calling the action , either put the header specifying the origing allowed (*), or localhot :8082, or even none , and still the error persists

const url=xxxxxxxxx.herokuapp.com/

fetchAllBikesJson({ commit}) {
       fetch(url +"bikes/all", {
         credentials: "include",
        
Option1
         headers: {
           "Access-Control-Allow-Origin": "*"
         },
Option 2
         headers: {
           "Access-Control-Allow-Origin": "http://localhost:8082"
         },
Option 2
         NO HEADERS
        method: "GET",
      })
        .then((response) => {
          return response.json();
        })
        .then((response) => {
          // console.log(response);
          response;
          commit("setAllBikesJson", response);
        })
        .catch((error) => {
          // console.log("error", error);
          error;
        });
    },

Also adding a view for the error from my wen console as well as one from my web console in the Network item

How to Fix the problem of No 'Access-Control-Allow-Origin' in a SpringBoot+Vuejs app build with Gradle plugin

How to Fix the problem of No 'Access-Control-Allow-Origin' in a SpringBoot+Vuejs app build with Gradle plugin
Any help about about his issue .thanks in advance!!!!

答案1

得分: 2

尝试定义配置而不是bean跨域配置。

@Configuration
public class CorsConfiguration implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedOrigins("*")
      .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS");
  }
}

另外,我注意到你的代码中有这样的部分:

http.cors();
....
...http.etc()

而应该是 http.cors().and() // 可能这是你的问题

请参考这个链接

英文:

Try defining the configuration instead of bean cors configuration

@Configuration
public class CorsConfiguration implements WebMvcConfigurer {

  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
      .allowedOrigins("*")
      .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH", "OPTIONS");
  }
}

Also I noticed that you have in your code like this:

http.cors();
....
...http.etc()

Instead it should be http.cors().and() // May be this is your issue

Please check this

huangapple
  • 本文由 发表于 2020年9月16日 23:06:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/63922943.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定