最近在自己新建的博客后台中使用 Editor.md 作为发布文章的编辑器,后来在做上传图片的时候遇到了一些难题,就是提交的表单中没有Token,无法通过 Laravel 的 VerifyCsrfToken 中间件检查。本文将讲解如何解决这个问题。
Editor.md 主要特性
Github下载地址:https://github.com/pandao/editor.md
/* 配置editormd */
var editor = editormd("editormd", {
path: "{{ asset('/editor.md/lib/') }}",
height: 700,
syncScrolling: "single",
toolbarAutoFixed: false,
saveHTMLToTextarea: false,
imageUpload: true,
imageFormats : ["jpg","jpeg","gif","png","bmp","webp"],
imageUploadURL:"{{url('backend/uploadimage')}}"
});
public function uploadimage(Request $request)
{
$message='';
if (!$this->disk->exists('/article')) {
$message = "article 文件夹不存在,请先创建";
}else{
$pathDir=date('Ymd');
if(!$this->disk->exists('/article/'.$pathDir)){
$this->disk->makeDirectory('/article/'.$pathDir);
}
}
if($request->file('editormd-image-file')){
$path="uploads/article/".$pathDir;
$pic = $request->file('editormd-image-file');
if($pic->isValid()){
$newName=md5(time() . rand(0, 10000)).".".$pic->getClientOriginalExtension();
if($this->disk->exists($path.'/'.$newName)){
$message = "文件名已存在或文件已存在";
}else{
if($pic->move($path,$newName)){
$url = asset($path.'/'.$newName);
}else{
$message="系统异常,文件保存失败";
}
}
}else{
$message = "文件无效";
}
}else{
$message="Not File";
}
$data = array(
'success' => empty($message) ? 1 : 0, //1:上传成功 0:上传失败
'message' => $message,
'url' => !empty($url) ? $url : ''
);
header('Content-Type:application/json;charset=utf8');
exit(json_encode($data));
}
Route::group(['prefix' => 'backend'], function () {
Route::post('uploadimage',['uses'=>'Backend\UploadController@uploadimage']);
});
我们可以发现会出现 500 错误,这是由 Laravel 的TokenMismatchException 异常导致的,也就是 Laravel 默认开启了防 CSRF,而 Editor.md 的上传表单中并没有包含 token,所以才会出现这个错误。
当我们点击上传图片的时候会弹出上传框,这个就是上传的表单,我们可以用调试器查出这是请求了 image-dialog.js,具体路径为editor.md/plugins/image-dialog/image-dialog.js。我们可以对其中的 var dialogContent 变量进行就修改。
具体的修改代码
if (settings.crossDomainUpload)
{
action += "&callback=" + settings.uploadCallbackURL + "&dialog_id=editormd-image-dialog-" + guid;
}
var csrfToken = $('meta[name="_token"]').attr('content');
var csrfField = "";
if (csrfToken) {
csrfField = "<input type='hidden' name='_token' value='" + csrfToken + "' />";
}
在 if(settings.crossDomainUpload) 结束后加上这5行代码,接下来,将 csrfField 变量加入到下面的代码中。
var dialogContent = ( (settings.imageUpload) ? "<form action=\"" + action + "\" target=\"" + iframeName + "\" method=\"post\" enctype=\"multipart/form-data\" class=\"" + classPrefix + "form\">" : "<div class=\"" + classPrefix + "form\">" ) +
( (settings.imageUpload) ? "<iframe name=\"" + iframeName + "\" id=\"" + iframeName + "\" guid=\"" + guid + "\"></iframe>" : "" ) +
"<label>" + imageLang.url + "</label>" +
"<input type=\"text\" data-url />" + (function () {
return (settings.imageUpload) ? "<div class=\"" + classPrefix + "file-input\">" +
"<input type=\"file\" name=\"" + classPrefix + "image-file\" accept=\"image/*\" />" +
csrfField +
"<input type=\"submit\" value=\"" + imageLang.uploadButton + "\" />" +
"</div>" : "";
})() +
"<br/>" +
"<label>" + imageLang.alt + "</label>" +
"<input type=\"text\" value=\"" + selection + "\" data-alt />" +
"<br/>" +
"<label>" + imageLang.link + "</label>" +
"<input type=\"text\" value=\"http://\" data-link />" +
"<br/>" + csrfField +
( (settings.imageUpload) ? "</form>" : "</div>");
然后在请求的页面头部加上这行代码
<meta name="_token" content="{{ csrf_token() }}"/>
这样再次请求上传图片就可以把 token 带过去。
本文为 Ellison 个人笔记,文章来自于网络或个人总结,转载无需和我联系,但请注明来自 Ellison`s Blog https://www.ruoxiaozh.com
Laravel 框架中前端如何使用 CSRF Laravel 5.6 单设备登录 Laravel 5.6 使用 UUID CURL 类封装 Laravel Eloquent 必备的实用技巧 提高安全性的最佳 Nginx 配置 Vagrant SSH 的登录总结 Laravel 跨域解决方案 CORS 跨域的概念与 TP5 的解决方案 MySQL 千万级大数据 SQL 查询优化技巧详解 数据库 30 条军规 JavaScript 判断访问客户端是 PC 端还是移动端 PHP 的笛卡尔积算法实现 API 文档编写 - APIDOC Linux MySQL 定时备份并上传到 git 仓库 Laravel 5.5 之 Api Resource Laravel 实现文章浏览次数统计 如何在 Laravel 项目中使用 Swagger 构建 Api 文档 如何编写基于 Swagger-PHP 的 API 文档 网站加载动画 Markdown 语法说明 见过世面的人,从不说这3句话 PHP7 新特性 - 完结篇 阿里云 Redis 开发规范 Nginx 负载均衡设置 PHP 生成随机红包算法 规范的 README 需要哪些内容 PHP 代码规范之 PSR-2 Ubuntu 14/16 下的 Laravel LNMP 线上环境自动部署脚本 PHP 闭包 不会,找人教你就够了? PHP 新特性 - 命名空间