cookie过大导致request 400 错误研究

问:get请求太长报400的错误,如何解决?生成系统中经常偶现此问题
问:get请求URL的长度是谁限制的?
问:每一个cookie的value的大小还是同域下cookie的个数做的限制?

现象:出现 400 Bad request

cookie过大导致request 400 错误研究_第1张图片

状态码400:客户端请求有语法错误,不能被服务器所理解。

问题:request header过大

一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求体4个部分组成。
cookie过大导致request 400 错误研究_第2张图片
谁对request header 大小做限制?

在HTTP规范RFC-2616中有这样一段描述:

The HTTP protocol does not place any a priori limit on the length of a URI. Servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET- based forms that could generate such URIs. A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15).
Note: Servers ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths.

HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URI长度进行限制,只是说如果server无法处理太长的URI,可以通过返回414状态码。

规范中虽然未对GET请求的长度做出明确的规定,但是在浏览器和应用服务器中对GET请求却做出限制或者相关的可配置:

  • Chrome:对Google浏览器URL的最大长度为8182个字符。
  • IE:对IE浏览器URL的最大长度为2083个字符。若超出这个数字,提交按钮没有任何反应。
  • Firefox:对Firefox浏览器URL的最大长度为65536个字符。
  • Safari: 对Safari浏览器URL的最大长度为80000个字符。
  • Apache能接受url长度限制为8192字符
  • nginx可以通过修改配置来改变url请求串的url长度限制:
    • client_header_buffer_size 默认值:1k
    • large_client_header_buffers默认值:4 8k

浏览器限制更多还是服务器限制更多?

实验分析

实验结论:浏览器允许的request header大小一般情况比Nginx服务器允许的大

测试方式:设置同样大小的cookie,通过浏览器直接访问服务器与通过浏览器先访问到Nginx再代理到服务器做对比得出。

const http = require('http');
const url = require('url');
const fs = require('fs-extra');

const server = http.createServer(async (req, res) => {
    if (req.url === '/index.html') {
        console.log(req.headers);
        const html = await fs.readFile('./index.html', 'utf8');
        const cookieArr = [];
        for (let i = 0; i < 10; i++) {
            cookieArr.push(`cookie${i}=${Array.from({ length: 80 }, (v, i) => 'abcdefghijklmnopq' + i).join('')}value${i}; `);
        }
        res.writeHead(200, {
            'Content-Type': 'text/html',
            'Set-Cookie': cookieArr
        });
        res.end(html);
    }
    if (req.url.startsWith('/postMethod')) {
        console.log('post');
        res.end('post');
    }
});
server.listen('3000', '127.0.0.1', () => {
    console.log('server runing...');
});
结论

过浏览器直接访问服务器的没有问题。
cookie过大导致request 400 错误研究_第3张图片

通过Nginx转发的存在问题

cookie过大导致request 400 错误研究_第4张图片

修改Nginx配置
  • client_header_buffer_size
    client_header_buffer_size size;
    Default: client_header_buffer_size 1k;
    Context: http, server

  • large_client_header_buffers
    Syntax: large_client_header_buffers number size;
    Default: large_client_header_buffers 4 8k;
    Context: http, server

解决方案总结:

  1. cookie要设置合理,不能太大,个数不能太多
  2. 合理设置时效性,max-age,expires
  3. get请求参数过长,出现参数丢失情况
  4. Nginx上修改允许request header头大小配置,很明显,当前的ng默认配置已不能满足需求。
  5. 临时解决方案:让用户清除cookie。影响:用户需要重新登录

你可能感兴趣的:(1024程序员节,nginx)