发布时间:2022-01-11 18:19:01 阅读次数:241
许多 Web 应用为用户提供了通过登录进行认证的方式。在 Web 应用中实现这个功能是一项复杂且有潜在安全风险的工作。出于这个原因,Laravel 努力为你提供快速、安全、简单的用户认证实现工具。
在底层代码中,Laravel 的认证组件由「guards」和「providers」组成,Guard 定义了用户在每个请求中如何实现认证,例如,Laravel 通过 session
guard 来维护 Session 存储的状态和 Cookie。
Provider 定义了如何从持久化存储中获取用户信息,Laravel 底层支持通过 Eloquent 和数据库查询构建器两种方式来获取用户,如果需要的话,你还可以定义额外的 Provider。
如果看到这些名词觉得云里雾里,大可不必太过担心,因为对绝大多数应用而言,只需使用默认认证配置即可,不需要做什么改动。实际上,几乎所有东西 Laravel 都已经为你配置好了。配置文件位于 config/auth.php
,其中包含了用于调整认证服务行为的、文档友好的选项配置。
学院君注:通俗点说,在进行登录认证的时候,要做两件事,一个是从数据库存取用户数据,一个是把用户登录状态保存起来,在 Laravel 的底层实现中,通过 Provider 存取数据,通过 Guard 存储用户认证信息,前者主要和数据库打交道,后者主要和 Session 打交道(API 例外)。
想要在新建的 Laravel 项目中快速实现用户认证功能?这可以通过安装官方提供的 入门套件扩展包 扩展包来实现。完成数据库迁移工作后,在浏览器中访问 /register
即可进入新用户注册页面进行体验。入门套件已经为完整的用户认证系统提供了所有必要的脚手架代码。
即使你选择不在你的 Laravel 应用中使用入门套件扩展包,安装Laravel Breeze 扩展包也是一个很好的机会来学习如何在一个实际的 Laravel 项目中实现所有认证功能,因为 Laravel Breeze 为你创建了认证相关的控制器、路由和视图,你可以查看这些文件中的实现代码来学习如何实现 Laravel 的认证功能。
默认情况下,Laravel 在 app/Models
目录下包含了一个 Eloquent 模型 App\Models\User
,这个模型可以和默认的 Eloquent 认证驱动一起使用。如果你的应用不使用 Eloquent,你可以使用 database
认证驱动,该驱动使用 Laravel 查询构建器与数据库交互。
为 App\Models\User
模型构建数据库表结构的时候,确保 password
字段长度至少有 60 位。保持默认字符串长度(255)是个不错的选择。
还有,你需要验证 users
表包含了 remember_token
,该字段是个可以为空的字符串类型,字段长度为 100,用于在登录时存储应用维护的「记住我」 Session 令牌。
Laravel 框架提供了多个认证相关的官方扩展包,接下来,我们来整体探究一下 Laravel 的认证生态系统并讨论每个扩展包的预期目标。
首先,来看看认证的原理。使用 Web 浏览器认证的时候,需要用户通过登录表单提供用户名和密码作为凭证,如果这些凭证是正确的,Laravel 应用会在用户 Session 中存储该认证用户的信息,然后将包含 Session ID 的 Cookie 通过响应头发送给客户端浏览器,以便后续该浏览器发起的 HTTP 请求可以通过 Session 与指定用户关联起来:服务端获取到带有 Session Cookie 的请求后,会基于 Session ID 获取 Session 数据,由于之前在 Session 中存储了认证用户信息,所以通过这种机制就可以将发起该请求的用户看作是「认证用户」。这样一个原本「无状态」的 HTTP 通信就变成「有状态的」了。
当一个远程服务需要认证后才访问 API 接口时,由于没有 Web 浏览器,所以就不能使用 Cookie 在客户端和服务端之间传递 Session ID 了,取而代之的,我们可以在每个请求中带上远程服务颁发的 API 访问令牌进行认证。服务端会验证令牌是否有效,如果有效的话就可以将该请求与数据表中持有该令牌的用户关联起来,实现认证的效果。
Laravel 内置的浏览器认证服务
Laravel 通过 Auth
和 Session
门面提供了内置的认证和会话服务,这些功能提供了基于 Cookie 的浏览器请求认证,你可以使用这些门面提供的方法验证用户登录凭证然后对用户进行认证操作。此外,这些服务还会自动存储相应的认证数据到用户 Session 并通过 HTTP 响应发送包含对应 Session ID 的 Cookie。这篇文档后续部分包含了如何使用这些服务。
应用入门套件
正如本文档后面所介绍的,你可以通过与 Laravel 内置认证服务交互来手动构建自定义的用户认证层,不过,为了帮助你快速起步,Laravel 官方发布了免费的认证扩展包,它们提供了强大的、现代的、完整的认证层代码实现,这些扩展包就是 Laravel Breeze、Laravel Jetstream 和 Laravel Fortify。
Laravel Breeze 是一个简单的、最小化的完整认证功能实现扩展包,包含了登录、注册、密码重置、邮箱验证和密码确认等功能。Laravel Breeze 的视图层使用的是 Blade 模板和 Tailwind CSS,要使用这个扩展包,请参考 Laravel 应用入门套件文档。
Laravel Fortify 是一个针对 Laravel 项目开发的开箱即用认证后端,实现了本文档介绍的大部分功能,包括基于 Cookie 的认证以及双因子认证和邮箱验证。Fority 是 Laravel Jetstream 认证功能的后端实现,也可以独立与 Laravel Sanctum 结合用于为 Laravel 单页面应用提供认证功能。
Laravel Jetstream 是一个功能强大的入门套件扩展包,基于 Tailwind CSS、Laravel Livewire 以及 Inertia.js 等前端技术栈为 Laravel Fortify 的后端认证服务提供了美观的、现代的 UI 界面。Laravel Jetstream 除了提供基于浏览器的 Cookie 认证外,还内置集成了 Laravel Sanctum 提供 API 令牌认证。Laravel 的 API 认证下面马上就会介绍。
Laravel API 认证服务
Laravel 官方提供了两个可选的扩展包帮助你管理 API 令牌和认证带有 API 令牌的请求:Passport 和 Sanctum。这两个库和 Laravel 内置的基于 Cookie 的认证库并不互斥,因为这些库主要关注 API 令牌认证而内置的认证服务关注的是基于 Cookie 的浏览器认证。很多应用会同时使用 Laravel 内置的基于 Cookie 的浏览器认证服务和任意一个 Laravel API 认证扩展包(Passport 和 Sanctum 二选一)。
Passport
Passport 是一个 OAuth2 认证服务商,提供了多个 OAuth2「授权类型」以便颁发不同类型的访问令牌。总体来说,它是一个健全且复杂的 API 认证扩展包。不过,大多数应用并不需要 OAuth2 规范提供的复杂特性,这会让开发者和用户都感到困惑。此外,开发者也一直对如何使用 Passport 认证 SPA 应用和移动应用感到困扰。
Sanctum
针对 OAuth2 的复杂和开发者的困扰,Laravel 官方开始着手构建更加简单、更加精练的认证扩展包用于处理来自浏览器的第一方 Web 请求和基于令牌的 API 请求,这个目标最终被落地为 Laravel Sanctum 的发布。对于除了 API 接口之外还提供第一方 Web UI 的应用、或者前后端分离的单页面应用、以及带有移动客户端的 Laravel 应用,优先推荐使用 Sanctum 这个认证扩展包。
Laravel Sanctum 是一个混合了 Web/API 认证的扩展包,可用于管理应用的整个认证流程。其背后的工作原理是对于一个基于 Sanctum 提供认证服务的应用,当服务端接收到请求时,Sanctum 会先判断请求是否包含引用了认证 Session 的会话 Cookie,如果没有通过会话 Cookie 认证,Sanctum 会继续检查请求是否包含 API 令牌,如果 API 令牌存在,则 Sanctum 会使用 API 令牌认证请求。想要了解更多关于这个处理流程的底层细节,请参考 Sanctum 官方文档。
Laravel Jetstream 认证脚手架代码中使用了 Laravel Sanctum 扩展包提供 API 认证服务,因为我们相信它能够满足大多数 Web 应用的认证需求。
总结 & 如何选择
总而言之,如果你的应用只会通过浏览器访问,使用 Laravel 内置的认证服务就好了。
接下来,如果应用提供了 API 接口,可以在 Passport 和 Sanctum 扩展包中任选其一提供 API 令牌认证。一般来说,优先使用 Sanctum,因为它位 API 认证、SPA 认证以及移动端认证提供了简单但完整的解决方案,包括对「作用域」和「权限」的支持。
如果你想要构建基于 Laravel 后端驱动的单页面应用(SPA),可以使用 Laravel Sanctum,使用 Sanctum 的时候,可以手动手动实现后端认证路由,也可以使用 Laravel Fority 作为后端认证服务提供者。
Passport 可用于构建基于 OAuth2 规范的认证功能,比如我们要做开放平台,需要提供针对第三方应用的授权认证(比如微信、支付宝、QQ、微博之类的开发平台),则只能选择 Passport。
最后,如果你想要在新安装的 Laravel 项目中快速搭建认证系统,推荐使用 Laravel Jetstream,其中包含了 Laravel 内置的认证服务(通过 Laravel Fortify 集成)和 Laravel Sanctum 提供完整的用户认证解决方案。