-1

I have a front application with Vue JS and I'm using axios to call my Spring Boot API, using Spring Security.

Vue is running on http://localhost:8081. API is running on http://localhost:8080

I have set my Spring Boot application as followed:

application.properties: empty

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.demin</groupId>
    <artifactId>api</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>api</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

ApiApplication:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }
}

IndexController:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@CrossOrigin(origins = "http://localhost:8081/")
@RestController
@RequestMapping("/api")
public class IndexController {
        
    @GetMapping("/index") 
    public ResponseEntity<String> findTitle()  {
        System.err.println("Hello IndexController !");
        return new ResponseEntity<>("Hello world", HttpStatus.OK);
    }
}

SecurityConfig:

import java.util.List;
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.web.cors.CorsConfiguration;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        corsConfiguration.setAllowedOrigins(List.of("http://localhost:8081"));
        corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));      

        http
            .authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .csrf().disable()
            .cors().configurationSource(request -> corsConfiguration);
    }
}

Now, when I make a call from Vue js:

axios.get('http://localhost:8080/api/index')
  .then((response) => {
    console.log(response.data);
  })
  .catch(function (error) {
    console.log(error);
  });

My browser returns:

Access to XMLHttpRequest at 'http://localhost:8080/api/index' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

It seems like it's a frequent issue so I've tried a lot of "solutions" but I am obviously missing something and I need some help...

EDIT: enter image description here

enter image description here

EDIT#2:

import java.util.Arrays;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors();
        http.formLogin().disable();
            
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

returns the same error.

EDIT#3:

2021-07-23 07:39:49.050  INFO 3924 --- [  restartedMain] com.demin.api.ApiApplication             : No active profile set, falling back to default profiles: default
2021-07-23 07:39:49.082  INFO 3924 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2021-07-23 07:39:49.082  INFO 3924 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2021-07-23 07:39:49.533  INFO 3924 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2021-07-23 07:39:49.542  INFO 3924 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 3 ms. Found 0 JPA repository interfaces.
2021-07-23 07:39:49.983  INFO 3924 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2021-07-23 07:39:49.992  INFO 3924 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-07-23 07:39:49.992  INFO 3924 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.48]
2021-07-23 07:39:50.063  INFO 3924 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-07-23 07:39:50.064  INFO 3924 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 980 ms
2021-07-23 07:39:50.084  INFO 3924 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2021-07-23 07:39:50.220  INFO 3924 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2021-07-23 07:39:50.225  INFO 3924 --- [  restartedMain] o.s.b.a.h2.H2ConsoleAutoConfiguration    : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:966f4eb4-9170-4c8f-a106-67ce4bac32bd'
2021-07-23 07:39:50.354  INFO 3924 --- [  restartedMain] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [name: default]
2021-07-23 07:39:50.395  INFO 3924 --- [  restartedMain] org.hibernate.Version                    : HHH000412: Hibernate ORM core version 5.4.32.Final
2021-07-23 07:39:50.496  INFO 3924 --- [  restartedMain] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
2021-07-23 07:39:50.592  INFO 3924 --- [  restartedMain] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2021-07-23 07:39:50.763  INFO 3924 --- [  restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2021-07-23 07:39:50.771  INFO 3924 --- [  restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-07-23 07:39:50.803  WARN 3924 --- [  restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-07-23 07:39:51.019  INFO 3924 --- [  restartedMain] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: 5d615eab-a8ac-4024-9fc0-be44e58ac78e

2021-07-23 07:39:51.109  INFO 3924 --- [  restartedMain] o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@5d114f4, org.springframework.security.web.context.SecurityContextPersistenceFilter@3c920c43, org.springframework.security.web.header.HeaderWriterFilter@45adf32d, org.springframework.security.web.csrf.CsrfFilter@59560611, org.springframework.security.web.authentication.logout.LogoutFilter@3101ec7e, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@65bc50ad, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@2439fa5a, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@4f62b51e, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@42ca4d2d, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@3765695a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@154842ed, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5f512afa, org.springframework.security.web.session.SessionManagementFilter@180f71e7, org.springframework.security.web.access.ExceptionTranslationFilter@46815abf, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@611036c4]
2021-07-23 07:39:51.145  INFO 3924 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2021-07-23 07:39:51.173  INFO 3924 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-07-23 07:39:51.182  INFO 3924 --- [  restartedMain] com.demin.api.ApiApplication             : Started ApiApplication in 2.434 seconds (JVM running for 3.184)
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Zabon
  • 241
  • 2
  • 18
  • Does this answer your question? [How to configure CORS in a Spring Boot + Spring Security application?](https://stackoverflow.com/questions/36968963/how-to-configure-cors-in-a-spring-boot-spring-security-application) – Toerktumlare Jul 22 '21 at 21:24
  • 1
    how about read the official documentation and configure it like they have https://docs.spring.io/spring-security/site/docs/current/reference/html5/#cors instead of making up some own configuration. – Toerktumlare Jul 22 '21 at 21:25
  • right now you are claiming that the official documentation is faulty. Thats a big claim. im suspecting you are implementing "our suggestions" very badly or there are parts of your application that you are not telling us about. So i also suggest you produce a small reproducible example with our examples implemented, as i have no problems at all implementing CORS. Voted to close not reproducible. – Toerktumlare Jul 23 '21 at 00:04
  • i have written an answer, and as a beginner developer, i suggest you follow a tutorial instead of asking on stack overflow. Your problem was absolute basic spring boot knowledge, that could be avoided by just following a basic spring guide that teaches you how to build a basic spring application. – Toerktumlare Jul 23 '21 at 19:59

1 Answers1

1

This question has nothing to do with CORS.

After reviewing the provided small example, the problem lies in the folder structure.

Springs main function is annotated with the annotation @SpringBootApplication which the api documentation states:

This is a convenience annotation that is equivalent to declaring @Configuration, @EnableAutoConfiguration and @ComponentScan.

For the documentation of @ComponentScan it says the following:

Configures component scanning directives for use with @Configuration classes. ... If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.

Note the last part.

So spring will scan all packages below the class that is annotated with @SpringBootApplication in search for classes that are annotated with @Configuration.

The provided projects directory layout is the following:

java
├── com
│   └─ demin
│        └── api
│             └── @SpringBootApplication
├── config
│      └── @Configuration
└── controller
       └── @RestController

Which means that none of the annotated classes will be picked up of the scan.

So the solution to the problem is that the directory structure needs to be changed to:

java
└── com
    └─ demin
         └── api
              ├── @SpringBootApplication
              ├── config
              │     └── @Configuration
              └── controller
                    └── @RestController

For spring to be able to scan the underlying packages and pick up the annotated classes.

Or you can define basePackageClasses() or basePackages() in a @ComponentScan annotation if you want spring to scan specific packages in specific locations. Or just specific classes.

When you pull in spring-security-starter you get a auto configuration defined for you which is defined in the Hello Spring Security section of the Spring Security Reference Manual

And since none of defined configuration was even picked up by the application scanning this is the configuration that is currently in use. The rest endpoint wasn't loaded either.

The configuration and endpoint not loaded could have been spotted in the debug logs if these had been enabled and provided.

So how to prevent this:

Toerktumlare
  • 12,548
  • 3
  • 35
  • 54