在 Web 应用中,表单是用户与后端交互的主要方式。Laravel 提供了简洁而强大的工具来处理表单数据,并内置了跨站请求伪造(CSRF)保护,防止恶意网站利用用户身份发起未授权请求。本章将详细介绍如何在 Laravel 中创建安全、规范的表单。
在 Blade 模板中,你可以直接使用 HTML 构建表单。Laravel 推荐使用 POST 方法提交数据,并通过 @csrf 指令自动添加 CSRF 令牌字段。
<form method="POST" action="/profile">
@csrf
<div class="form-group">
<label for="name">姓名</label>
<input type="text" name="name" id="name" class="form-control">
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" name="email" id="email" class="form-control">
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
生成的 HTML 中会自动包含一个隐藏的 CSRF 令牌输入框:
<input type="hidden" name="_token" value="随机生成的令牌">
Laravel 的 CSRF 保护机制通过验证请求中的令牌与会话中存储的令牌是否一致来工作。如果令牌不匹配,Laravel 会抛出 TokenMismatchException 异常(通常显示 419 页面)。这可以有效防止跨站请求伪造攻击。
X-CSRF-TOKEN)。
HTML 表单只支持 GET 和 POST 方法,但 Laravel 允许你通过 @method 指令伪造 PUT、PATCH 或 DELETE 请求,以便在路由中使用 RESTful 风格。
<form method="POST" action="/user/1">
@csrf
@method('PUT')
<!-- 实际会生成一个隐藏的 _method 字段,值为 PUT -->
<div class="form-group">
<label>用户名</label>
<input type="text" name="name" value="旧名称">
</div>
<button type="submit">更新</button>
</form>
生成的 HTML 中会包含:
<input type="hidden" name="_method" value="PUT">
这样 Laravel 的路由就能正确识别为 PUT 请求。
Laravel 提供了便捷的错误消息显示方式。当控制器验证失败时,会将错误信息闪存到 Session 中,并重定向回表单页面。你可以使用 @error 指令或 $errors 变量来显示错误。
@if ($errors->any())
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<input type="text" name="name" value="{{ old('name') }}">
@error('name')
<div class="error-feedback">{{ $message }}</div>
@enderror
下面是一个完整的注册表单,包含了 CSRF 保护、验证错误显示、旧数据保留等功能。
<form method="POST" action="/register">
@csrf
<div class="form-group">
<label for="name">姓名</label>
<input type="text" name="name" id="name" class="form-control @error('name') is-invalid @enderror" value="{{ old('name') }}">
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" name="email" id="email" class="form-control @error('email') is-invalid @enderror" value="{{ old('email') }}">
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="form-group">
<label for="password">密码</label>
<input type="password" name="password" id="password" class="form-control @error('password') is-invalid @enderror">
@error('password')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">注册</button>
</form>
对应的控制器验证规则示例:
public function register(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users',
'password' => 'required|min:8|confirmed',
]);
// 创建用户...
return redirect('/')->with('success', '注册成功!');
}
当使用 JavaScript 发起 AJAX 请求时,需要手动将 CSRF 令牌添加到请求头中。Laravel 推荐在布局文件中将令牌存入 meta 标签,然后由 JavaScript 读取。
<meta name="csrf-token" content="{{ csrf_token() }}">
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Laravel 9+ 默认的 resources/js/bootstrap.js 已配置
axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
app/Http/Middleware/VerifyCsrfToken.php 的 $except 数组中添加路由,但请谨慎使用。route() 生成 URL,便于维护。old() 保留输入: 验证失败后,使用 old('field') 可以保留用户之前输入的内容,提升体验。
Laravel 通过 CSRF 令牌为表单提交提供了开箱即用的安全防护。结合表单方法伪造、验证错误显示等功能,你可以快速构建出安全、用户友好的 Web 表单。记住:始终对所有状态变更请求使用 @csrf,并善用 old() 和错误处理来优化用户体验。