美文网首页
跨域问题

跨域问题

作者: ShoneSingLone | 来源:发表于2020-11-17 11:50 被阅读0次

cookie-samesite

const Koa = require('koa');
const app = new Koa();
const cors = require('@koa/cors');

// logger

app.use(cors({
    origin: ctx => {
        const allowedList = [
            "http://localhost:8080"
        ];
        if (allowedList.includes(ctx.request.header.origin)) {
            return ctx.request.header.origin
        } else {
            return false;
        }
    }
}));

app.use(async ctx => {
    const {
        request,
        cookies
    } = ctx;
    const {
        url
    } = request;
    const dataFromFront = cookies.get("data");
    console.log("dataFromFront", dataFromFront, ctx.cookies.get("HttpOnly"), 
    ctx.cookies.get("dataFromBack"));

    if (url === "/api") {
        ctx.set("Content-Type", "application/json");
        ctx.set("Access-Control-Allow-Credentials", true);
        // httponly 无法被前端读取,但是可以带回来
        ctx.cookies.set("dataFromBack", `update by back server ${dataFromFront}`);
        ctx.cookies.set("HttpOnly", "can not read by front");
        ctx.body = JSON.stringify({
            dataFromFront
        })
    } else {
        ctx.cookies = "";
        ctx.body = 'Hello World';
    }

});

app.on('error', err => {
    console.error('server error', err)
});

app.listen(3000);
HttpOnly无法访问
  <div id="app">
    <pre style="text-align: left"
      >{{ JSON.stringify(data, null, 2) }}
    </pre>
    <input v-model="cookieData" />
    <button @click="getData">getData</button>
  </div>
import axios from "axios";
import cookies from "js-cookie";

export default {
  name: "App",
  methods: {
    async getData() {
      try {
        axios.defaults.withCredentials = true;
        document.cookie = "native=setcookiestring";
        cookies.set("data", `front${this.cookieData}`);
        const res = await axios.get("http://localhost:3000/api");
        this.data = {
          dataFromFront: res.data.dataFromFront,
          //document.cookie 无法获取HttpOnly的cookie
          dataFromCookie: document.cookie,
          dataFromBack: document.cookie,
        };
      } catch (error) {
        console.log("mounted -> error", error);
      }
    },
  },
  data() {
    return {
      data: "",
      cookieData: "",
    };
  },
};

Koa CORS中间件

'use strict';

const vary = require('vary');

/**
 * CORS middleware
 *
 * @param {Object} [options]
 *  - {String|Function(ctx)} origin `Access-Control-Allow-Origin`, default is request Origin header
 *  - {String|Array} allowMethods `Access-Control-Allow-Methods`, default is 'GET,HEAD,PUT,POST,DELETE,PATCH'
 *  - {String|Array} exposeHeaders `Access-Control-Expose-Headers`
 *  - {String|Array} allowHeaders `Access-Control-Allow-Headers`
 *  - {String|Number} maxAge `Access-Control-Max-Age` in seconds
 *  - {Boolean} credentials `Access-Control-Allow-Credentials`
 *  - {Boolean} keepHeadersOnError Add set headers to `err.header` if an error is thrown
 * @return {Function} cors middleware
 * @api public
 */
module.exports = function (options) {
  const defaults = {
    allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH',
  };

  options = {
    ...defaults,
    ...options,
  };

  if (Array.isArray(options.exposeHeaders)) {
    options.exposeHeaders = options.exposeHeaders.join(',');
  }

  if (Array.isArray(options.allowMethods)) {
    options.allowMethods = options.allowMethods.join(',');
  }

  if (Array.isArray(options.allowHeaders)) {
    options.allowHeaders = options.allowHeaders.join(',');
  }

  if (options.maxAge) {
    options.maxAge = String(options.maxAge);
  }

  options.keepHeadersOnError = options.keepHeadersOnError === undefined || !!options.keepHeadersOnError;

  return async function cors(ctx, next) {
    // If the Origin header is not present terminate this set of steps.
    // The request is outside the scope of this specification.
    const requestOrigin = ctx.get('Origin');

    // Always set Vary header
    // https://github.com/rs/cors/issues/10
    ctx.vary('Origin');

    if (!requestOrigin) return await next();

    let origin;
    if (typeof options.origin === 'function') {
      origin = options.origin(ctx);
      if (origin instanceof Promise) origin = await origin;
      if (!origin) return await next();
    } else {
      origin = options.origin || requestOrigin;
    }

    let credentials;

    if (typeof options.credentials === 'function') {
      credentials = options.credentials(ctx);
      if (credentials instanceof Promise) credentials = await credentials;
    } else {
      credentials = !!options.credentials;
    }

    const headersSet = {};

    function set(key, value) {
      ctx.set(key, value);
      headersSet[key] = value;
    }

    if (ctx.method !== 'OPTIONS') {
      // Simple Cross-Origin Request, Actual Request, and Redirects
      set('Access-Control-Allow-Origin', origin);
      if (credentials === true) {
        set('Access-Control-Allow-Credentials', 'true');
      }

      if (options.exposeHeaders) {
        set('Access-Control-Expose-Headers', options.exposeHeaders);
      }

      if (!options.keepHeadersOnError) {
        return await next();
      }
      try {
        return await next();
      } catch (err) {
        const errHeadersSet = err.headers || {};
        const varyWithOrigin = vary.append(errHeadersSet.vary || errHeadersSet.Vary || '', 'Origin');
        delete errHeadersSet.Vary;

        err.headers = {
          ...errHeadersSet,
          ...headersSet,
          ...{
            vary: varyWithOrigin
          },
        };
        throw err;
      }
    } else {
      // Preflight Request

      // If there is no Access-Control-Request-Method header or if parsing failed,
      // do not set any additional headers and terminate this set of steps.
      // The request is outside the scope of this specification.
      if (!ctx.get('Access-Control-Request-Method')) {
        // this not preflight request, ignore it
        return await next();
      }

      ctx.set('Access-Control-Allow-Origin', origin);

      if (credentials === true) {
        ctx.set('Access-Control-Allow-Credentials', 'true');
      }

      if (options.maxAge) {
        ctx.set('Access-Control-Max-Age', options.maxAge);
      }

      if (options.allowMethods) {
        ctx.set('Access-Control-Allow-Methods', options.allowMethods);
      }

      let allowHeaders = options.allowHeaders;
      if (!allowHeaders) {
        allowHeaders = ctx.get('Access-Control-Request-Headers');
      }
      if (allowHeaders) {
        ctx.set('Access-Control-Allow-Headers', allowHeaders);
      }

      ctx.status = 204;
    }
  };
};

相关文章

网友评论

      本文标题:跨域问题

      本文链接:https://www.haomeiwen.com/subject/gblxiktx.html