php Laravel DecryptException - 负载无效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44652194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 03:01:03  来源:igfitidea点击:

Laravel DecryptException - The payload is invalid

phplaravelapicookies

提问by ezero

I am sending an AJAX post request back to my Laravel API and receiving this error messsage:

我正在向我的 Laravel API 发送一个 AJAX 发布请求并收到此错误消息:

DecryptException in compiled.php line 13235: The payload is invalid.

在compiled.php 行13235 中的DecryptException:有效负载无效。

I am reading the XSRF-TOKEN from the cookie and sending that along as a request header named X-XSRF-TOKEN.

我正在从 cookie 中读取 XSRF-TOKEN 并将其作为名为 X-XSRF-TOKEN 的请求标头发送。

The site is a completely seperate site from the Laravel API but shares the same session, which is why I am getting the value from a cookie.

该站点是一个完全独立于 Laravel API 的站点,但共享相同的会话,这就是我从 cookie 中获取值的原因。

The strange thing is, occasionally it works. Any ideas what is causing this?

奇怪的是,偶尔它会起作用。任何想法是什么导致了这种情况?

回答by VnoitKumar

If you are sending X-XSRF-TOKENfrom JavaScript you can decode it using decodeURIComponent(). It converts %3Dto =.

如果您X-XSRF-TOKEN从 JavaScript发送,您可以使用decodeURIComponent(). 它转换%3D=.

回答by ezero

I found out the cause of the problem. The XSRF-TOKEN cookie value sometimes had a rogue character appended to the end: '%3D' - sometimes there are two of these on the end. No idea how they get there but when they are present, the verification fails.

我找到了问题的原因。XSRF-TOKEN cookie 值有时会在末尾附加一个流氓字符:'%3D' - 有时在末尾有两个。不知道他们是如何到达那里的,但是当他们在场时,验证失败。

If you base64_decode the cookie value, you get a json string which has the rogue character: '7' appended to the end so Laravel's decrypt method fails.

如果您对 cookie 值进行 base64_decode,您会得到一个 json 字符串,其中包含流氓字符:'7' 附加到末尾,因此 Laravel 的解密方法失败。

I ended up having to write my own CSRF verify function:

我最终不得不编写自己的 CSRF 验证函数:

$payload = base64_decode($request->header('X-XSRF-TOKEN'));

            //Remove any rogue chars from the end of the json  
            for($i=0; $i<strlen($payload); $i++){
                $lastChar = substr($payload, -1);
                if($lastChar != '}'){
                    $payload = substr($payload, 0, -1);
                } else {
                    break;
                }
            }

            //Needs to be base64 encoded when passed to decrypt
            $payload = base64_encode($payload);

            $headerToken = decrypt($payload);
            $cookieToken = $request->cookie('XSRF-TOKEN');

            //Compare tokens
            if($headerToken == $cookieToken){
                return true;
            } else {
                return false;
            }

回答by rayalois22

Here is a solution and steps that work for me in Laravel:

这是在 Laravel 中对我有用的解决方案和步骤:

  1. Include the CSRF token in your document's header as a meta tag named csrf-token:
  1. 将 CSRF 令牌作为名为csrf-token的元标记包含在文档的标题中:

<!-- CSRF Token -->
 <meta name="csrf-token" content="{{ csrf_token() }}">

  1. Create a JavaScript function to retrieve the value of the csrf-token meta tag:
  1. 创建一个 JavaScript 函数来检索 csrf-token 元标记的值:

function csrf(name="csrf-token"){
    const metas = document.getElementsByTagName('meta');
    for (let i = 0; i < metas.length; i++) {
        if (metas[i].getAttribute('name') === name) {
            return metas[i].getAttribute('content');
        }
    }
    
    return null;
}

  1. Set the X-CSRF-TOKEN header for your request, giving it the value of the csrf() function. An example using the Fetch API:
  1. 为您的请求设置 X-CSRF-TOKEN 标头,为其提供 csrf() 函数的值。使用 Fetch API 的示例:

let params = {headers:{}};
params.headers["Content-Type"] = "application/json; charset=UTF-8";
params.headers["X-CSRF-TOKEN"] = csrf(); // call your csrf() function
params.mode = "same-origin";
params.method = "POST";
let response = await fetch('/your-url', params);
// handle the response object

回答by Andy White

I had a similar issue but it seems to be related only to Google Chrome. I modified EncryptCookies to dd() whenever it encountered a decrypt exception:

我有一个类似的问题,但它似乎只与谷歌浏览器有关。每当遇到解密异常时,我将 EncryptCookies 修改为 dd():

protected function decrypt(Request $request)
{
    foreach ($request->cookies as $key => $c) {
        if ($this->isDisabled($key)) {
            continue;
        }

        try {
            $request->cookies->set($key, $this->decryptCookie($c));
        } catch (DecryptException $e) {
            dd('exception: ', $e, $key, $c, $request); // added by me
            $request->cookies->set($key, null);
        }
    }

    return $request;
}

Strangely, whenever I refresh the page, sometimes the DecryptException is thrown but most of the time the try statement succeeds. When I test in IE and Firefox, the try statement always succeeds. It seems to related to the amount of data in my request headers but the problem is non-deterministic.

奇怪的是,每当我刷新页面时,有时会抛出 DecryptException,但大多数时候 try 语句会成功。当我在 IE 和 Firefox 中测试时,try 语句总是成功。它似乎与我的请求标头中的数据量有关,但问题是不确定的。

回答by Mrudul Addipalli

it can also happen because of encryption / decryption error, where plain text from database is been decrypted by the decryption method/function, because you would have added some data directly into the database which needs to be encrypted bot inserted as plaintext , so it can be related to encryption / decryption issue.

它也可能由于加密/解密错误而发生,其中来自数据库的纯文本被解密方法/函数解密,因为您将一些数据直接添加到数据库中,这些数据需要作为明文插入的加密机器人,所以它可以与加密/解密问题有关。