Laravel Sanctum auth:sanctum 具有 Angular SPA 未验证响应的中间件
Laravel Sanctum auth:sanctum middleware with Angular SPA unauthenticated response
我有一个具有以下设置的应用程序:
Laravel
主持人:appname.local:8000
环境变量:
- SESSION_DRIVER=数据库
- SESSION_LIFETIME=480
- SESSION_CONNECTION=mysql
- SESSION_DOMAIN=.appname.local
- SESSION_SECURE_COOKIE=假
- SESSION_COOKIE=appnameapi_session
- SANCTUM_STATEFUL_DOMAINS='.appname.local,localhost,127.0.0.1'
Angular
主持人:appname.local:4200
目前有效:
- 我可以调用 Sanctum 的 csrf-cookie 端点,它在我的浏览器中设置 CSRF 令牌。
- 然后我可以调用我的 API 的登录端点,使用 Auth::attempt() 对我的 Laravel 应用程序中的用户进行身份验证。这会在会话 table 中创建一个新条目,如下所示
Angular 获取令牌和验证用户的方法
成功验证后的会话数据库条目
什么不起作用:
对受以下中间件保护的路由的后续请求:auth:sanctum 都会导致未经身份验证的响应。 HTTP 请求永远不会到达我的控制器。
auth:sanctum 保护路由
但我可以在开发者控制台中看到正在发送 cookie。所以我不明白为什么 Sanctum 不接受授权
我已经学习了几个教程,但我似乎无法理解为什么 Laravel 的 Authenticate 中间件无法看到我已经对我的用户进行了身份验证。
有谁知道我哪里做错了吗?
Laravel Sanctum 似乎不支持 SPA 的通配符域。
尝试删除点。
SANCTUM_STATEFUL_DOMAINS='appname.local'
您可能需要针对通配符子域的不同解决方案。您可以查看不记名令牌选项。我还没有测试过这个。
我认为艾登是正确的。我出于不相关的原因正在访问这个问题,但是为了支持子域,您可以在 SESSION_DOMAIN
env 变量中有一个点,但永远不要 SANCTUM_STATEFUL_DOMAINS
.
这是本地和生产环境的有效环境配置:
./.env
# localhost
SANCTUM_STATEFUL_DOMAINS="angular-site.test"
SESSION_DOMAIN=".angular-site.test"
# production
# SANCTUM_STATEFUL_DOMAINS="hockeysticks.net"
# SESSION_DOMAIN=".hockeysticks.net"
这将允许 cookie 跨多个子域工作,例如 auth.hockeysticks.net
、product.hockeysticks.net
、service.hockeysticks.net
和 api.hockeysticks.net
。
如果有人在 SESSION_DOMAIN
中输入点,如果没有子域,cookie 仍然有效,但在这种情况下省略它理论上应该更安全。
这是 Laravel 的开发人员 Mohamed Said 的一段视频,其中谈到了 Sanctum:https://www.youtube.com/watch?v=Kd3hcrxtTHA。在其中,他介绍了身份验证逻辑。
@agm1984 和@Eden Webstudio 提供的答案非常有用。但是,他们没有解决我的问题。
进一步调试后,我注意到 sanctum 的守卫逻辑在
config/sanctum.php
。它的默认值为 web。我对受保护路由的默认守卫是 api 守卫,这是我在身份验证过程中使用的守卫。
在 config/sanctum.php 和 'api' 中设置保护密钥后,身份验证似乎工作顺利。老实说,我不记得为什么我决定为我的 api 守卫使用 session 驱动程序。
config/auth.php
我遇到了同样的问题。我发现如果请求来自未在端口号上设置的应用程序,则 sanctum SPA API 工作正常。
您可以在
上托管您的前端应用
appname.local
而不是 appname.local:4200
如果您的前端和后端使用 localhost,端口不同,如下所示:
Angular/Ionic
Host: localhost:8100
Laravel v8
Host: localhost:8000
尝试将 ./env 设置为:
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:8100
请记住,我在关注@Gloire 的回答后设置了以下内容
我有一个具有以下设置的应用程序:
Laravel
主持人:appname.local:8000
环境变量:
- SESSION_DRIVER=数据库
- SESSION_LIFETIME=480
- SESSION_CONNECTION=mysql
- SESSION_DOMAIN=.appname.local
- SESSION_SECURE_COOKIE=假
- SESSION_COOKIE=appnameapi_session
- SANCTUM_STATEFUL_DOMAINS='.appname.local,localhost,127.0.0.1'
Angular
主持人:appname.local:4200
目前有效:
- 我可以调用 Sanctum 的 csrf-cookie 端点,它在我的浏览器中设置 CSRF 令牌。
- 然后我可以调用我的 API 的登录端点,使用 Auth::attempt() 对我的 Laravel 应用程序中的用户进行身份验证。这会在会话 table 中创建一个新条目,如下所示
Angular 获取令牌和验证用户的方法
成功验证后的会话数据库条目
什么不起作用:
对受以下中间件保护的路由的后续请求:auth:sanctum 都会导致未经身份验证的响应。 HTTP 请求永远不会到达我的控制器。
auth:sanctum 保护路由
但我可以在开发者控制台中看到正在发送 cookie。所以我不明白为什么 Sanctum 不接受授权
我已经学习了几个教程,但我似乎无法理解为什么 Laravel 的 Authenticate 中间件无法看到我已经对我的用户进行了身份验证。
有谁知道我哪里做错了吗?
Laravel Sanctum 似乎不支持 SPA 的通配符域。
尝试删除点。
SANCTUM_STATEFUL_DOMAINS='appname.local'
您可能需要针对通配符子域的不同解决方案。您可以查看不记名令牌选项。我还没有测试过这个。
我认为艾登是正确的。我出于不相关的原因正在访问这个问题,但是为了支持子域,您可以在 SESSION_DOMAIN
env 变量中有一个点,但永远不要 SANCTUM_STATEFUL_DOMAINS
.
这是本地和生产环境的有效环境配置:
./.env
# localhost
SANCTUM_STATEFUL_DOMAINS="angular-site.test"
SESSION_DOMAIN=".angular-site.test"
# production
# SANCTUM_STATEFUL_DOMAINS="hockeysticks.net"
# SESSION_DOMAIN=".hockeysticks.net"
这将允许 cookie 跨多个子域工作,例如 auth.hockeysticks.net
、product.hockeysticks.net
、service.hockeysticks.net
和 api.hockeysticks.net
。
如果有人在 SESSION_DOMAIN
中输入点,如果没有子域,cookie 仍然有效,但在这种情况下省略它理论上应该更安全。
这是 Laravel 的开发人员 Mohamed Said 的一段视频,其中谈到了 Sanctum:https://www.youtube.com/watch?v=Kd3hcrxtTHA。在其中,他介绍了身份验证逻辑。
@agm1984 和@Eden Webstudio 提供的答案非常有用。但是,他们没有解决我的问题。
进一步调试后,我注意到 sanctum 的守卫逻辑在
config/sanctum.php
。它的默认值为 web。我对受保护路由的默认守卫是 api 守卫,这是我在身份验证过程中使用的守卫。
在 config/sanctum.php 和 'api' 中设置保护密钥后,身份验证似乎工作顺利。老实说,我不记得为什么我决定为我的 api 守卫使用 session 驱动程序。
config/auth.php
我遇到了同样的问题。我发现如果请求来自未在端口号上设置的应用程序,则 sanctum SPA API 工作正常。
您可以在
上托管您的前端应用appname.local
而不是 appname.local:4200
如果您的前端和后端使用 localhost,端口不同,如下所示:
Angular/Ionic
Host: localhost:8100
Laravel v8
Host: localhost:8000
尝试将 ./env 设置为:
SESSION_DOMAIN=localhost
SANCTUM_STATEFUL_DOMAINS=localhost:8100
请记住,我在关注@Gloire 的回答后设置了以下内容