如何authenticate/authorize限时匿名用户?

How to authenticate/authorize anonymous user for a limited time?

假设我有一个发票实体。发票属于某个用户 (invoices.user_id)。

如果用户输入 myapp.com/invoices/1,他需要登录才能访问他的发票。这很正常。

有时 invoices.user_id 为空(发票所有者在我们的系统中没有帐户),但我们有一个 invoices.phone_number 列。

目标是为在我们系统中没有帐户的用户创建一个基于短信代码验证的身份验证系统。如果用户确认他确实拥有与发票相关的 phone 号码(代码验证),我想授予他临时访问此发票详细信息页面(且仅此页面)的权限(15 分钟)。

我的第一个想法是使用存储在会话中的 JWT 令牌。

我的第二个想法是使用自定义防火墙。

有没有更好的方法?

创建 kernel.request listener。这样您就可以在执行任何操作之前采取行动,并且整个应用程序都不会注意到用户可以随时注销的事实。

调用一个 "service" 来验证令牌。如果令牌无效,请清除身份验证状态并覆盖请求。例如,将用户重定向到 "you need to pay again" 页面。

这样你就不需要修改任何代码,执行任何选民等等,你的整个应用程序都可以得到保护。

至于身份验证本身,请选择 custom guard,您可以在其中完全控制身份验证过程的工作方式。

您可以使用以下操作验证虚拟用户 15 分钟:

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;

public function indexAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();

    /**
     * confirm that the user indeed owns 
     * phone number related to the invoice (code verification)
     */

    //create a user for this task only and fetch it
    $user = $em->getRepository(User::class)->find(1);

    //firewall name used for authentication in security.yml
    $firewall = "main_secured_area";

    $token = new UsernamePasswordToken($user, null, $firewall, $user->getRoles());
    $this->get('security.token_storage')->setToken($token);
    $this->get('session')->set("_security_$firewall", serialize($token));

    //$lifetime takes number of seconds to define session timeout 15min = 900sec
    $this->container->get('session')->migrate($destroy = false, $lifetime = 900);

    //fire the login event manually
    $event = new InteractiveLoginEvent($request, $token);
    $this->get("event_dispatcher")->dispatch("security.interactive_login", $event);

    return $this->render('default/index.html.twig');
}