Skip to content

Laravel - 安全性

安全是任何 Web 应用的关键方面。Laravel 提供了许多内置功能并遵循最佳实践来帮助你构建安全的应用。以下是一些关键的安全注意事项:

Laravel 的 Hash 外观为存储用户密码提供了安全的 Bcrypt 和 Argon2 散列(hashing)。Bcrypt 是默认的散列算法。

要散列一个密码,使用 make 方法:

use Illuminate\Support\Facades\Hash;
$password = 'my-secret-password';
$hashedPassword = Hash::make($password);

要验证密码是否与存储的散列值匹配,使用 check 方法:

if (Hash::check('my-secret-password', $hashedPassword)) {
// The passwords match...
}

check() 方法如果明文密码与散列密码匹配,则返回 true,否则返回 false。

Laravel 使实现身份验证变得非常简单。你可以使用 Laravel Breeze 或 Laravel Jetstream 等入门套件快速搭建身份验证视图和路由。在底层,Laravel 的内置身份验证服务,如 Auth 外观,处理用户验证。

Auth::attempt 方法通常用于处理来自登录表单的身份验证尝试。它接受一个凭据数组作为第一个参数:

use Illuminate\Support\Facades\Auth;
// Example in a login controller method
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate(); // Important for security
return redirect()->intended('dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}

attempt 方法验证数据库中的凭据。如果身份验证成功,它返回 true 并建立一个已认证的会话。intended 方法将用户重定向到他们在被身份验证中间件拦截之前试图访问的 URL,或者重定向到备用 URI。

当恶意网站诱骗用户浏览器在用户已认证的情况下向你的应用发起非预期的请求时,就会发生 CSRF 攻击。Laravel 会为每个活跃的用户会话自动生成一个 CSRF“令牌”。此令牌用于验证确实是已认证的用户正在向应用发出请求。

任何时候在应用中定义需要发起 POST、PUT、PATCH 或 DELETE 请求的 HTML 表单时,都应使用 @csrf Blade 指令包含一个隐藏的 CSRF 令牌字段:

<form method="POST" action="/profile">
@csrf
<!-- ... other form fields ... -->
<button type="submit">Submit</button>
</form>

Laravel 的 VerifyCsrfToken 中间件,包含在 web 中间件组中,会自动验证所有非 GET 请求的此令牌。

当攻击者将客户端脚本(通常是 JavaScript)注入到其他用户查看的页面时,就会发生 XSS 攻击。为了防止 XSS,你绝不应该信任用户提交的数据,并且在将其渲染到 HTML 中之前始终对其进行转义(escape)。

Blade 的双大括号语法 {{ $variable }} 会自动使用 PHP 的 htmlspecialchars 函数对输出进行转义,从而防止 XSS:

<div>{{ $userInput }}</div>

如果你需要渲染未转义的 HTML(并且你确定内容是安全的),可以使用 {!! $variable !!} 语法。使用此语法时务必极其小心。

当应用程序将未经过滤的用户输入插入到 SQL 查询中时,就会发生 SQL 注入漏洞。Laravel 的 Eloquent ORM 和 Query Builder 默认使用 PDO 参数绑定,这可以防止 SQL 注入。只要你正确使用这些工具,你的数据库查询就能免受此类攻击。

// Safe: Eloquent uses parameter binding
User::where('email', $request->email)->first();
// Safe: Query Builder uses parameter binding
DB::table('users')->where('email', $request->email)->first();
// Unsafe: Raw SQL query with direct concatenation (AVOID THIS)
// DB::select(DB::raw("SELECT * FROM users WHERE email = '" . $request->email . "'"));

默认情况下,Laravel 生成的所有 Cookie 都会被加密和签名,以便它们不能被客户端 JavaScript 修改或读取。你的 .env 文件中的 APP_KEY 用作加密密钥。如果此密钥发生更改,所有现有 Cookie 将失效。

始终为你的生产应用使用 HTTPS (HTTP Secure),尤其是在传输敏感数据时(例如,登录凭据、个人信息、会话数据)。HTTPS 会加密传输中的数据,防止同一网络上的攻击者拦截数据。你可以配置你的 Web 服务器(Nginx、Apache)来强制使用 HTTPS。

考虑实现内容安全策略(CSP)标头。CSP 是一种附加的安全层,有助于检测和缓解某些类型的攻击,包括 XSS 和数据注入。你可以通过中间件或使用 spatie/laravel-csp 等包来配置 CSP 标头。

额外资源:定期查阅 Laravel 安全文档,并通过 OWASP (开放式 Web 应用安全项目) 等资源了解常见的 Web 漏洞,保持信息更新。