Axios gets a new session id with every request, and also refuses to send csrf, but why?

huangapple go评论61阅读模式
英文:

Axios gets a new session id with every request, and also refuses to send csrf, but why?

问题

I'm here to provide translations for the non-code parts of your text. Here's the translated content:

"I'm making a webshop with laravel api and vuejs components.
If you "add to cart" an item, it sends a post request to the api, makes a record in the "CartData" table with your session id, then saves the given product to another table (with hasMany relationship), called "CartItems," setting the cart id from the given CartData.

So at the end it should look something like this:

cartData:

id session_id
4 ASDABC123

cartItems:

id cart_data_id product_id product_data
1 4 2 data of the product in json

but right now, it generates a new session data in every single request, so in every single "add to cart" click. However, when I do "session()->getId()" in the blade template, it displays the same exact session ID.

How could I fix that? Why is this happening, am I missing something?

the "buy" method in vue (app):

axios.post(
'api/cart/add',
{
product_id: item.id,
product_data: JSON.stringify(item),
}).then(
response => {
console.log(response);
toastr.success(item.name + ' added to cart!', 'Success');
}).catch(error => {
console.log(error);
toastr.error('Something went wrong!', 'Error');
});
}, ```

About the CSRF part:

``` /**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

import axios from 'axios';
window.axios = axios;

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; ```

this is in the bootstrap.js file that's being imported in the very first line of app.js (main js) file.

so based on the default comment in it, it should be using csrf token automatically, no?

I also have this in my header:

`<meta name="csrf-token" content="{{ csrf_token() }}">`

which gets the csrf token just fine.

edit 1:

When I press "addToCart", now it just returns 419 axios error.

I tried `php artisan session:table` then migrate. when I try to access `$request->session()->getId()` in the controller (to store the session data of the request, since `session()->getId()` returns a new session id every time, it throws

local.ERROR: Session store not set on request. {"exception":"[object] (RuntimeException(code: 0): Session store not set on request.


If I put `middleware(['web'])` to the route, it returns the axios 419 error, even though I have the csrf in meta and *everything I wrote above*.

I can't believe I'm missing something so important....."

Please note that I have translated the text, but if you have any specific questions or need further assistance with the technical issues, feel free to ask.

<details>
<summary>英文:</summary>

I&#39;m making a webshop with laravel api and vuejs components.

If you &quot;add to cart&quot; an item, it sends a post request to the api, makes a record in the &quot;CartData&quot; table with your session id, then saves the given product to another table (with hasMany relationship), called &quot;CartItems&quot;, setting the cart id from the given CartData.

So at the end it should look something like this:

cartData:

|id|session_id|
|-|-|
|4|ASDABC123|

cartItems:

|id|cart_data_id|product_id|product_data|
|-|-|-|-|
|1|4|2|*data of the product in json*|

but right now, it generates a new session data in every single request, so in every single &quot;add to cart&quot; click. However, when I do &quot;session()-&gt;getId()&quot; in the blade template, it displays the same exact session ID.


How could I fix that? Why is this happening, am I missing something?

the &quot;buy&quot; method in vue (app):

    buy(item) {
        axios.post(
            &#39;api/cart/add&#39;,
            {
                product_id: item.id,
                product_data: JSON.stringify(item),
            }).then(
                response =&gt; {
                    console.log(response);
                    toastr.success(item.name + &#39; added to cart!&#39;, &#39;Success&#39;);
                }).catch(error =&gt; {
                    console.log(error);
                    toastr.error(&#39;Something went wrong!&#39;, &#39;Error&#39;);
                });
    },

About the CSRF part:

```/**
 * We&#39;ll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the &quot;XSRF&quot; token cookie.
 */

import axios from &#39;axios&#39;;
window.axios = axios;

