POST 请求不工作,但 GET 工作正常。请求的资源上不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】POST 请求不工作,但 GET 工作正常。请求的资源上不存在“Access-Control-Allow-Origin”标头【英文标题】:POST request is not working, but GET is working fine. No 'Access-Control-Allow-Origin' header is present on the requested resource 【发布时间】:2020-01-02 04:11:19 【问题描述】:

我有一个 POST 和一个 GET 方法,它们来自触发请求的同一个域。虽然,我觉得 CORS 不会成为问题,但似乎是,因为端口不同。

添加标头后,我可以设法处理我的 GET 请求,但 POST 不起作用。

我已经在服务器端添加了标题,下面是代码:

    @SuppressWarnings("unchecked")
    @RequestMapping(method=RequestMethod.OPTIONS,value="/refer")
    public ResponseEntity<?> options()
        return new ResponseEntity(getHeaders(), HttpStatus.OK);

    


    @RequestMapping(method=RequestMethod.GET,value="/search",produces="application/json")
    public ResponseEntity<?> searchCook(@ModelAttribute("cookSearch") CookSearch cookSearch)

        ResponseDto<List<DtoCook>> response = new ResponseDto<>();
        List<DtoCook> results = serviceCook.search(cookSearch);
        response.setData(results);
        response.setMessage(results.size()+" found.");
        return new ResponseEntity<>(response, getHeaders(),HttpStatus.OK);

    


    @SuppressWarnings("unchecked")
    @RequestMapping(method=RequestMethod.POST,value="/refer",produces="application/json",consumes="application/json")
    public ResponseEntity<?> referCookPost(@ModelAttribute("dtoCookRefer") DtoCookRefer dtoCookRefer,BindingResult result) 

        System.out.println("in cook rest controller");

        // set the headers to allow CORS
        MultiValueMap<String, String> headers = getHeaders();

        System.out.println(dtoCookRefer.getCookName()+ " phone");
        ResponseDto<DtoCookRefer> respDto = new ResponseDto<>();
        respDto.setData(dtoCookRefer);

        //run Spring validator manually
        new CookReferValidator().validate(dtoCookRefer, result);

        if(serviceCookRefer.checkUniquePhNum(dtoCookRefer)) 
            respDto.setMessage("Phone number already present");
            return new ResponseEntity<>(respDto, headers,HttpStatus.UNPROCESSABLE_ENTITY);
        


        // validate cook data
        if(result.hasErrors()) 
            //TODO set message source
            respDto.setMessage("Improper data");
            return new ResponseEntity<>(respDto, headers,HttpStatus.UNPROCESSABLE_ENTITY);


        else 
            // save data to database
            serviceCookRefer.referCook(dtoCookRefer);
            // return proper response
            respDto.setMessage("Processed Successfully");
            return new ResponseEntity(respDto, headers, HttpStatus.OK);
        


    

    private MultiValueMap<String, String> getHeaders()

        MultiValueMap<String, String> headers = new LinkedMultiValueMap<String,String>();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.add("Access-Control-Allow-Origin","http://example.org");
        headers.add("Access-Control-Allow-Methods","GET,PUT,POST,DELETE,OPTIONS");
        headers.add("Access-Control-Allow-Headers", 
                "Cache-Control,Pragma,Expires,Access-Control-Allow-Origin,"
                + "Access-Control-Allow-Methods,Content-Type,Transfer-Encoding,Date");
        return headers;
    

下面是 Angular 中的代码:

import  Injectable  from '@angular/core';
import HttpClient, HttpHeaders from '@angular/common/http';
import  CookRefer  from './cook-refer';

@Injectable(
  providedIn: 'root'
)
export class CookReferService 
  private _url : string = "http://123.121.166.243:8080/ffc/ext/cook/refer";
  constructor(private _http : HttpClient)  

  headers = new HttpHeaders(
    'Content-Type':'application/json',
    'Access-Control-Request-Method':'POST'
  );

  options=headers:this.headers;

  
  refer(cook : CookRefer)
    return this._http.post<any>(this._url,cook,this.options);
  
我什至添加了一个 OPTIONS 方法,但没有帮助。我不确定是否有必要。我需要以下几点帮助: 看起来浏览器阻止了 CORS 请求。请求甚至没有到达服务器。 尤其是对于 POST,它甚至在我在客户端(角度)端添加标头之前就触发了预检请求,但对于 GET 则不是。 为什么 GET 有效但 POST 无效?

【问题讨论】:

【参考方案1】:

也许你应该在你的帖子请求中添加标题 Access-Control-Request-Method ,在你允许的标题中。

尝试在您的控制器上使用 CrossOrigin 注释,而不是添加 options 方法,或者如果您希望仅允许一种方法使用 CORS,请在您的方法上使用:

@CrossOrigin
@RestController
public class Controller 

    // @CrossOrigin
    @RequestMapping("/link")
    public String retrieve() 
       // ...
    

您也可以从控制器中进行全局 Cors 配置,例如:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer 

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/**");
    

【讨论】:

尝试放注解时,spring/java 无法导入jar。我也尝试过全局配置。我正在使用弹簧 4。 这个注解在spring 4.2引入【参考方案2】:

需要下面的标题

headers.add("Access-Control-Allow-Credentials","true");

由于浏览器控制台出错,我不得不删除 'Access-Control-Request-Method':'POST'

注释@CrossOrigin 确实添加了我手动添加的相同标题。

现在,我在以下给出的链接中找到了我的问题的答案:

Tells why we need Access-Control-Allow-Credentials header

What exactly does the Access-Control-Allow-Credentials header do?

Why is there no preflight in CORS for POST requests with standard content-type

当我用谷歌搜索一般错误时,我很难找到问题的答案,因为网站上发布的主题太具体,我不知道。

感谢您为@tcharaf 的答案指明方向。

【讨论】:

以上是关于POST 请求不工作,但 GET 工作正常。请求的资源上不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

req.user 在 axios POST 请求中未定义,但 GET 工作正常

为啥我的 POST 请求在部署时被 CORS 阻止但它在本地工作

jQuery .ajax() POST 请求抛出 405(不允许的方法)但 GET 不会

Angular 7:发送 post 请求给出错误 405(不允许的方法)

Axios POST 请求抱怨跨域,但 curl 请求工作正常

CORS 正在阻止 PUT、DELETE 和 POST 请求,但 GET 正在工作