如何将 laravel CSRF 令牌值传递给 vue
How to pass laravel CSRF token value to vue
我有这种形式,用户只能在文本区域内键入文本:
<form action="#" v-on:submit="postStatus">{{-- Name of the method in Vue.js --}}
<div class="form-group">
<textarea class="form-control" rows="5" maxlength="140" autofocus placeholder="What are you upto?" required v-model="post"></textarea>
</div>
<input type="submit" value="Post" class="form-control btn btn-info">
{{ csrf_field() }}
</form>
然后,我有这个脚本代码,我使用 vue.js 和 ajax 以便将该文本传递到控制器并最终将其保存到数据库中:
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
},
http : {
headers: {
'X-CSRF-Token': $('meta[name=_token]').attr('content')
}
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
}
});
}
},
});
但是,到目前为止这还行不通,因为存在令牌不匹配异常。我不知道如何让它工作。如何将此令牌值传递给控制器。我尝试了以下方法:
1) 在表单中,我为令牌添加了一个 vue 名称:
<input type="hidden" name="_token" value="YzXAnwBñC7qPK9kg7MGGIUzznEOCi2dTnG9h9çpB" v-model="token">
2) 我试图将此标记值传递到 vue 中:
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
token : '',
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
'_token': this.token,
}
});
}
},
});
...但是在控制台中,vue 甚至没有捕捉到它:(
这导致我出现以下错误:
TokenMismatchException in VerifyCsrfToken.php line 68:
我该如何解决?有什么想法吗?
我的解决方案是所有 vue 组件在发出请求之前立即获取 csrf 令牌。我把它放在我的 bootstrap.js 文件中。
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', CoolApp.csrfToken);
next();
});
然后有一个classCoolApp.php
public function getScriptVariables()
{
return json_encode([
'csrfToken' => csrf_token(),
]);
}
简单地说,我建议将其放入您的 PHP 文件中:
<script>
window.Laravel = <?php echo json_encode(['csrfToken' => csrf_token()]); ?>
</script>
这样您就可以轻松地从 JS 部分(在本例中为 Vue)导入 csrfToken。
此外,如果您在 PHP 布局文件中插入此代码,您可以通过应用程序的任何组件使用该令牌,因为 window
是一个 JS 全局变量。
资料来源:我从 this post 那里得到了窍门。
感谢这两个答案,我解决了它:
1) 首先我阅读了 ,这让我想到了
2) 这个.
所以,在我的表格中我保留了这个:
{{ csrf_field() }}
在 js 文件中我只添加了以下内容(在 Vue 实例的外部和上方):
var csrf_token = $('meta[name="csrf-token"]').attr('content');
所以整个js代码是:
var csrf_token = $('meta[name="csrf-token"]').attr('content');
/*Event handling within vue*/
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
token : csrf_token,
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
'_token': this.token,
}
});
}
},
});
Very Easy Solution
只需在表单中添加一个隐藏字段。一个例子
<form id="logout-form" action="/logout" method="POST" style="display: none;">
<input type="hidden" name="_token" :value="csrf">
</form>
现在在 vue 文件的 script 中添加 csrf
变量,就像这样。 (记住,一定要在data里面)。
<script>
export default {
data: () => ({
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
}),
}
</script>
N.B. 您将在 blade.php
文件中看到这样的元标记。
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
如果没有这样的东西,你需要把它放在那里。
更好的方法是简单地将 csrf 令牌通过插槽传递到 vue 组件中。
在 blade.php 文件中:
@extends('layouts.app')
@section('content')
<my-vue-component>
{{ csrf_field() }}
</my-vue-component>
@endsection
在MyVueComponent.vue
<form role="form">
<slot>
<!-- CSRF gets injected into this slot -->
</slot>
<!-- form fields here -->
</form>
如果您使用的是 Axios,您可以通过以下方式轻松完成此操作:
自动 Axios CSRF 令牌附加解决方案:
首先,将令牌存储在 HTML 元标记中:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后将 CSRF 令牌注册为通用 header 到 Axios,这样所有传出的 HTTP 请求都会自动附加它。
在您的 bootstrapping/main JS 文件中,包括:
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
现在您可以发出附有 csrf 的请求。
我有这种形式,用户只能在文本区域内键入文本:
<form action="#" v-on:submit="postStatus">{{-- Name of the method in Vue.js --}}
<div class="form-group">
<textarea class="form-control" rows="5" maxlength="140" autofocus placeholder="What are you upto?" required v-model="post"></textarea>
</div>
<input type="submit" value="Post" class="form-control btn btn-info">
{{ csrf_field() }}
</form>
然后,我有这个脚本代码,我使用 vue.js 和 ajax 以便将该文本传递到控制器并最终将其保存到数据库中:
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
},
http : {
headers: {
'X-CSRF-Token': $('meta[name=_token]').attr('content')
}
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
}
});
}
},
});
但是,到目前为止这还行不通,因为存在令牌不匹配异常。我不知道如何让它工作。如何将此令牌值传递给控制器。我尝试了以下方法:
1) 在表单中,我为令牌添加了一个 vue 名称:
<input type="hidden" name="_token" value="YzXAnwBñC7qPK9kg7MGGIUzznEOCi2dTnG9h9çpB" v-model="token">
2) 我试图将此标记值传递到 vue 中:
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
token : '',
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
'_token': this.token,
}
});
}
},
});
...但是在控制台中,vue 甚至没有捕捉到它:(
这导致我出现以下错误:
TokenMismatchException in VerifyCsrfToken.php line 68:
我该如何解决?有什么想法吗?
我的解决方案是所有 vue 组件在发出请求之前立即获取 csrf 令牌。我把它放在我的 bootstrap.js 文件中。
Vue.http.interceptors.push((request, next) => {
request.headers.set('X-CSRF-TOKEN', CoolApp.csrfToken);
next();
});
然后有一个classCoolApp.php
public function getScriptVariables()
{
return json_encode([
'csrfToken' => csrf_token(),
]);
}
简单地说,我建议将其放入您的 PHP 文件中:
<script>
window.Laravel = <?php echo json_encode(['csrfToken' => csrf_token()]); ?>
</script>
这样您就可以轻松地从 JS 部分(在本例中为 Vue)导入 csrfToken。
此外,如果您在 PHP 布局文件中插入此代码,您可以通过应用程序的任何组件使用该令牌,因为 window
是一个 JS 全局变量。
资料来源:我从 this post 那里得到了窍门。
感谢这两个答案,我解决了它:
1) 首先我阅读了
2) 这个
所以,在我的表格中我保留了这个:
{{ csrf_field() }}
在 js 文件中我只添加了以下内容(在 Vue 实例的外部和上方):
var csrf_token = $('meta[name="csrf-token"]').attr('content');
所以整个js代码是:
var csrf_token = $('meta[name="csrf-token"]').attr('content');
/*Event handling within vue*/
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
token : csrf_token,
},
methods : {
postStatus : function (e) {
e.preventDefault();
console.log('Posted: '+this.post+ '. Token: '+this.token);
$.ajax({
url : '/posts',
type : 'post',
dataType : 'json',
data : {
'body' : this.post,
'_token': this.token,
}
});
}
},
});
Very Easy Solution
只需在表单中添加一个隐藏字段。一个例子
<form id="logout-form" action="/logout" method="POST" style="display: none;">
<input type="hidden" name="_token" :value="csrf">
</form>
现在在 vue 文件的 script 中添加 csrf
变量,就像这样。 (记住,一定要在data里面)。
<script>
export default {
data: () => ({
csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
}),
}
</script>
N.B. 您将在 blade.php
文件中看到这样的元标记。
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
如果没有这样的东西,你需要把它放在那里。
更好的方法是简单地将 csrf 令牌通过插槽传递到 vue 组件中。
在 blade.php 文件中:
@extends('layouts.app')
@section('content')
<my-vue-component>
{{ csrf_field() }}
</my-vue-component>
@endsection
在MyVueComponent.vue
<form role="form">
<slot>
<!-- CSRF gets injected into this slot -->
</slot>
<!-- form fields here -->
</form>
如果您使用的是 Axios,您可以通过以下方式轻松完成此操作: 自动 Axios CSRF 令牌附加解决方案:
首先,将令牌存储在 HTML 元标记中:
<meta name="csrf-token" content="{{ csrf_token() }}">
然后将 CSRF 令牌注册为通用 header 到 Axios,这样所有传出的 HTTP 请求都会自动附加它。
在您的 bootstrapping/main JS 文件中,包括:
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
现在您可以发出附有 csrf 的请求。