How do I know wether the Server or the Client is failing the Cors request?
So I am making a Restful Webservice with the Springtoolsuite and I am making a Rest Client as well. I am at a point at which I can run the service and have both Postman give me the results I expect as well as run the internal Browser of Spring and have the proper things happening.
However if I then load the html file outside of Springs browser im getting the typical CORS errors of "CORS request did not succeed" and "CORS preflight channel did not succeed" in Mozilla and in Chrome I get a 403 for OPTIONS and "access to XMLHttpRequest at 'http://localhost:8080/.." from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." which is also a CORS issue.
localhost:8080 is my choice of URL because Apache Tomcat starts the service on this port when I run the project as a Spring Boot App.
What I am unsure of now is how to find out wether I am making poorly worded requests in my Rest Client or wether I have an issue in my servercode for example supposedly the error can come from preflighting multiple times and I am unsure wether I might be doing that.
First the servercode:
package de.TeamCAM.textory.rest_interface;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import multex.Exc;
import static multex.MultexUtil.create;
import de.TeamCAM.textory.domain.*;
import de.TeamCAM.textory.domain.imports.*;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@Transactional
public class ApplicationController {
private final KapitelRepository kapitelRepository;
private final String className = getClass().getSimpleName();
@Autowired
public ApplicationController(final KapitelRepository kapitelRepository) {
this.kapitelRepository = kapitelRepository;
}
@GetMapping(path = "/Kategorie/Welt/Kapitel/{kapitelname}")
public ResponseEntity<KapitelResource> findeEinKapitel(@PathVariable String kapitelname,
@ApiParam(hidden = true) final HttpMethod method, final WebRequest request, HttpServletResponse res) {
_print(method, request);
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "*");
final Kapitel kapitel;
kapitel = kapitelRepository.find(kapitelname);
if(kapitel != null) {
return new ResponseEntity<>(new KapitelResource(kapitel), HttpStatus.OK);}
else return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@RequestMapping(method = RequestMethod.OPTIONS, value="/**")
public void manageOptions(HttpServletResponse response)
{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
} }
this is the Apllicationcontroller that handles the requests. I also have a security class that I tried to modify in a way that allows for all possibilities and CORS issues to be resolved `
package de.TeamCAM.textory.rest_interface;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String CLIENT_ROLE = "CLIENT";
private static final String BANK_ROLE = "BANK";
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/**").permitAll()
.antMatchers("/bank/**").hasRole(BANK_ROLE)
.antMatchers("/client/**").hasRole(CLIENT_ROLE)
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "file:///E:/se2/spring-ddd-bank/src/main/resources/static/kapitel.html").permitAll()
.antMatchers(
HttpMethod.GET,
"/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui.html**",
"/webjars/**",
"favicon.ico"
).permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable()
;
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
private static final List<String> predefinedUsernames = Arrays.asList("bank", "hans", "nina", "fritz", "lisa");
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
final InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication = auth.inMemoryAuthentication();
for(final String username: predefinedUsernames) {
final String role = username.equalsIgnoreCase(BANK_ROLE) ? BANK_ROLE : CLIENT_ROLE;
inMemoryAuthentication.withUser(username).password(username).roles(role);
}
}
public List<String> predefinedUsernames(){
return predefinedUsernames;
}
}
additionally according to another stackoverflow answer i created another class to add cors support
package de.TeamCAM.textory.rest_interface;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}`
which did not help either, I also added in a couple of dependencies according to other answers and now my pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<name>Spring DDD Bank</name>
<groupId>de.bht-berlin.knabe</groupId>
<artifactId>spring-ddd-bank</artifactId>
<version>0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<aspectj.version>1.8.9</aspectj.version>
<derby.version>10.12.1.1</derby.version>
<multexVersion>8.3</multexVersion>
<swagger.version>2.8.0</swagger.version>
<messageTextFile>MessageText.properties</messageTextFile>
</properties>
<dependencies>
<!-- Experiment Knabe 2018-11-15: Serve Web Content, see https://spring.io/guides/gs/serving-web-content/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/rest-hateoas/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/securing-web/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Derby Database (in-memory in test suite, or in-directory in production
code) -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<!-- For offering the Derby network server when the REST server is running: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<version>${derby.version}</version>
</dependency>
<!-- For downloading the Derby Client Driver: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
<!-- Install artifact into the local repo, so that a database browser
can pick it up, but do not deliver it with the product: -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</dependency>
<!-- Following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Disable Maven Compiler Plugin for production sources following https://stackoverflow.com/questions/14614446/how-do-i-disable-the-maven-compiler-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<!-- Use AspectJ Maven Plugin instead for compiling production sources
following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
</goals>
</execution>
</executions>
<configuration>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<dependencies>
<!-- Avoid AspectJ version clashes between 1.8.9 and 1.8.10 following
https://stackoverflow.com/questions/41646801/maven-aspectj-weaving-for-java8 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<!-- Here used for extraction of exception message texts in the reference
language from the exception Javadoc comments. -->
<goals>
<goal>javadoc</goal>
</goals>
<!-- <phase>process-classes</phase> -->
<phase>compile</phase>
<configuration>
<!-- Specific configuration for the messages report -->
<doclet>multex.tool.ExceptionMessagesDoclet</doclet>
<docletArtifact>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</docletArtifact>
<useStandardDocletOptions>false</useStandardDocletOptions>
<show>private</show>
<verbose>false</verbose>
<debug>false</debug>
<additionalparam>
-out
${project.build.directory}/classes/${messageTextFile}
</additionalparam>
<!-- For the project-reports page -->
<name>ExceptionTexts</name>
<description>Extraction of Exception Message Texts from Source
Code</description>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Java Code Coverage analyzer. See https://www.petrikainulainen.net/programming/maven/creating-code-coverage-reports-for-unit-and-integration-tests-with-the-jacoco-maven-plugin/ -->
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<!-- Prepares the property pointing to the JaCoCo runtime agent, which
is passed as VM argument, when the Maven Surefire plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<!-- Sets the name of the property containing the settings for the
JaCoCo runtime agent. -->
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is created
after unit tests have been run. -->
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the collected execution
data. -->
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line for test runs in Surefire, created by
the upper prepare-agent goal of the jacoco-maven-plugin. -->
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-javadoc-plugin
</artifactId>
<versionRange>
[2.9.1,)
</versionRange>
<goals>
<goal>javadoc</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-dependency-plugin
</artifactId>
<versionRange>
[3.0.2,)
</versionRange>
<goals>
<goal>sources</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<show>private</show>
</configuration>
</plugin>
<!-- Do not look for possible repositories for each dependency in order
to speed up project site generation. See https://www.mkyong.com/maven/maven-site-build-is-very-slow-dependency-report/ -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.9</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
</plugins>
</reporting>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository><!-- For current MulTEx: -->
<id>bht-knabe-repository</id>
<name>BHT Knabe Maven 2 repository</name>
<url>http://public.beuth-hochschule.de/~knabe/mvn-repo/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
I am doing this without a web.xml file so of course all answers on how to change the web.xml to add CORS support did not help either. These are all things on the serverside that would make or brake the CORS support in my opinion now on to the clientside.
The html is pretty harmless the only relevant lines are
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="allstar.js" defer></script>
which I have in the head, putting them at the end of the body changed nothing.
The 2 relevant js files are the following:
let speichern = document.getElementById("speichern");
var put = document.getElementById("put");
var dele = document.getElementById("delete");
var post = document.getElementById("post");
var get = document.getElementById("get");
let form = document.getElementById("formSubmit");
let kapitelName = document.getElementsByName("kapitelName")[0];
let kapitelInhalt = document.getElementsByName("kapitelInhalt")[0];
let istEnde = document.getElementById("istEnde");
let bild = document.getElementsByName("bild");
let name = {};
let inhalt = {};
kapitelName.oninput = function() {
name.value = kapitelName.value;
console.log(name);
}
kapitelInhalt.oninput = function() {
inhalt.value = kapitelInhalt.value;
console.log(inhalt);
}
istEnde.onchange = function() {
console.log("The checkbox was checked.");
}
var script = document.createElement('script');
script.onload = function () {}
document.getElementById("put").onclick = function() {
myputFunction()
}
function myputFunction() {
script.src = "trueput.js";
document.head.appendChild(script);
}
document.getElementById("get").onclick = function() {
mygetFunction()
}
function mygetFunction() {
script.src = "trueget.js";
document.head.appendChild(script);
}
document.getElementById("post").onclick = function() {
mypostFunction()
}
function mypostFunction() {
script.src = "truepost.js";
document.head.appendChild(script);
}
document.getElementById("delete").onclick = function() {
mydeleteFunction()
}
function mydeleteFunction() {
script.src = "truedelete.js";
document.head.appendChild(script);
}
which handles buttonclicks on different buttons and starts the appropriate js file. I have POST PUT and DELETE methods in the applicationcontroller and files for each of them but I want to at least get a GET going and go from there. So here is the JS file for the GET request that is baiscally doing the entire clientside of the rest exchange:
var kapitelname = document.getElementsByClassName("titelanzeige")[0].value;
$.ajax({
headers: {
'Authorization': 'Basic ' + btoa("bank" + ":" + "bank")
},
url: "http://localhost:8080/Kategorie/Welt/Kapitel/" +kapitelname,
type: 'GET',
success: function(data) {
$('.titelanzeige').html("");
$('.inhaltsanzeige').html("");
$('.titelanzeige').append(data.kapitelname);
$('.inhaltsanzeige').append(data.inhalt);
}
});
I tried adding Origin: to this but it doesnt get recognised and only turns out an error. Changing the type to text or to json didnt achieve anything. So after implementing a bunch of solutions for both the server and the client I am still being blocked by the same-origin-policy and my main question is how I can check which of the 2 sides here is faulty so that I know what to work on. Thanks in advance.
ajax spring spring-mvc spring-boot cors
add a comment |
So I am making a Restful Webservice with the Springtoolsuite and I am making a Rest Client as well. I am at a point at which I can run the service and have both Postman give me the results I expect as well as run the internal Browser of Spring and have the proper things happening.
However if I then load the html file outside of Springs browser im getting the typical CORS errors of "CORS request did not succeed" and "CORS preflight channel did not succeed" in Mozilla and in Chrome I get a 403 for OPTIONS and "access to XMLHttpRequest at 'http://localhost:8080/.." from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." which is also a CORS issue.
localhost:8080 is my choice of URL because Apache Tomcat starts the service on this port when I run the project as a Spring Boot App.
What I am unsure of now is how to find out wether I am making poorly worded requests in my Rest Client or wether I have an issue in my servercode for example supposedly the error can come from preflighting multiple times and I am unsure wether I might be doing that.
First the servercode:
package de.TeamCAM.textory.rest_interface;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import multex.Exc;
import static multex.MultexUtil.create;
import de.TeamCAM.textory.domain.*;
import de.TeamCAM.textory.domain.imports.*;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@Transactional
public class ApplicationController {
private final KapitelRepository kapitelRepository;
private final String className = getClass().getSimpleName();
@Autowired
public ApplicationController(final KapitelRepository kapitelRepository) {
this.kapitelRepository = kapitelRepository;
}
@GetMapping(path = "/Kategorie/Welt/Kapitel/{kapitelname}")
public ResponseEntity<KapitelResource> findeEinKapitel(@PathVariable String kapitelname,
@ApiParam(hidden = true) final HttpMethod method, final WebRequest request, HttpServletResponse res) {
_print(method, request);
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "*");
final Kapitel kapitel;
kapitel = kapitelRepository.find(kapitelname);
if(kapitel != null) {
return new ResponseEntity<>(new KapitelResource(kapitel), HttpStatus.OK);}
else return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@RequestMapping(method = RequestMethod.OPTIONS, value="/**")
public void manageOptions(HttpServletResponse response)
{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
} }
this is the Apllicationcontroller that handles the requests. I also have a security class that I tried to modify in a way that allows for all possibilities and CORS issues to be resolved `
package de.TeamCAM.textory.rest_interface;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String CLIENT_ROLE = "CLIENT";
private static final String BANK_ROLE = "BANK";
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/**").permitAll()
.antMatchers("/bank/**").hasRole(BANK_ROLE)
.antMatchers("/client/**").hasRole(CLIENT_ROLE)
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "file:///E:/se2/spring-ddd-bank/src/main/resources/static/kapitel.html").permitAll()
.antMatchers(
HttpMethod.GET,
"/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui.html**",
"/webjars/**",
"favicon.ico"
).permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable()
;
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
private static final List<String> predefinedUsernames = Arrays.asList("bank", "hans", "nina", "fritz", "lisa");
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
final InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication = auth.inMemoryAuthentication();
for(final String username: predefinedUsernames) {
final String role = username.equalsIgnoreCase(BANK_ROLE) ? BANK_ROLE : CLIENT_ROLE;
inMemoryAuthentication.withUser(username).password(username).roles(role);
}
}
public List<String> predefinedUsernames(){
return predefinedUsernames;
}
}
additionally according to another stackoverflow answer i created another class to add cors support
package de.TeamCAM.textory.rest_interface;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}`
which did not help either, I also added in a couple of dependencies according to other answers and now my pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<name>Spring DDD Bank</name>
<groupId>de.bht-berlin.knabe</groupId>
<artifactId>spring-ddd-bank</artifactId>
<version>0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<aspectj.version>1.8.9</aspectj.version>
<derby.version>10.12.1.1</derby.version>
<multexVersion>8.3</multexVersion>
<swagger.version>2.8.0</swagger.version>
<messageTextFile>MessageText.properties</messageTextFile>
</properties>
<dependencies>
<!-- Experiment Knabe 2018-11-15: Serve Web Content, see https://spring.io/guides/gs/serving-web-content/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/rest-hateoas/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/securing-web/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Derby Database (in-memory in test suite, or in-directory in production
code) -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<!-- For offering the Derby network server when the REST server is running: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<version>${derby.version}</version>
</dependency>
<!-- For downloading the Derby Client Driver: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
<!-- Install artifact into the local repo, so that a database browser
can pick it up, but do not deliver it with the product: -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</dependency>
<!-- Following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Disable Maven Compiler Plugin for production sources following https://stackoverflow.com/questions/14614446/how-do-i-disable-the-maven-compiler-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<!-- Use AspectJ Maven Plugin instead for compiling production sources
following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
</goals>
</execution>
</executions>
<configuration>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<dependencies>
<!-- Avoid AspectJ version clashes between 1.8.9 and 1.8.10 following
https://stackoverflow.com/questions/41646801/maven-aspectj-weaving-for-java8 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<!-- Here used for extraction of exception message texts in the reference
language from the exception Javadoc comments. -->
<goals>
<goal>javadoc</goal>
</goals>
<!-- <phase>process-classes</phase> -->
<phase>compile</phase>
<configuration>
<!-- Specific configuration for the messages report -->
<doclet>multex.tool.ExceptionMessagesDoclet</doclet>
<docletArtifact>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</docletArtifact>
<useStandardDocletOptions>false</useStandardDocletOptions>
<show>private</show>
<verbose>false</verbose>
<debug>false</debug>
<additionalparam>
-out
${project.build.directory}/classes/${messageTextFile}
</additionalparam>
<!-- For the project-reports page -->
<name>ExceptionTexts</name>
<description>Extraction of Exception Message Texts from Source
Code</description>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Java Code Coverage analyzer. See https://www.petrikainulainen.net/programming/maven/creating-code-coverage-reports-for-unit-and-integration-tests-with-the-jacoco-maven-plugin/ -->
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<!-- Prepares the property pointing to the JaCoCo runtime agent, which
is passed as VM argument, when the Maven Surefire plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<!-- Sets the name of the property containing the settings for the
JaCoCo runtime agent. -->
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is created
after unit tests have been run. -->
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the collected execution
data. -->
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line for test runs in Surefire, created by
the upper prepare-agent goal of the jacoco-maven-plugin. -->
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-javadoc-plugin
</artifactId>
<versionRange>
[2.9.1,)
</versionRange>
<goals>
<goal>javadoc</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-dependency-plugin
</artifactId>
<versionRange>
[3.0.2,)
</versionRange>
<goals>
<goal>sources</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<show>private</show>
</configuration>
</plugin>
<!-- Do not look for possible repositories for each dependency in order
to speed up project site generation. See https://www.mkyong.com/maven/maven-site-build-is-very-slow-dependency-report/ -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.9</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
</plugins>
</reporting>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository><!-- For current MulTEx: -->
<id>bht-knabe-repository</id>
<name>BHT Knabe Maven 2 repository</name>
<url>http://public.beuth-hochschule.de/~knabe/mvn-repo/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
I am doing this without a web.xml file so of course all answers on how to change the web.xml to add CORS support did not help either. These are all things on the serverside that would make or brake the CORS support in my opinion now on to the clientside.
The html is pretty harmless the only relevant lines are
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="allstar.js" defer></script>
which I have in the head, putting them at the end of the body changed nothing.
The 2 relevant js files are the following:
let speichern = document.getElementById("speichern");
var put = document.getElementById("put");
var dele = document.getElementById("delete");
var post = document.getElementById("post");
var get = document.getElementById("get");
let form = document.getElementById("formSubmit");
let kapitelName = document.getElementsByName("kapitelName")[0];
let kapitelInhalt = document.getElementsByName("kapitelInhalt")[0];
let istEnde = document.getElementById("istEnde");
let bild = document.getElementsByName("bild");
let name = {};
let inhalt = {};
kapitelName.oninput = function() {
name.value = kapitelName.value;
console.log(name);
}
kapitelInhalt.oninput = function() {
inhalt.value = kapitelInhalt.value;
console.log(inhalt);
}
istEnde.onchange = function() {
console.log("The checkbox was checked.");
}
var script = document.createElement('script');
script.onload = function () {}
document.getElementById("put").onclick = function() {
myputFunction()
}
function myputFunction() {
script.src = "trueput.js";
document.head.appendChild(script);
}
document.getElementById("get").onclick = function() {
mygetFunction()
}
function mygetFunction() {
script.src = "trueget.js";
document.head.appendChild(script);
}
document.getElementById("post").onclick = function() {
mypostFunction()
}
function mypostFunction() {
script.src = "truepost.js";
document.head.appendChild(script);
}
document.getElementById("delete").onclick = function() {
mydeleteFunction()
}
function mydeleteFunction() {
script.src = "truedelete.js";
document.head.appendChild(script);
}
which handles buttonclicks on different buttons and starts the appropriate js file. I have POST PUT and DELETE methods in the applicationcontroller and files for each of them but I want to at least get a GET going and go from there. So here is the JS file for the GET request that is baiscally doing the entire clientside of the rest exchange:
var kapitelname = document.getElementsByClassName("titelanzeige")[0].value;
$.ajax({
headers: {
'Authorization': 'Basic ' + btoa("bank" + ":" + "bank")
},
url: "http://localhost:8080/Kategorie/Welt/Kapitel/" +kapitelname,
type: 'GET',
success: function(data) {
$('.titelanzeige').html("");
$('.inhaltsanzeige').html("");
$('.titelanzeige').append(data.kapitelname);
$('.inhaltsanzeige').append(data.inhalt);
}
});
I tried adding Origin: to this but it doesnt get recognised and only turns out an error. Changing the type to text or to json didnt achieve anything. So after implementing a bunch of solutions for both the server and the client I am still being blocked by the same-origin-policy and my main question is how I can check which of the 2 sides here is faulty so that I know what to work on. Thanks in advance.
ajax spring spring-mvc spring-boot cors
add a comment |
So I am making a Restful Webservice with the Springtoolsuite and I am making a Rest Client as well. I am at a point at which I can run the service and have both Postman give me the results I expect as well as run the internal Browser of Spring and have the proper things happening.
However if I then load the html file outside of Springs browser im getting the typical CORS errors of "CORS request did not succeed" and "CORS preflight channel did not succeed" in Mozilla and in Chrome I get a 403 for OPTIONS and "access to XMLHttpRequest at 'http://localhost:8080/.." from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." which is also a CORS issue.
localhost:8080 is my choice of URL because Apache Tomcat starts the service on this port when I run the project as a Spring Boot App.
What I am unsure of now is how to find out wether I am making poorly worded requests in my Rest Client or wether I have an issue in my servercode for example supposedly the error can come from preflighting multiple times and I am unsure wether I might be doing that.
First the servercode:
package de.TeamCAM.textory.rest_interface;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import multex.Exc;
import static multex.MultexUtil.create;
import de.TeamCAM.textory.domain.*;
import de.TeamCAM.textory.domain.imports.*;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@Transactional
public class ApplicationController {
private final KapitelRepository kapitelRepository;
private final String className = getClass().getSimpleName();
@Autowired
public ApplicationController(final KapitelRepository kapitelRepository) {
this.kapitelRepository = kapitelRepository;
}
@GetMapping(path = "/Kategorie/Welt/Kapitel/{kapitelname}")
public ResponseEntity<KapitelResource> findeEinKapitel(@PathVariable String kapitelname,
@ApiParam(hidden = true) final HttpMethod method, final WebRequest request, HttpServletResponse res) {
_print(method, request);
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "*");
final Kapitel kapitel;
kapitel = kapitelRepository.find(kapitelname);
if(kapitel != null) {
return new ResponseEntity<>(new KapitelResource(kapitel), HttpStatus.OK);}
else return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@RequestMapping(method = RequestMethod.OPTIONS, value="/**")
public void manageOptions(HttpServletResponse response)
{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
} }
this is the Apllicationcontroller that handles the requests. I also have a security class that I tried to modify in a way that allows for all possibilities and CORS issues to be resolved `
package de.TeamCAM.textory.rest_interface;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String CLIENT_ROLE = "CLIENT";
private static final String BANK_ROLE = "BANK";
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/**").permitAll()
.antMatchers("/bank/**").hasRole(BANK_ROLE)
.antMatchers("/client/**").hasRole(CLIENT_ROLE)
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "file:///E:/se2/spring-ddd-bank/src/main/resources/static/kapitel.html").permitAll()
.antMatchers(
HttpMethod.GET,
"/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui.html**",
"/webjars/**",
"favicon.ico"
).permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable()
;
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
private static final List<String> predefinedUsernames = Arrays.asList("bank", "hans", "nina", "fritz", "lisa");
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
final InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication = auth.inMemoryAuthentication();
for(final String username: predefinedUsernames) {
final String role = username.equalsIgnoreCase(BANK_ROLE) ? BANK_ROLE : CLIENT_ROLE;
inMemoryAuthentication.withUser(username).password(username).roles(role);
}
}
public List<String> predefinedUsernames(){
return predefinedUsernames;
}
}
additionally according to another stackoverflow answer i created another class to add cors support
package de.TeamCAM.textory.rest_interface;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}`
which did not help either, I also added in a couple of dependencies according to other answers and now my pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<name>Spring DDD Bank</name>
<groupId>de.bht-berlin.knabe</groupId>
<artifactId>spring-ddd-bank</artifactId>
<version>0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<aspectj.version>1.8.9</aspectj.version>
<derby.version>10.12.1.1</derby.version>
<multexVersion>8.3</multexVersion>
<swagger.version>2.8.0</swagger.version>
<messageTextFile>MessageText.properties</messageTextFile>
</properties>
<dependencies>
<!-- Experiment Knabe 2018-11-15: Serve Web Content, see https://spring.io/guides/gs/serving-web-content/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/rest-hateoas/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/securing-web/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Derby Database (in-memory in test suite, or in-directory in production
code) -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<!-- For offering the Derby network server when the REST server is running: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<version>${derby.version}</version>
</dependency>
<!-- For downloading the Derby Client Driver: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
<!-- Install artifact into the local repo, so that a database browser
can pick it up, but do not deliver it with the product: -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</dependency>
<!-- Following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Disable Maven Compiler Plugin for production sources following https://stackoverflow.com/questions/14614446/how-do-i-disable-the-maven-compiler-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<!-- Use AspectJ Maven Plugin instead for compiling production sources
following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
</goals>
</execution>
</executions>
<configuration>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<dependencies>
<!-- Avoid AspectJ version clashes between 1.8.9 and 1.8.10 following
https://stackoverflow.com/questions/41646801/maven-aspectj-weaving-for-java8 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<!-- Here used for extraction of exception message texts in the reference
language from the exception Javadoc comments. -->
<goals>
<goal>javadoc</goal>
</goals>
<!-- <phase>process-classes</phase> -->
<phase>compile</phase>
<configuration>
<!-- Specific configuration for the messages report -->
<doclet>multex.tool.ExceptionMessagesDoclet</doclet>
<docletArtifact>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</docletArtifact>
<useStandardDocletOptions>false</useStandardDocletOptions>
<show>private</show>
<verbose>false</verbose>
<debug>false</debug>
<additionalparam>
-out
${project.build.directory}/classes/${messageTextFile}
</additionalparam>
<!-- For the project-reports page -->
<name>ExceptionTexts</name>
<description>Extraction of Exception Message Texts from Source
Code</description>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Java Code Coverage analyzer. See https://www.petrikainulainen.net/programming/maven/creating-code-coverage-reports-for-unit-and-integration-tests-with-the-jacoco-maven-plugin/ -->
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<!-- Prepares the property pointing to the JaCoCo runtime agent, which
is passed as VM argument, when the Maven Surefire plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<!-- Sets the name of the property containing the settings for the
JaCoCo runtime agent. -->
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is created
after unit tests have been run. -->
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the collected execution
data. -->
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line for test runs in Surefire, created by
the upper prepare-agent goal of the jacoco-maven-plugin. -->
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-javadoc-plugin
</artifactId>
<versionRange>
[2.9.1,)
</versionRange>
<goals>
<goal>javadoc</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-dependency-plugin
</artifactId>
<versionRange>
[3.0.2,)
</versionRange>
<goals>
<goal>sources</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<show>private</show>
</configuration>
</plugin>
<!-- Do not look for possible repositories for each dependency in order
to speed up project site generation. See https://www.mkyong.com/maven/maven-site-build-is-very-slow-dependency-report/ -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.9</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
</plugins>
</reporting>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository><!-- For current MulTEx: -->
<id>bht-knabe-repository</id>
<name>BHT Knabe Maven 2 repository</name>
<url>http://public.beuth-hochschule.de/~knabe/mvn-repo/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
I am doing this without a web.xml file so of course all answers on how to change the web.xml to add CORS support did not help either. These are all things on the serverside that would make or brake the CORS support in my opinion now on to the clientside.
The html is pretty harmless the only relevant lines are
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="allstar.js" defer></script>
which I have in the head, putting them at the end of the body changed nothing.
The 2 relevant js files are the following:
let speichern = document.getElementById("speichern");
var put = document.getElementById("put");
var dele = document.getElementById("delete");
var post = document.getElementById("post");
var get = document.getElementById("get");
let form = document.getElementById("formSubmit");
let kapitelName = document.getElementsByName("kapitelName")[0];
let kapitelInhalt = document.getElementsByName("kapitelInhalt")[0];
let istEnde = document.getElementById("istEnde");
let bild = document.getElementsByName("bild");
let name = {};
let inhalt = {};
kapitelName.oninput = function() {
name.value = kapitelName.value;
console.log(name);
}
kapitelInhalt.oninput = function() {
inhalt.value = kapitelInhalt.value;
console.log(inhalt);
}
istEnde.onchange = function() {
console.log("The checkbox was checked.");
}
var script = document.createElement('script');
script.onload = function () {}
document.getElementById("put").onclick = function() {
myputFunction()
}
function myputFunction() {
script.src = "trueput.js";
document.head.appendChild(script);
}
document.getElementById("get").onclick = function() {
mygetFunction()
}
function mygetFunction() {
script.src = "trueget.js";
document.head.appendChild(script);
}
document.getElementById("post").onclick = function() {
mypostFunction()
}
function mypostFunction() {
script.src = "truepost.js";
document.head.appendChild(script);
}
document.getElementById("delete").onclick = function() {
mydeleteFunction()
}
function mydeleteFunction() {
script.src = "truedelete.js";
document.head.appendChild(script);
}
which handles buttonclicks on different buttons and starts the appropriate js file. I have POST PUT and DELETE methods in the applicationcontroller and files for each of them but I want to at least get a GET going and go from there. So here is the JS file for the GET request that is baiscally doing the entire clientside of the rest exchange:
var kapitelname = document.getElementsByClassName("titelanzeige")[0].value;
$.ajax({
headers: {
'Authorization': 'Basic ' + btoa("bank" + ":" + "bank")
},
url: "http://localhost:8080/Kategorie/Welt/Kapitel/" +kapitelname,
type: 'GET',
success: function(data) {
$('.titelanzeige').html("");
$('.inhaltsanzeige').html("");
$('.titelanzeige').append(data.kapitelname);
$('.inhaltsanzeige').append(data.inhalt);
}
});
I tried adding Origin: to this but it doesnt get recognised and only turns out an error. Changing the type to text or to json didnt achieve anything. So after implementing a bunch of solutions for both the server and the client I am still being blocked by the same-origin-policy and my main question is how I can check which of the 2 sides here is faulty so that I know what to work on. Thanks in advance.
ajax spring spring-mvc spring-boot cors
So I am making a Restful Webservice with the Springtoolsuite and I am making a Rest Client as well. I am at a point at which I can run the service and have both Postman give me the results I expect as well as run the internal Browser of Spring and have the proper things happening.
However if I then load the html file outside of Springs browser im getting the typical CORS errors of "CORS request did not succeed" and "CORS preflight channel did not succeed" in Mozilla and in Chrome I get a 403 for OPTIONS and "access to XMLHttpRequest at 'http://localhost:8080/.." from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource." which is also a CORS issue.
localhost:8080 is my choice of URL because Apache Tomcat starts the service on this port when I run the project as a Spring Boot App.
What I am unsure of now is how to find out wether I am making poorly worded requests in my Rest Client or wether I have an issue in my servercode for example supposedly the error can come from preflighting multiple times and I am unsure wether I might be doing that.
First the servercode:
package de.TeamCAM.textory.rest_interface;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletResponse;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.Authorization;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.WebRequest;
import multex.Exc;
import static multex.MultexUtil.create;
import de.TeamCAM.textory.domain.*;
import de.TeamCAM.textory.domain.imports.*;
@CrossOrigin(origins = "http://localhost:8080")
@RestController
@Transactional
public class ApplicationController {
private final KapitelRepository kapitelRepository;
private final String className = getClass().getSimpleName();
@Autowired
public ApplicationController(final KapitelRepository kapitelRepository) {
this.kapitelRepository = kapitelRepository;
}
@GetMapping(path = "/Kategorie/Welt/Kapitel/{kapitelname}")
public ResponseEntity<KapitelResource> findeEinKapitel(@PathVariable String kapitelname,
@ApiParam(hidden = true) final HttpMethod method, final WebRequest request, HttpServletResponse res) {
_print(method, request);
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "*");
final Kapitel kapitel;
kapitel = kapitelRepository.find(kapitelname);
if(kapitel != null) {
return new ResponseEntity<>(new KapitelResource(kapitel), HttpStatus.OK);}
else return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
@RequestMapping(method = RequestMethod.OPTIONS, value="/**")
public void manageOptions(HttpServletResponse response)
{
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
} }
this is the Apllicationcontroller that handles the requests. I also have a security class that I tried to modify in a way that allows for all possibilities and CORS issues to be resolved `
package de.TeamCAM.textory.rest_interface;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.SecurityBuilder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String CLIENT_ROLE = "CLIENT";
private static final String BANK_ROLE = "BANK";
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/**").permitAll()
.antMatchers("/bank/**").hasRole(BANK_ROLE)
.antMatchers("/client/**").hasRole(CLIENT_ROLE)
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.OPTIONS, "file:///E:/se2/spring-ddd-bank/src/main/resources/static/kapitel.html").permitAll()
.antMatchers(
HttpMethod.GET,
"/v2/api-docs",
"/swagger-resources/**",
"/swagger-ui.html**",
"/webjars/**",
"favicon.ico"
).permitAll()
.anyRequest().authenticated()
.and().httpBasic()
.and().csrf().disable()
;
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("GET","POST","OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
private static final List<String> predefinedUsernames = Arrays.asList("bank", "hans", "nina", "fritz", "lisa");
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
final InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication = auth.inMemoryAuthentication();
for(final String username: predefinedUsernames) {
final String role = username.equalsIgnoreCase(BANK_ROLE) ? BANK_ROLE : CLIENT_ROLE;
inMemoryAuthentication.withUser(username).password(username).roles(role);
}
}
public List<String> predefinedUsernames(){
return predefinedUsernames;
}
}
additionally according to another stackoverflow answer i created another class to add cors support
package de.TeamCAM.textory.rest_interface;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}`
which did not help either, I also added in a couple of dependencies according to other answers and now my pom.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<name>Spring DDD Bank</name>
<groupId>de.bht-berlin.knabe</groupId>
<artifactId>spring-ddd-bank</artifactId>
<version>0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<aspectj.version>1.8.9</aspectj.version>
<derby.version>10.12.1.1</derby.version>
<multexVersion>8.3</multexVersion>
<swagger.version>2.8.0</swagger.version>
<messageTextFile>MessageText.properties</messageTextFile>
</properties>
<dependencies>
<!-- Experiment Knabe 2018-11-15: Serve Web Content, see https://spring.io/guides/gs/serving-web-content/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/rest-hateoas/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<!-- According to https://spring.io/guides/gs/securing-web/ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Derby Database (in-memory in test suite, or in-directory in production
code) -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
</dependency>
<!-- For offering the Derby network server when the REST server is running: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbynet</artifactId>
<version>${derby.version}</version>
</dependency>
<!-- For downloading the Derby Client Driver: -->
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>${derby.version}</version>
<!-- Install artifact into the local repo, so that a database browser
can pick it up, but do not deliver it with the product: -->
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</dependency>
<!-- Following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Disable Maven Compiler Plugin for production sources following https://stackoverflow.com/questions/14614446/how-do-i-disable-the-maven-compiler-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<!-- Use AspectJ Maven Plugin instead for compiling production sources
following http://www.mojohaus.org/aspectj-maven-plugin/usage.html -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
</goals>
</execution>
</executions>
<configuration>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<dependencies>
<!-- Avoid AspectJ version clashes between 1.8.9 and 1.8.10 following
https://stackoverflow.com/questions/41646801/maven-aspectj-weaving-for-java8 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<!-- Here used for extraction of exception message texts in the reference
language from the exception Javadoc comments. -->
<goals>
<goal>javadoc</goal>
</goals>
<!-- <phase>process-classes</phase> -->
<phase>compile</phase>
<configuration>
<!-- Specific configuration for the messages report -->
<doclet>multex.tool.ExceptionMessagesDoclet</doclet>
<docletArtifact>
<groupId>de.tfh-berlin.knabe</groupId>
<artifactId>multex</artifactId>
<version>${multexVersion}</version>
</docletArtifact>
<useStandardDocletOptions>false</useStandardDocletOptions>
<show>private</show>
<verbose>false</verbose>
<debug>false</debug>
<additionalparam>
-out
${project.build.directory}/classes/${messageTextFile}
</additionalparam>
<!-- For the project-reports page -->
<name>ExceptionTexts</name>
<description>Extraction of Exception Message Texts from Source
Code</description>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Java Code Coverage analyzer. See https://www.petrikainulainen.net/programming/maven/creating-code-coverage-reports-for-unit-and-integration-tests-with-the-jacoco-maven-plugin/ -->
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.9</version>
<executions>
<!-- Prepares the property pointing to the JaCoCo runtime agent, which
is passed as VM argument, when the Maven Surefire plugin is executed. -->
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the execution data. -->
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<!-- Sets the name of the property containing the settings for the
JaCoCo runtime agent. -->
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<!-- Ensures that the code coverage report for unit tests is created
after unit tests have been run. -->
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<!-- Sets the path to the file which contains the collected execution
data. -->
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<!-- Sets the output directory for the code coverage report. -->
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- Sets the VM argument line for test runs in Surefire, created by
the upper prepare-agent goal of the jacoco-maven-plugin. -->
<argLine>${surefireArgLine}</argLine>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings
only. It has no influence on the Maven build itself. -->
<plugin>
<groupId>org.eclipse.m2e</groupId>
<artifactId>lifecycle-mapping</artifactId>
<version>1.0.0</version>
<configuration>
<lifecycleMappingMetadata>
<pluginExecutions>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-javadoc-plugin
</artifactId>
<versionRange>
[2.9.1,)
</versionRange>
<goals>
<goal>javadoc</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-dependency-plugin
</artifactId>
<versionRange>
[3.0.2,)
</versionRange>
<goals>
<goal>sources</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<show>private</show>
</configuration>
</plugin>
<!-- Do not look for possible repositories for each dependency in order
to speed up project site generation. See https://www.mkyong.com/maven/maven-site-build-is-very-slow-dependency-report/ -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.9</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>
</plugin>
</plugins>
</reporting>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository><!-- For current MulTEx: -->
<id>bht-knabe-repository</id>
<name>BHT Knabe Maven 2 repository</name>
<url>http://public.beuth-hochschule.de/~knabe/mvn-repo/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
I am doing this without a web.xml file so of course all answers on how to change the web.xml to add CORS support did not help either. These are all things on the serverside that would make or brake the CORS support in my opinion now on to the clientside.
The html is pretty harmless the only relevant lines are
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="allstar.js" defer></script>
which I have in the head, putting them at the end of the body changed nothing.
The 2 relevant js files are the following:
let speichern = document.getElementById("speichern");
var put = document.getElementById("put");
var dele = document.getElementById("delete");
var post = document.getElementById("post");
var get = document.getElementById("get");
let form = document.getElementById("formSubmit");
let kapitelName = document.getElementsByName("kapitelName")[0];
let kapitelInhalt = document.getElementsByName("kapitelInhalt")[0];
let istEnde = document.getElementById("istEnde");
let bild = document.getElementsByName("bild");
let name = {};
let inhalt = {};
kapitelName.oninput = function() {
name.value = kapitelName.value;
console.log(name);
}
kapitelInhalt.oninput = function() {
inhalt.value = kapitelInhalt.value;
console.log(inhalt);
}
istEnde.onchange = function() {
console.log("The checkbox was checked.");
}
var script = document.createElement('script');
script.onload = function () {}
document.getElementById("put").onclick = function() {
myputFunction()
}
function myputFunction() {
script.src = "trueput.js";
document.head.appendChild(script);
}
document.getElementById("get").onclick = function() {
mygetFunction()
}
function mygetFunction() {
script.src = "trueget.js";
document.head.appendChild(script);
}
document.getElementById("post").onclick = function() {
mypostFunction()
}
function mypostFunction() {
script.src = "truepost.js";
document.head.appendChild(script);
}
document.getElementById("delete").onclick = function() {
mydeleteFunction()
}
function mydeleteFunction() {
script.src = "truedelete.js";
document.head.appendChild(script);
}
which handles buttonclicks on different buttons and starts the appropriate js file. I have POST PUT and DELETE methods in the applicationcontroller and files for each of them but I want to at least get a GET going and go from there. So here is the JS file for the GET request that is baiscally doing the entire clientside of the rest exchange:
var kapitelname = document.getElementsByClassName("titelanzeige")[0].value;
$.ajax({
headers: {
'Authorization': 'Basic ' + btoa("bank" + ":" + "bank")
},
url: "http://localhost:8080/Kategorie/Welt/Kapitel/" +kapitelname,
type: 'GET',
success: function(data) {
$('.titelanzeige').html("");
$('.inhaltsanzeige').html("");
$('.titelanzeige').append(data.kapitelname);
$('.inhaltsanzeige').append(data.inhalt);
}
});
I tried adding Origin: to this but it doesnt get recognised and only turns out an error. Changing the type to text or to json didnt achieve anything. So after implementing a bunch of solutions for both the server and the client I am still being blocked by the same-origin-policy and my main question is how I can check which of the 2 sides here is faulty so that I know what to work on. Thanks in advance.
ajax spring spring-mvc spring-boot cors
ajax spring spring-mvc spring-boot cors
asked Nov 22 '18 at 2:07
Eric EricsonEric Ericson
32
32
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Still not entirely sure how to test which one doesn't work but I did find the solution.
I implemented 2 changes either one of which probably did the trick:
For one I added the
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
package to the WebConfig class and I changed
<script src="allstar.js" defer></script>
to
<script src="allstar.js" crossorigin="anonymous" defer></script>
and now I CORS finally isn't a problem anymore. This is all based on Stackoverflow questions posed previously but the code contains like 20 seperate answer codes from about as many questions so I didn't find the time to link them, sorry.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53422932%2fhow-do-i-know-wether-the-server-or-the-client-is-failing-the-cors-request%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Still not entirely sure how to test which one doesn't work but I did find the solution.
I implemented 2 changes either one of which probably did the trick:
For one I added the
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
package to the WebConfig class and I changed
<script src="allstar.js" defer></script>
to
<script src="allstar.js" crossorigin="anonymous" defer></script>
and now I CORS finally isn't a problem anymore. This is all based on Stackoverflow questions posed previously but the code contains like 20 seperate answer codes from about as many questions so I didn't find the time to link them, sorry.
add a comment |
Still not entirely sure how to test which one doesn't work but I did find the solution.
I implemented 2 changes either one of which probably did the trick:
For one I added the
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
package to the WebConfig class and I changed
<script src="allstar.js" defer></script>
to
<script src="allstar.js" crossorigin="anonymous" defer></script>
and now I CORS finally isn't a problem anymore. This is all based on Stackoverflow questions posed previously but the code contains like 20 seperate answer codes from about as many questions so I didn't find the time to link them, sorry.
add a comment |
Still not entirely sure how to test which one doesn't work but I did find the solution.
I implemented 2 changes either one of which probably did the trick:
For one I added the
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
package to the WebConfig class and I changed
<script src="allstar.js" defer></script>
to
<script src="allstar.js" crossorigin="anonymous" defer></script>
and now I CORS finally isn't a problem anymore. This is all based on Stackoverflow questions posed previously but the code contains like 20 seperate answer codes from about as many questions so I didn't find the time to link them, sorry.
Still not entirely sure how to test which one doesn't work but I did find the solution.
I implemented 2 changes either one of which probably did the trick:
For one I added the
configuration.setAllowedOrigins(Arrays.asList("*"));
configuration.setAllowedMethods(Arrays.asList("*"));
configuration.setAllowedHeaders(Arrays.asList("*"));
package to the WebConfig class and I changed
<script src="allstar.js" defer></script>
to
<script src="allstar.js" crossorigin="anonymous" defer></script>
and now I CORS finally isn't a problem anymore. This is all based on Stackoverflow questions posed previously but the code contains like 20 seperate answer codes from about as many questions so I didn't find the time to link them, sorry.
answered Nov 24 '18 at 6:35
Eric EricsonEric Ericson
32
32
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53422932%2fhow-do-i-know-wether-the-server-or-the-client-is-failing-the-cors-request%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown