eggjs / egg

🥚 Born to build better enterprise frameworks and apps with Node.js & Koa
https://eggjs.org
MIT License
18.89k stars 1.81k forks source link

Egg.js中csrf的问题? #3558

Closed 750973092 closed 5 years ago

750973092 commented 5 years ago

What happens?

我现在遇到了一个问题,我在用Egg.js,Egg.js默认开启了csrf,POST请求都需要附带csrf请求头,csrfToken在Cookie中,问题是,我现在第一次访问是POST请求,但是Cookie里没有csrfToekn,所以这个接口访问的时候,就因为没有csrf头而被拦截了

比如说啊,我有一个注册的API,但是访问必须要携带存储在Cookie里的csrfToken,要获取csrfToken,必须先GET一次。然后呢,我第一次请求是POST,因为是注册API,所以Cookie里是没有csrfToken的

难道我注册之前,必须随便GET一下吗? 有demo吗

最小可复现仓库

请使用 egg-init --type=simple bug 创建,并上传到你的 GitHub 仓库

复现步骤,错误日志以及相关配置

相关环境信息

popomore commented 5 years ago

接口是异步的吧,页面渲染的时候就有 cookie

egg-bot commented 5 years ago

Hello @750973092. Please provide a reproducible example following the instruction.

Issues labeled by Need Reproduce will be closed if no activities in 7 days.


@750973092,请根据这个说明提供最小可复现代码。

如果在 7 天内没有进展会被自动关闭。

750973092 commented 5 years ago

是前后端分离,egg提供接口,但请求的时候第一个接口是POST请求,前端渲染的时候还没有cookie,因为还没有请求egg接口

popomore commented 5 years ago

跨域就把这个关掉,直接用 cors 吧

750973092 commented 5 years ago

跨域我后端不作处理,前端做了代理,所以还是前端第一次请求接口的时候是POST,但egg那时候cookie没有设置值

popomore commented 5 years ago

跨域的 csrf 用不了,如果是同域的,就在页面渲染的时候设置,不管谁来设。

cnvp commented 5 years ago

可以单独对某个接口过滤掉,不走csrf

yuzifu commented 5 years ago

遇到一样的问题,前端是vue-admin-template,后端是egg,访问egg实现的api时提示"missing csrf token"。 文档里关于CSRF问题,有一段话是这么说的:“在 CSRF 默认配置下,token 会被设置在 Cookie 中,在 AJAX 请求的时候,可以从 Cookie 中取到 token,放置到 query、body 或者 header 中发送给服务端。” 所以我在vue-admin-template的request拦截器里增加了设置csrf token:

// request拦截器
service.interceptors.request.use(
  config => {
    if (store.getters.token) {
      config.headers['X-Token'] = getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    config.headers['x-csrf-token'] = Cookies.get('x-csrf-token') // 增加csrf token
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

但是调试发现Cookies.get('x-csrf-token')获取的值是undefine

unclexiao commented 5 years ago

@ yuzifu 你在前端拦截器里设置了request的header,为何要在后端的cookies里去取呢,当然拿不到呀。 ctx.request.header["x-csrf-token"]试过了么?config.security.domainWhiteList配置了吗?

yuzifu commented 5 years ago

@ yuzifu 你在前端拦截器里设置了request的header,为何要在后端的cookies里去取呢,当然拿不到呀。 ctx.request.header["x-csrf-token"]试过了么?config.security.domainWhiteList配置了吗?

已经按文档启用了egg-cors,跨域工作是正常的。 上面的代码是vue-admin-template里的,用意是给前端的post请求设置csrf token。

lky5230 commented 5 years ago

第一个post请求过来egg过滤掉csrf,回给前端csrf值让其他接口弄上x-csrf-token, exports.security = { csrf: { ignore: '/example' }, };

egg-bot commented 5 years ago

This issue is closed because it has been marked as Need Reproduce, but has not had recent activity. If you can provide a reproduce, feel free to ping anyone of our maintainers to reopen this issue. Thank you for your contributions.

meguoe commented 4 years ago

第一个post请求过来egg过滤掉csrf,回给前端csrf值让其他接口弄上x-csrf-token, exports.security = { csrf: { ignore: '/example' }, };

你这样成功了吗?我把登录接口设置为ignore后,可以正常登录,但并没有返回csrf token。

sinceseason commented 3 years ago

第一个post请求过来egg过滤掉csrf,回给前端csrf值让其他接口弄上x-csrf-token, exports.security = { csrf: { ignore: '/example' }, };

你这样成功了吗?我把登录接口设置为ignore后,可以正常登录,但并没有返回csrf token。

问题解决了吗,我也遇到了同样问题

meguoe commented 3 years ago

第一个post请求过来egg过滤掉csrf,回给前端csrf值让其他接口弄上x-csrf-token, exports.security = { csrf: { ignore: '/example' }, };

你这样成功了吗?我把登录接口设置为ignore后,可以正常登录,但并没有返回csrf token。

问题解决了吗,我也遇到了同样问题

可以的。

meguoe commented 3 years ago

第一个请求中执行一下 ctx.rotateCsrfSecret()

sinceseason commented 3 years ago

第一个请求中执行一下 ctx.rotateCsrfSecret()

为什么加上了还是没有呢?需要其他依赖吗? 我是这么写的

 // config.default.ts
  config.security = {
    csrf: {
      useSession: true,
            headerName: "x-csrf-token", // 自定义请求头
            ignore: ['/user/csrf']
        },
  }
 // userController
    async testCsrf() {
        const ctx = this.ctx;
        ctx.rotateCsrfSecret()
        ctx.body = {
            name: 'test'
        };
    }
puluomia22 commented 2 years ago
  1. 配置第一个请求过滤csrf config.security.csrf.ignore = '/first'
  2. /first 接口实现返回 csrfToken ctx.rotateCsrfSecret()

注意: js 读取不到csrfToken cookies 时,按下面方法排查下。