前言
Laravel 路由、中间件及 CSRF。
路由
基本路由
<?php
Route::prefix('v1')->namespace('Api')->group(function () {
// 系统时间
Route::get('time', 'IndexController@time')->name('index.time');
// 需要证验权限的分组
Route::middleware('check.sign')->group(function () {
// 图片列表(含搜索)
Route::get('/photos', 'PhotosController@index')->name('photos.index');
// 创建表单
Route::get('/photos/create', 'PhotosController@create')->name('photos.create');
// 保存图片
Route::post('/photos', 'PhotosController@store')->name('photos.store');
// 国片详情
Route::get('/photos/{id}', 'PhotosController@show')->name('photos.show');
// 编辑表单
Route::get('/photos/{id}/edit', 'PhotosController@edit')->name('photos.edit');
// 更新图片
Route::put('/photos/{id}', 'PhotosController@update')->name('photos.update');
// 删除图片
Route::delete('/photos/{id}', 'PhotosController@destroy')->name('photos.destroy');
});
});
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function () {
// 跳至登录
Route::redirect('/manage', '/admin/login', 301);
// 登录页面
Route::view('/login', 'admin.login')->name('admin.login');
// 退出登录
Route::get('/logout/{id?}', 'AdminController@login')->name('admin.logout');
});
// 事件推送
Route::any('wechat/push', 'WechatController@push')->name('wechat.push');
// 视图路由
Route::view('/', 'welcome', ['name' => 'Taylor']);
// 重定向路由
Route::redirect('/here', '/there', 301);
// 限流路由
Route::middleware('auth:api', 'throttle:60,1')->group(function () {
});
资源路由
动词 | 路径 | 方法 | 路由 |
---|---|---|---|
get | /photos | index | photos.index |
get | /photos/create | create | photos.create |
post | /photos | store | photos.store |
get | /photos/{id} | show | photos.show |
get | /photos/{id}/edit | edit | photos.edit |
put/patch | /photos/{id} | update | photos.update |
delete | /photos/{id} | destroy | photos.destroy |
一般资源路由定义:
Route::resource('photos', 'PhotosController');
等于以下路由定义:
Route::get('/photos', 'PhotosController@index')->name('photos.index');
Route::get('/photos/create', 'PhotosController@create')->name('photos.create');
Route::post('/photos', 'PhotosController@store')->name('photos.store');
Route::get('/photos/{id}', 'PhotosController@show')->name('photos.show');
Route::get('/photos/{id}/edit', 'PhotosController@edit')->name('photos.edit');
Route::put('/photos/{id}', 'PhotosController@update')->name('photos.update');
Route::delete('/photos/{id}', 'PhotosController@destroy')->name('photos.destroy');
使用 resource 方法时,如果仅使用到部分路由,必须使用 only 列出所有可用路由:
Route::resource('photos', 'PhotosController', ['only' => ['index', 'show']]);
切记不要使用 except,因为 only 相当于白名单,相对于 except 更加直观,路由使用白名单有利于养成『安全习惯』。
如果你想创建资源控制器,则可以使用如下类似方法:
$ php artisan make:controller PhotosController --resource
生成链接
如果为路由指定了名称后,就可以使用全局辅助函数 route
来生成链接,如果路由有参数,则可以把参数作为 route
函数的第二个参数传入,指定的参数将会自动插入到 URL 中对应的位置,比如:
Route::get('/photos/{id}', 'PhotosController@show')->name('photos.show');
$url = route('photos.show', ['id' => 1]);
中间件
中间件提供了一种方便的机制过滤进入应用程序的 HTTP 请求。这些中间件可以用来执行各种任务,Laravel 自带了一些中间件,包括身份验证、CSRF 保护等。所有的这些中间件都位于 app/Http/Middleware 目录。
创建一个中间件
$ php artisan make:middleware CheckAge
前置中间件
<?php
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// 执行一些任务
return $next($request);
}
}
后置中间件
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 执行一些任务
return $response;
}
}
注册中间件
全局中间件
如果你希望中间件在应用处理每个 HTTP 请求期间运行。只需要在 app/Http/Kernel.php 中的 $middleware 属性中列出这个中间件。
路由中间件
假设你想为指定的路由分配中间件 ,首先应该在 app/Http/Kernel.php 文件内为该中间件分配一个键。默认情况下,该类中的 $routeMiddleware 属性下包含了 Laravel 内置的中间件。若要加入自定义的中间件,只需把它附加到列表后并为其分配一个自定义键。
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
一旦在 HTTP 内核中定义好了中间件,就可以通过 middleware 方法将为路由分配中间件:
Route::get('admin/profile', function () {
//
})->middleware('auth');
路由中间组
某些时候你可能希望使用一个键把多个中间件打包成一个组,以便更容易地分配给路由。你可以使用 Http 核心的 $middlewareGroups 属性。
中间件组可以使用与单个中间件相同的语法将自身分配给路由和控制器动作。同样,中间件组使得一次将多个中间件分配给一个路由更加方便。
排序中间件
很少情况下,你可能需要中间件以特定的顺序执行,但是当它们被分配到路由时,你无法控制它们的顺序。在这种情况下,可以使用 app/Http/Kernel.php 文件的 $middlewarePriority 属性指定中间件优先级。
Terminable 中间件
有时,在准备好 HTTP 响应之后,中间件可能需要做一些工作。如果你在中间件上定义了一个 terminate 方法,并且你使用的是 FastCGI ,那么它将会在响应准备发送到浏览器之后自动调用。
<?php
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// Store the session data...
}
}
terminate 方法应该同时接收请求和响应。定义了这个中间件之后,别忘了将它添加到路由列表或者 app/Http/Kernel.php 文件的全局中间件中。
CSRF
Laravel 可以轻松使地保护你的应用程序免受 跨站请求伪造 (CSRF) 攻击。 跨站点请求伪造是一种恶意攻击,它凭借已通过身份验证的用户身份来运行未经过授权的命令。
Laravel 会自动为每个活跃的用户的会话生成一个 CSRF「令牌」。该令牌用于验证经过身份验证的用户是否是向应用程序发出请求的用户。
HTML 表单
<form method="POST" action="/profile">
@csrf
</form>
JavaScript
当构建由 JavaScript 驱动的应用时,可以方便的让 JavaScript HTTP
函数库发起每一个请求时自动附上 CSRF 令牌。默认情况下,resources/js/bootstrap.js 文件中提供的 Axios HTTP 库会使用 cookie 中加密的 XSRF-TOKEN 的值然后在请求时自动发送 X-XSRF-TOKEN 标头。 如果不使用此库,则需要为应用程序手动配置此行为。
<meta name="csrf-token" content="{{ csrf_token() }}">
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
总结
- 绝不在路由配置文件里书写『闭包路由』或者其他业务逻辑代码,因为一旦使用将无法使用路由缓存。
- 路由要保持干净整洁,绝不放置除路由配置以外的其他程序逻辑。
网友评论