크로스 도 메 인 cors 이해

7553 단어 전단node.js
이 글 은 개발 과정 에서 앞 뒤 가 어떻게 크로스 오 버 문 제 를 해결 하 는 지 설명 하고 크로스 오 버 자원 공유 에 관 한 이론 지식 은 읽 기 MDN 크로스 소스 자원 공유 (CORS) 의 글 을 통 해 알 수 있다.
크로스 도 메 인 을 해결 하 는 수단 은 매우 많은 데 여 기 는 주로 백 엔 드 nodejs 를 통 해 예 를 들 수 있다.
준비 작업
우 리 는 동원 전략 약정 , , 세 가지 가 같 아야 자원 에 접근 할 수 있다 는 것 을 알 고 있 습 니 다. 여 기 는 nodejs 를 통 해 서로 다른 포트 의 크로스 도 메 인 요청 환경 을 만 듭 니 다.
api 인터페이스 서비스
  • api.js
  • // api.js
    const handleRequest = (req, res) => {
        res.end(JSON.stringify({result:"success"})
    )}
    
    require("http").createServer(handleRequest).listen(3000)

    전단 서비스
    프론트 서비스 index.htmlserver.js
  • server.js
  • index.html
  • // server.js
    const fs = require("fs")
    const path = require("path")
    
    const handleRequest=(req,res)=>{
        const indexpath = path.resolve(__dirname, "./index.html");
        fs.createReadStream(indexpath).pipe(res)
    };
    
    require("http").createServer(handleRequest).listen(8080)
    //index.html
    
    
        const request = new XMLHttpRequest();
        request.responseType="json";
        request.open("GET","http://127.0.0.1:3000",true);
        request.onload = ()=>{
            console.log(request.response);
        }
        request.send();
    
    

    시작 서비스nodejs 환경 에서 실행 node apinode server 브 라 우 저 를 열 고 입력 http://127.0.0.1:8080 을 하면 콘 솔 에서 오류 정 보 를 볼 수 있 습 니 다.
    Access to XMLHttpRequest at 'http://127.0.0.1:3000/' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

    Access-Control-Allow-Origin
    크로스 필드 해결 첫 번 째 단 계 는 응답 헤드 설정 Access-Control-Allow-Origin 입 니 다.
    Access-Control-Allow-Origin:  | *
    origin 매개 변수의 값 은 이 자원 에 접근 할 수 있 는 외부 도 메 인 URI 를 지정 합 니 다. 마스크 * 는 모든 것 을 허용 하고 수정 api.js 은 다음 과 같 습 니 다.
    const handleRequest = (req, res) => {
        res.setHeader("Access-Control-Allow-Origin", "*")
        res.end(JSON.stringify({result:"success"}))
    }

    다시 시작 node api, 새로 고침 8080 의 주 소 를 보면 도 메 인 을 넘 어 방문 하 는 자원 을 볼 수 있 습 니 다.
    Access-Control-Allow-Methods
    프로젝트 에서 사용 RESTful API 하면 getpost 요청 을 제외 하고 deleteput 등 요청 이 있 을 것 입 니 다. 저 희 는 수정 index.html 하고 delete 요청 으로 바 꿉 니 다.
     request.open("DELETE","http://127.0.0.1:3000",true);

    브 라 우 저 를 열 면 콘 솔 에 도 메 인 을 뛰 어 넘 는 오류 메시지 가 나타 납 니 다.
    Access to XMLHttpRequest at 'http://127.0.0.1:3000/' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: Method DELETE is not allowed by Access-Control-Allow-Methods in preflight response.

    수정 api.js, Access-Control-Allow-Methods 속성 을 추가 하면 이 문 제 를 해결 할 수 있 습 니 다.
    res.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS")

    Access-Control-Max-Age
    브 라 우 저 콘 솔 Network 에서 매번 보 내 는 XHR 요청 이 하나의 options 요청 을 가 져 오 는 것 을 볼 수 있 습 니 다. 이 는 브 라 우 저 는 먼저 OPTIONS 방법 으로 예비 검사 요청 (preflight request) 을 해 야 하기 때 문 입 니 다. 서버 에서 이 크로스 소스 요청 을 허용 하 는 지 알 수 있 습 니 다. 응답 헤드 에 추가 할 수 있 습 니 다 Access-Control-Max-Age.매번 사전 검사 요청 을 보 내지 않도록 options 발송 빈 도 를 제한 합 니 다.
    res.setHeader("Access-Control-Max-Age", 86400)
    Access-Control-Max-Age 이 응답 의 유효 시간 은 86400 초, 즉 24 시간 임 을 나타 낸다.유효 시간 내 에 브 라 우 저 는 같은 요청 을 위해 다시 예비 검사 요청 을 할 필요 가 없습니다.
    브 라 우 저 자체 가 최대 유효 시간 을 유지 하고 있 습 니 다. 이 첫 번 째 필드 의 값 이 최대 유효 시간 을 초과 하면 유효 하지 않 습 니 다.
    Access-Control-Allow-Headers
    앞 뒤 통신 에서 저 희 는 요청 헤더 에 tokan 정 보 를 서버 에 보 내 고 수정 index.html 은 다음 과 같 습 니 다.
        request.open("POST","http://127.0.0.1:3000/get",true);
        request.responseType="json";
    +    request.setRequestHeader("Authorization","token");
        request.onload = ()=>{
            console.log(request.response);
        }
        request.send();

    브 라 우 저 콘 솔 을 열 면 새로운 크로스 오 버 정 보 를 볼 수 있 습 니 다.
    Access to XMLHttpRequest at 'http://127.0.0.1:3000/get' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: Request header field authorization is not allowed by Access-Control-Allow-Headers in preflight response.

    수정 api.js, 추가 Access-Control-Allow-Headers, 실제 요청 에서 휴대 할 수 있 는 첫 번 째 필드 를 가리 키 기:
    res.setHeader("Access-Control-Allow-Headers", "Content-Type,Authorization")

    Access-Control-Allow-Credentials
    일부 폼 을 사용 하거나 구성 요소 라 이브 러 리 를 업로드 할 때 withCredentials 이 속성의 설정 을 자주 볼 수 있 습 니 다. 도 메 인 을 뛰 어 넘 는 상황 에서 설정 한 cookies 은 서버 에 전송 되 지 않 기 때문에 백 엔 드 응답 헤드 Access-Control-Allow-Credentialstrue 일 때 만 cookies 정 보 를 얻 을 수 있 습 니 다.
    // index.html
    request.withCredentials = true;
    document.cookie="name=chenwl";
    res.setHeader("Access-Control-Allow-Credentials",true)

    그러나 설정 Access-Control-Allow-Credentials 을 하 더 라 도 여기 백 엔 드 는 cookies 정 보 를 얻 을 수 없습니다. 이전 Access-Control-Allow-Origin 에 '*' 로 설정 되 었 기 때문에 요청 페이지 와 일치 하 는 도 메 인 이름 을 명확 하고 지정 해 야 합 니 다. 수정 Access-Control-Allow-Origin 은 다음 과 같 습 니 다.
    res.setHeader("Access-Control-Allow-Origin", req.headers.origin)

    통상 적 인 상황 에서 우 리 는 Access-Control-Allow-Origin 을 위해 화이트 리스트 를 설정한다.
    const corsWhitelist = [
      "https://domain1.example",
      "https://domain2.example",
      "https://domain3.example",
    ]
    if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
        res.setHeader("Access-Control-Allow-Origin", req.headers.origin)
    }

    전체 코드
    api.js
    const handleRequest = (req, res) => {
        res.setHeader("Access-Control-Allow-Origin", req.headers.origin)
        res.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS")
        res.setHeader("Access-Control-Allow-Headers", "Content-Type,Authorization")
        res.setHeader("Access-Control-Max-Age", 86400)
        res.setHeader("Access-Control-Allow-Credentials", true)
    
        res.end(JSON.stringify({ cookie: req.headers.cookie }))
    }
    
    require("http").createServer(handleRequest).listen(3000)
    index.html
    
    
        let request = new XMLHttpRequest();
        request.open("POST","http://127.0.0.1:3000/get",true);
        request.responseType="json";
        request.setRequestHeader("Authorization","tokena");
        request.setRequestHeader("Content-Type","application/json;charsrt=utf-8");
        request.withCredentials = true;
        document.cookie="name=chenwl";
        request.onload = ()=>{console.log(request.response)}
        request.send();
    
    

    좋은 웹페이지 즐겨찾기