摘要:基本功能创建文章的第一步是用户发请求,然后返回创建文章的页面。实际上,会报错添加保护虽然我们完成了基本功能,但是提交请求的时候还是会报错,其实这是防止攻击。假如违反了规则,错误信息会自动被保存在闪存的中,即只对下一次请求生效。
基本功能
创建文章的第一步是用户发请求,然后返回创建文章的页面。
路由:处理用户「创建文章」的请求
</>复制代码
/routes/web.php
Route::get("/posts/create","PostsController@create");
控制器: 返回文章编辑视图
</>复制代码
/app/Http/Controllers/PostsController.php
public function create()
{
return view("posts.create");
}
视图: 使用 Bootstrap 组件来创建文章编辑页面
</>复制代码
/resources/views/posts/create.blade.php
@extends("layouts.master")
@section("content")
创建文章
@endsection
action 方法根据控制器来生成对应的路由,也可以用之前学过的 url 方法:
</>复制代码
生成的 url 如下:
</>复制代码
用户提交之后,需要在路由中处理用户提交的数据的请求:
</>复制代码
/routes/web.php
Route::post("/posts","PostsController@store");
最后是保存文章实现,我们使用 request() 方法获取请求字段,保存完之后跳转到博客首页:
</>复制代码
use AppPost;
public function store()
{
$post = new Post();
$post->title = request("title");
$post->body = request("body");
$post->save();
return redirect("posts");
}
现在,访问 posts/create,创建文章后点击提交,查看下效果。实际上,会报错:
</>复制代码
TokenMismatchException in VerifyCsrfToken.php line 68
添加 CSRF 保护
虽然我们完成了基本功能,但是提交请求的时候还是会报错,其实这是防止 CSRF 攻击。
举一个简单的例子,你登录一个投票网站,通过发送该请求向编号为 25 的人投票:
</>复制代码
http://example.com/vote/25
CSRF 如何进行攻击呢,顾名思义,CSRF 是 Cross-site request forgery 的缩写,即跨站请求伪造,因此需要具备两个条件:
跨站。首先,我登录了该投票网站,网站保存了我的登录信息,然后我又登录了另外一个网站;
伪造请求。在另外一个网站的界面中,可能包含了类似 这样的 HTML 代码。由于投票网站无法区分你在哪里发送的请求,因此,就等于你向 30 号选手进行了投票;
解决方式也很简单:
登录 A 网站的时候,生成一条 token
提交请求的时候,该 token 也跟着提交
两者进行验证即可
第一步,Laravel 已经帮我们实现了:
</>复制代码
/vendor/laravel/framework/src/Illuminate/Session/Store.php
public function start()
{
$this->loadSession();
if (! $this->has("_token")) {
$this->regenerateToken();
}
return $this->started = true;
}
第二步,Laravel 也帮我们封装好了,直接使用 csrf_field() 函数即可,我们在文章编辑的表单中加入即可:
</>复制代码
/resources/views/posts/create.blade.php
创建文章
{{ csrf_field() }}
可以看看该函数长什么样:
</>复制代码
function csrf_field()
{
return new HtmlString("");
}
因此,我们也可以写成:
</>复制代码
最后一步,Laravel 通过中间件来进行自动检验:
</>复制代码
public function handle($request, Closure $next)
{
if (
$this->isReading($request) ||
$this->runningUnitTests() ||
$this->inExceptArray($request) ||
$this->tokensMatch($request)
) {
return $this->addCookieToResponse($request, $next($request));
}
throw new TokenMismatchException;
}
简单解读下该中间件的处理流程:
判断请求类型,如果是 GET、HEAD、OPTIONS 等不会更改资源的请求就通过;
如果处于测试环境下就通过;
$except 数组内添加的 url 默认通过;
tokens 匹配也通过;
通过之后,就会添加名为 XSRF-TOKEN 的cookie;如果没通过,就抛出异常,也就是我们上一节显示的错误信息了。
批量创建文章刚才我们采用是 save() 方法来保存文章,实际上,也可以使用 create() 方法,该方法允许一次性插入多条数据,因此必须指定允许批量插入的字段:
</>复制代码
/app/Post.php
class Post extends Model
{
protected $fillable = [
"title",
"body",
];
}
store() 方法可以写成:
</>复制代码
/app/Http/Controllers/PostsController.php
public function store(Request $request)
{
Post::create([
"title" => request("title"),
"body" => request("body")
]);
return redirect("posts");
}
或者传入数组给 request():
</>复制代码
/app/Http/Controllers/PostsController.php
public function store(Request $request)
{
Post::create(request(["title","body"]));
return redirect("posts");
}
添加字段验证
接下来进一步完善创建文章的功能,即字段验证。可以直接使用 validate 方法:
</>复制代码
/app/Http/Controllers/PostsController.php
public function store(Request $request)
{
$this->validate(request(), [
"title" => "required|unique:posts|max:255",
"body" => "required|min:5",
]);
Post::create(request(["title", "body"]));
return redirect("posts");
}
我们为 title 添加了非空、唯一性以及最大字符的验证规则,对 body 字段添加了非空和最小字符的规则。
假如违反了规则,错误信息 $errors 会自动被保存在闪存的 Session 中,即只对下一次请求生效。并且,我们不需要将其返回给视图,Laravel 帮我们做了处理,我们所有的视图都可以获取到 $errors 变量,可以令其显示出来:
</>复制代码
/resources/views/layouts/master.blade.php
@include("layouts.errors");
@include("layouts.footer")
具体错误消息:
</>复制代码
/resources/views/layouts/errors.blade.php
@if (count($errors))
- @foreach ($errors->all() as $error)
-
- {{ $error }}
- @endforeach
-
@endif
Forms · Bootstrap
CSRF (Cross-site request forgery) attack example and prevention in PHP - Stack Overflow
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/22701.html
摘要:编辑迁移文件我们为表格添加了外键,同时生定义了约束,该约束允许删除父表文章的时候,自动删除关联的子表评论。关联中文文档的辅助函数列表中文文档 本节将学习 Eloquent Relations,表与表之间存在着多种关系,举例如下: 一对一:文章与作者 一对多:文章与评论 多对多:标签与文章 文章与评论的一对多关系 一对多关系,主要理解两点: 如何实现一对多关系 实现了之后能给开发带...
摘要:本节将实现文章评论与用户关联的功能。关系定义首先修改与表,增加字段增加全部回滚并重新执行迁移添加用户表与文章表评论表的一对多关系添加文章评论表与用户表的多对一关系同时,评论表的字段增加。同时,我们还自定义了返回的错误信息。 本节将实现文章、评论与用户关联的功能。 关系定义 首先修改 posts 与 comments 表,增加 user_id 字段 /database/migratio...
摘要:将上述的一系列查询进行封装模型到了这一步,我们基本上实现了文章归档的功能。但是有一个问题,文章归档实际上包括在通用视图中,这就意味着,网站的所有请求都需要返回,否则就会报错。数据库之数据库请求构建器中文文档的视图功能中文文档 首先,要实现的是按照日期来统计文章,原始的 SQL 如下: select year(created_at) year, monthname(c...
摘要:熟悉了路由与视图的基本操作之后,我们来让视图显示一个任务列表吧。创建迁移现在,我们就可以创建一个用来生成任务表的迁移了。 熟悉了路由与视图的基本操作之后,我们来让视图显示一个任务列表吧。主要知识点: 数据迁移 查询构造器 数据库 创建数据库 首先创建一个数据库: $ mysql -uroot -p mysql> create database laratasks; 数据库配置 La...
摘要:为的辅助方法,用于截取字符串的前个字符,然后返回前个字符加的格式。显示某篇文章显示某篇文章的比较简单,路由注意要放在下面,假如这样那么,我们访问的时候,会被当成是的查询参数。 文章的显示功能比较简单,分为两部分: 文章列表 具体的某篇文章 显示文章列表 路由之前已经定义好: Route::get(/posts,PostsController@index); 控制器: public ...
阅读 1876·2021-11-11 16:55
阅读 2668·2021-08-27 13:11
阅读 3702·2019-08-30 15:53
阅读 2372·2019-08-30 15:44
阅读 1495·2019-08-30 11:20
阅读 1111·2019-08-30 10:55
阅读 999·2019-08-29 18:40
阅读 3176·2019-08-29 16:13