如何使用Laravel API在AngularJS表单中发送csrf_token()?

如何使用Laravel API在AngularJS表单中发送csrf_token()?,angularjs,laravel,csrf-protection,Angularjs,Laravel,Csrf Protection,我正在尝试构建angular+laravel rest应用程序。我可以查看我的数据库。当我尝试添加新项目时。我收到500错误告诉我csrf令牌不匹配。 我的表格布局是: <form class="form-horizontal" ng-submit="addItem()"> <input type="text" ng-model="itemEntry" placeholder="Type and hit Enter to add item"> </form&g

我正在尝试构建angular+laravel rest应用程序。我可以查看我的数据库。当我尝试添加新项目时。我收到
500错误
告诉我csrf令牌不匹配。 我的表格布局是:

<form class="form-horizontal" ng-submit="addItem()">

  <input type="text" ng-model="itemEntry" placeholder="Type and hit Enter to add item">
</form>
以下是我用于应用程序的筛选器:

Route::filter('csrf', function()
{
    if (Session::token() != Input::get('_token'))
    {
        throw new Illuminate\Session\TokenMismatchException;
    }
});
在我的刀片视图中,我使用了这个,它可以工作:

<input type="hidden" name="_token" value="{{ csrf_token() }}" />

一个选项是将CSRF令牌作为常量注入。在头标签中附加以下内容:


angular.module(“app”).constant(“CSRF_-TOKEN”,“{{CSRF_-TOKEN()}}”);
然后,在您的模块方法中,它可以在需要时注入

app.factory(“FooService”,函数($http,CSRF_令牌){
控制台日志(CSRF_令牌);
};

也许你会有兴趣看一下这本书的源代码。

鲁本斯·马里尤佐(Rubens Mariuzzo)接受的解决方案是可行的,但是我认为我已经找到了一个我认为更好的替代方案

这样,您就不必将html脚本中的数据传递到angularjs应用程序中,并且可以更好地分离关注点。例如,这允许您将Laravel应用程序作为API使用

我的解决方案包括通过api请求获取CSRF令牌,并将该值设置为常量

此外,您没有在需要时注入CSRF令牌,而是将令牌设置在默认头中,该头将在任何API http请求时由服务器进行检查

示例显示了laravel,然而任何严肃的框架都应该能够提供类似的东西

拉维尔的CSRF路线:

// Returns the csrf token for the current visitor's session.
Route::get('api/csrf', function() {
    return Session::token();
});
使用
before=>'api.csrf'
过滤器保护路由

// Before making the declared routes available, run them through the api.csrf filter
Route::group(array('prefix' => 'api/v1', 'before' => 'api.csrf'), function() {
Route::resource('test1', 'Api\V1\Test1Controller');
Route::resource('test2', 'Api\V1\Test2Controller');
});
api.csrf
过滤器

// If the session token is not the same as the the request header X-Csrf-Token, then return a 400 error.
Route::filter('api.csrf', function($route, $request)
{
if (Session::token() != $request->header('X-Csrf-Token') )
{
    return Response::json('CSRF does not match', 400);
}
});
AngularJS的东西把这个放在app.js中:

阻止版本:

var xhReq = new XMLHttpRequest();
xhReq.open("GET", "//" + window.location.hostname + "/api/csrf", false);
xhReq.send(null);

app.constant("CSRF_TOKEN", xhReq.responseText);

app.run(['$http', 'CSRF_TOKEN', function($http, CSRF_TOKEN) {    
    $http.defaults.headers.common['X-Csrf-Token'] = CSRF_TOKEN;
}]);
非阻塞版本

var xhReq = new XMLHttpRequest();
xhReq.open("GET", "//" + window.location.hostname + "/api/csrf", true);

xhReq.onload = function(e) {
  if (xhReq.readyState === 4) {
    if (xhReq.status === 200) {
      app.constant("CSRF_TOKEN", xhReq.responseText);

      app.run(['$http', 'CSRF_TOKEN', function($http, CSRF_TOKEN) {
        $http.defaults.headers.common['X-Csrf-Token'] = CSRF_TOKEN;
      }]);
    }
  }
};

xhReq.send(null);

现在,CSRF_令牌常量作为头被注入来自AngularJS应用程序的所有http请求中,并且所有API路由都受到保护。

我认为我的解决方案没有那么痛苦,而且更加灵活,特别是它认为在Karma上测试应用程序

首先将此代码添加到主视图中

 <meta name="csrf-token" content="{{ csrf_token() }}">
最后,我们需要新的过滤器来应对laravel方面的变化

Route::filter('csrfInHeader', function($route, $request) {

    if (Session::token() !== (string) $request->header('X-CSRF-TOKEN') ) {

        throw new Illuminate\Session\TokenMismatchException;

    }
});

“csrfInHeader”过滤器将按angular应用程序检查所有http请求。您不需要在每个请求中添加csrf令牌。此外,如果您通过Karma测试您的应用程序,您将不会在测试时努力获取csrf令牌。

如果您使用Laravel 5,无需将csrf令牌添加到angular http头中

带Angular的Laravel 5自动为您执行此操作


最简单的方法

Route::get('/getToken','Controller@getToken');
在web或api.php文件中

内部控制器

public function getToken(){

          return csrf_token();

    }
放置此代码

在Angular应用程序中

$http.get("http://localhost:8000/getToken")
  .then(function(response) {
    alert(response.data)
  });
获取csrf_令牌()的安全方法


您好,我在头部添加了脚本。我注入了CSRF_令牌。我如何在表单中添加它?顺便说一句,我编辑了我的代码。我仍然无法管理它,我端到端地阅读了代码。我编辑了$scope.addItem。您能看一看吗?嘿,我为该解决方案添加了另一个替代方案。您能检查并发表您的意见吗?@ytsejam-I我不明白在标题中指定内容类型是如何将CSRF令牌从服务器发送到AngularJS应用程序的替代解决方案。我遵循了本教程@Gravy,您是否从同一个域提供angular应用程序?我目前的api位于api.example.com,angular则从example.com提供,因此我遇到了一些问题由于会话被认为是跨源的,所以正在进行会话。这对REST api不起作用,令牌将不一样。太棒了。完全错过了这一点
Route::filter('csrfInHeader', function($route, $request) {

    if (Session::token() !== (string) $request->header('X-CSRF-TOKEN') ) {

        throw new Illuminate\Session\TokenMismatchException;

    }
});
Route::get('/getToken','Controller@getToken');
public function getToken(){

          return csrf_token();

    }
$http.get("http://localhost:8000/getToken")
  .then(function(response) {
    alert(response.data)
  });