Как я узнаю, что Сервер или Клиент не выполняют запрос Cors? - PullRequest
0 голосов
/ 22 ноября 2018

Итак, я делаю Restful Webservice с Springtoolsuite, и я также делаю Rest Client.Я нахожусь в точке, в которой я могу запустить службу и заставить как Почтальона дать мне ожидаемые результаты, так и запустить внутренний Браузер Spring, и у меня будут происходить правильные вещи.

Однако, если я затем загружуHTML-файл вне браузера Springs im получает типичные ошибки CORS «Запрос CORS не выполнен» и «Предварительный канал CORS не выполнен» в Mozilla, а в Chrome я получаю 403 для OPTIONS и «доступ к XMLHttpRequest по адресу http://localhost:8080/.." от источника 'null' было заблокировано политикой CORS: Ответ на запрос предварительной проверки не проходит проверку контроля доступа: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». "что также является проблемой CORS.

localhost: 8080 - мой выбор URL, потому что Apache Tomcat запускает службу на этом порту, когда я запускаю проект как приложение Spring Boot.

Что ясейчас я не уверен, как узнать, что я делаю плохо сформулированные запросы в своем клиенте отдыха или нет. У меня есть проблема в моем серверном коде, например, предположительно, ошибка может возникать из-за предварительной проверки несколько раз, и я не уверен, что могу это делать.

Сначала серверный код:

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", "*");
        } }

это Apllicationcontroller, который обрабатывает запросы.У меня также есть класс безопасности, который я пытался изменить таким образом, чтобы разрешить все возможности и проблемы с CORS `

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;
    }

}

дополнительно в соответствии с другим ответом stackoverflow, я создал другой класс для добавления поддержки cors

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("/**");
    }
}`

, что тоже не помогло, я также добавил пару зависимостей в соответствии с другими ответами, и теперь мой pom.xml выглядит так:

    <?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>

Я делаю это безфайл web.xml, поэтому, конечно, все ответы о том, как изменить web.xml для добавления поддержки CORS, также не помогли.Это все вещи на стороне сервера, которые, по моему мнению, теперь могут повлиять на поддержку CORS на клиентской стороне.

HTML довольно безопасен, единственные релевантные строки -

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="allstar.js" defer></script>

, которыеУ меня в голове, положив их в конец корпуса ничего не изменилось.Ниже приведены два соответствующих файла js:

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);
     }

, которые обрабатывают щелчки кнопок на разных кнопках и запускают соответствующий файл js.У меня есть методы POST PUT и DELETE в контроллере приложения и файлы для каждого из них, но я хочу, по крайней мере, запустить GET и пойти дальше.Итак, вот файл JS для запроса GET, который выполняет всю клиентскую часть остального обмена:

   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);
    }
});

Я попытался добавить Origin: к этому, но он не распознается и выдает только ошибку.Изменение типа текста или json ничего не дало.Таким образом, после реализации множества решений как для сервера, так и для клиента, я по-прежнему блокируюсь одной и той же политикой-источником, и мой главный вопрос - как я могу проверить, какая из двух сторон здесь неисправна, чтобы я знал, что работатьна.Заранее спасибо.

1 Ответ

0 голосов
/ 24 ноября 2018

Все еще не совсем уверен, как проверить, какой из них не работает, но я нашел решение.Я реализовал 2 изменения, одно из которых, вероятно, помогло:

Для одного я добавил пакет

configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowedMethods(Arrays.asList("*"));
    configuration.setAllowedHeaders(Arrays.asList("*"));

в класс WebConfig и изменил

<script src="allstar.js" defer></script>

на

<script src="allstar.js" crossorigin="anonymous" defer></script>

и теперь я CORS, наконец, больше не проблема.Все это основано на вопросах Stackoverflow, заданных ранее, но код содержит около 20 отдельных кодов ответов из примерно такого количества вопросов, поэтому я не нашел времени для их связи, извините.

...