window.axios.defaults.headers.common[&#39;X-Requested-With&#39;] = &#39;XMLHttpRequest&#39;;

this is in the bootstrap.js file that's being imported in the very first line of app.js (main js) file.

so based on the default comment in it, it should be using csrf token automatically, no?

I also have this in my header:

&lt;meta name=&quot;csrf-token&quot; content=&quot;{{ csrf_token() }}&quot;&gt;

which gets the csrf token just fine.

edit 1:

When I press "addToCart", now it just returns 419 axios error.

I tried php artisan session:table then migrate. when I try to access $request-&gt;session()-&gt;getId() in the controller (to store the session data of the request, since session()-&gt;getId() returns a new session id evey time, it throws

local.ERROR: Session store not set on request. {&quot;exception&quot;:&quot;[object] (RuntimeException(code: 0): Session store not set on request.

If I put middleware([&#39;web&#39;]) to the route, it returns the axios 419 error, even tho I have the csrf in meta and everything I wrote above.

I can't believe I'm missing something so important.....

Included code snippets all in all:

addToCart method (buy) in vue component

buy(item) {
            axios.post(
                &#39;api/cart/add&#39;,
                {
                    product_id: item.id,
                    product_data: JSON.stringify(item),
                }).then(
                    response =&gt; {
                        console.log(response);
                        toastr.success(item.name + &#39; added to cart!&#39;, &#39;Success&#39;);
                    }).catch(error =&gt; {
                        console.log(error);
                        toastr.error(&#39;Something went wrong!&#39;, &#39;Error&#39;);
                    });
        },

the addItem method in the cart controller is just a log that pushes "I GOT CALLED" when triggered.

api.php


Route::group([&#39;middleware&#39; =&gt; [&#39;web&#39;], &#39;controller&#39; =&gt; CartController::class], function () {
    Route::post(&#39;cart/add&#39;, &#39;addItem&#39;);
});

bootstrap.js

import axios from &#39;axios&#39;;


window.axios = axios;

window.axios.defaults.headers.common[&#39;X-CSRF-TOKEN&#39;] = document.querySelector(&#39;meta[name=&quot;csrf-token&quot;]&#39;).getAttribute(&#39;content&#39;);
 // this line above with the queryselector works either pushing it to window.axios and just axios. as mentioned, it shows up in the request&#39;s header.
window.axios.defaults.headers.common[&#39;X-Requested-With&#39;] = &#39;XMLHttpRequest&#39;;

答案1

得分: 1

将您的路由移到web.php文件中。

英文:

Your route is in api.php which is stateless and therefore does not recognise that any request is using a previously established session.

Move your endpoint into web.php file.

答案2

得分: 0

Both Back-end and front-end code should be on the same server and at the same port I think you are using Vue which is a front-end application which is communicating to the back-end via API. So instead, of session try using REST API or show me your code so that I can help you more about it.

英文:

Both Back-end and front-end code should be on the same server and at the same port I think you are using Vue which is a front-end application which is communicating to the back-end via API. So instead, of session try using REST API or show me your code so that I can help you more about it

答案3

得分: -1

CSRF是不相关的,因为它只是一种保护机制 - 不是身份验证(但你应该修复它,以免出现419错误)。当你发出请求并由PHP(laravel)处理时,会调用session_start,它会在浏览器中存储laravel_session cookie,并在服务器的某处(文件或数据库中)进行存储。

无法给出明确答案,但你可以像这样调试它:转到开发者工具中的网络选项卡,验证Axios是否实际发送会话ID。在Blade视图中的令牌和Axios发送的令牌可能不同。如果Axios没有发送令牌,laravel将初始化一个新的令牌(可能在这里出现问题)。

英文:

CSRF is irrelevant, because it's just protection mechanism - not identification (but you should fix it to not getting 419). When you make requests and PHP (laravel) handles it session_start called, which stores laravel_session cookie in the browser and somewhere at the server (in files or in dB).

Can't give a clear answer, but you can debug it like this: go to the network tab in the developer tools and verify, that Axios actually sends session id. Token in the Blade view and token which sends Axios may be different. If Axios not sending token, laravel will initialize new (maybe problem here).

huangapple
  • 本文由 发表于 2023年5月6日 21:38:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189195.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定