簡體   English   中英

Spring 啟動 CORS

[英]Spring Boot CORS

我正在嘗試運行 Spring Boot 並設置我的 RestConroller 以將 json 返回到我的 angular 項目。 我在 class 級別添加了 @CrossOrigin(origins = " ", allowedHeaders = " ") 但我的網站仍然返回以下錯誤。

本質上,我試圖讓在我的 S3 存儲桶中運行的 Angular 應用程序連接到在 Kubernetes pod 中運行的 Spring 引導應用程序以運行 Kafa 生產者和消費者的東西。 當我在本地(在不同的端口上)運行我的 Kafka 和 Spring 和 Angular 時,它都可以工作,但是當我嘗試在我的 S3 和我的容器中讓它工作時,它會失敗並出現下面的 corrs 錯誤。 因為這是一個學校項目,我不關心獲得 corrs 安全性的細節,我只希望它允許一切,所以當我通過我的 Angular 應用程序提交數據時,我可以證明我的 Kafa 東西在 Spring 端有效。

更正錯誤

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://<IPADDR>:8080/survey-submit. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://<IPADDR>:8080/survey-submit. (Reason: CORS request did not succeed).

ERROR 
{…}
​
error: error { target: XMLHttpRequest, isTrusted: true, lengthComputable: false, … }
​
headers: Object { normalizedNames: Map(0), lazyUpdate: null, headers: Map(0) }
​
message: "Http failure response for http://<IPADDR>:8080/survey-submit: 0 Unknown Error"
​
name: "HttpErrorResponse"
​
ok: false
​
status: 0
​
statusText: "Unknown Error"
​
url: "http://<IPADDR>:8080/survey-submit"

Angular 的調查表代碼

import { Component, OnInit } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from 'rxjs';

import {FormArray, FormBuilder, FormControl, FormGroup, Validators} from '@angular/forms';
import {Router} from '@angular/router';

@Component({
  selector: 'app-survey',
  templateUrl: './survey.component.html',
  styleUrls: ['./survey.component.css']
})

export class SurveyComponent implements OnInit {
    private surveyForm: FormGroup;
    private likeBest: Array<String> = ['Students', 'Location', 'Campus', 'Atmosphere', 'Dorms', 'Sports'];
    private  selectedBest = [];
    private response: string;

    constructor(private http: HttpClient, private _fb: FormBuilder, private router: Router) {

        this.surveyForm = new FormGroup({
            firstName: new FormControl(),
            lastName: new FormControl(),
            addrStreet: new FormControl(),
            addrCity: new FormControl(),
            addrState: new FormControl(),
            addrZip: new FormControl(),
            phone: new FormControl(),
            email: new FormControl(),
            date: new FormControl(),
            likeBest: this.addLikeBest(),
            howHeard: new FormControl(),
            recommendLikelihood: new FormControl()
        });
  }

  addLikeBest() {
        const  arr = this.likeBest.map(e => {
            return this._fb.control(false)
        })
     return this._fb.array(arr);
  }

  get likeBestAry() {
        return <FormArray>this.surveyForm.get('likeBest')
  }

    getSelectedBestValues() {
        this.selectedBest = [];
        this.likeBestAry.controls.forEach((control, i) => {
            if (control.value) {
                this.selectedBest.push(this.likeBest[i])
            }
        })
    }

  ngOnInit(): void {
  }

  private postData() {
     console.log(this.selectedBest)
    const inputData = {
                   nameFirst: this.surveyForm.value.firstName,
                   nameLast: this.surveyForm.value.lastName,
                   addrStreet: this.surveyForm.value.addrStreet,
                   addrCity: this.surveyForm.value.addrCity,
                   addrState: this.surveyForm.value.addrState,
                   addrZip: this.surveyForm.value.addrZip,
                   phone: this.surveyForm.value.phone,
                   email: this.surveyForm.value.email,
                   date: this.surveyForm.value.date,
                   likeBest: this.selectedBest.join(),
                   howHeard: this.surveyForm.value.howHeard,
                   recommendLikelihood: this.surveyForm.value.recommendLikelihood
    }

    this.http.post<any>('http://<IPFORSPRINGBOOTCONTAINER>:8080/survey-submit', inputData).subscribe({
      next: data => {
        console.log("test " + data);
        this.response = 'Item Saved.';
      }
    })
  }
}

Spring 引導 Kafka 配置


import edu.swe645.walton.hw1.model.Survey;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.*;
import org.springframework.kafka.support.serializer.JsonSerializer;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class KakfaConfiguration {

    Logger logger = LoggerFactory.getLogger("KakfaConfiguration.class");

    @Bean
    public ProducerFactory<String, Survey> producerFactory() {
        Map<String, Object> config = new HashMap<>();
        try {
            config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "<KAFKAIP>:31852");
            config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
            config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);


        } catch (Exception e){
            logger.error("Error in class KakfaConfiguration, Method producerFactory, Message - " +e.getMessage());
        }
        return new DefaultKafkaProducerFactory<>(config);
    }


    @Bean
    public KafkaTemplate<String, Survey> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }

    @Bean
    public ConsumerFactory<String, String> consumerFactory() {
        Map<String, Object> config = new HashMap<>();
        try {
            config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "<KAFKAIP>:31852");
            config.put(ConsumerConfig.GROUP_ID_CONFIG, "group_id");
            config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
            config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        }
        catch (Exception e){
            logger.error("Error in class KafkaConfiguration, Method consumerFactory, Message - " + e.getMessage());
        }
        return new DefaultKafkaConsumerFactory<>(config);
    }


    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() {
        ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory();
        factory.setConsumerFactory(consumerFactory());
        return factory;
    }



}

Spring 啟動 Controller

package edu.swe645.walton.hw1.resource;

import edu.swe645.walton.hw1.listner.KafkaConsumer;
import edu.swe645.walton.hw1.model.Survey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@Configuration
@CrossOrigin(origins = "*", allowedHeaders = "*")
public class SurveyResource {
    @Autowired
    private KafkaTemplate<String, Survey> kafkaTemplate;

    @Autowired
    private KafkaConsumer myTopicConsumer;
    Logger logger = LoggerFactory.getLogger("SurveyResource.class");

    private static final String TOPIC = "survey-data-topic";
    private int keyCounter = 0;

    @PostMapping(path="/survey-submit")
    public void postSurvey(@RequestBody Survey s)
    {
        try {
            kafkaTemplate.send(TOPIC, "mykey" + ++keyCounter, s);
        }
        catch (Exception e){
            logger.error("Error in class SurveyResource, Method postSurvey, Message - " + e.getMessage());
        }
    }

    @GetMapping(path="/old-surveys", produces = "application/json")
    public List<Survey> getMessages() {
        return myTopicConsumer.getMessages();
    }
}

編輯:我現在得到這個.... 在此處輸入圖像描述

我在 Chrome 中看到了這個在此處輸入圖像描述

您可以將其添加為過濾器,如下所示

@Component
public class CORSAllowFilter implements Filter {


    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");    
        chain.doFilter(req, response);
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM