1

我的应用中有两个用户,买家和管理员,他们都有不同的登录详细信息,管理员使用电子邮件和密码登录,买家使用他们的电话号码和我们发送给他们的代码登录。所以,我做了两个认证插件。这是我将插件添加到浏览器管道的方式:

pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :fetch_flash
  plug Phoenix.LiveView.Flash
  plug :protect_from_forgery
  plug :put_secure_browser_headers
  plug AffirmWeb.BuyerAuth
  plug AffirmWeb.AdminAuth
end

所以问题来了,当管理员登录时,他们得到登录菜单,他们可以访问所有其他页面。当买家登录时,我可以从日志中看到(我 IO.inspect 连接,所以我知道他们已经登录),他们仍然得到“退出”菜单,他们也无法访问某些页面。如果我将管道顺序更改为 AffirmWeb.BuyerAuth 排在最后,那么现在买家可以访问其他页面而管理员无法访问。关于如何解决这个问题的任何指导?

4

2 回答 2

2

为什么不使用范围路由并创建两个管道和两个范围,一个给买家,一个给管理员:

pipeline :browser do
  plug :accepts, ["html"]
  plug :fetch_session
  plug :fetch_flash
  plug Phoenix.LiveView.Flash
  plug :protect_from_forgery
  plug :put_secure_browser_headers
end

pipeline :buyer do
  plug AffirmWeb.BuyerAuth
end

pipeline :admin do
  plug AffirmWeb.AdminAuth
end

scope "/" do
  pipe_through :browser

  # ...routes for unauthenticated visitors...
end

scope "/buyer", AffirmWeb.Buyer do
  pipe_through [:browser, :buyer]

  # ...buyer routes...
end

scope "/admin", AffirmWeb.Admin, as: :admin do
  pipe_through [:browser, :admin]

  # ...admin routes...
end

现在更容易区分用户类型并使用不同的插件、控制器或布局模板。

您可以使用选项来scope为生成的 url 和路径帮助程序获得不同的结果。

于 2020-03-31T13:54:52.067 回答
0

如果没有看到身份验证插件的真实代码,很难提出任何建议,但一般建议是:用两个插件组成一个插件,然后在逻辑上或那里做。在您当前的代码中,后者似乎总是获胜,这可能用以下伪代码粗略描述:

a = is_buyer?
a = is_admin?
return a

相反,你想要有点像

a = 
  cond do
    is_buyer? -> :buyer
    is_admin? -> :admin
    _ -> :unknown
  end

因此,创建一个调用现有插件的插件,并在满足任何条件时立即返回。

于 2020-03-31T06:22:56.123 回答