Authentication 两个根页面;一个用于未经身份验证的用户,一个用于经身份验证的用户

Authentication 两个根页面;一个用于未经身份验证的用户,一个用于经身份验证的用户,authentication,routes,elixir,phoenix-framework,ueberauth,Authentication,Routes,Elixir,Phoenix Framework,Ueberauth,我想知道如何使用Phoenix实现在同一根“/”中有两个页面?一个用于未经身份验证的用户,另一个用于经过身份验证的用户。发生这种情况的用例有LinkedIn和Facebook,其中登录页面在“/”上提供,应用程序在“/”上提供 我使用Guardian进行身份验证,并将路由器设置为: pipeline :auth do plug Guardian.Plug.EnsureAuthenticated, handler: App.AuthHandler end pipeline :unau

我想知道如何使用Phoenix实现在同一根“/”中有两个页面?一个用于未经身份验证的用户,另一个用于经过身份验证的用户。发生这种情况的用例有LinkedIn和Facebook,其中登录页面在“/”上提供,应用程序在“/”上提供

我使用Guardian进行身份验证,并将路由器设置为:

 pipeline :auth do
   plug Guardian.Plug.EnsureAuthenticated, handler: App.AuthHandler
  end
 pipeline :unauth do
   plug Guardian.Plug.EnsureNotAuthenticated, handler: App.AuthHandler
 end

 scope "/", App.Web do
   pipe_through [:browser, :unauth]

   get "/", FrontController, :index
 end
 scope "/", App.Web do
   pipe_through [:browser, :auth]

   get "/page", ApplicationController, :index
 end
FrontController为未经身份验证的用户提供可访问的页面(例如登录页面),ApplicationController为实际应用程序提供服务

当ApplicationController提供“/”而不是“/”页面时,将抛出“this子句无法匹配,因为第1行的前一个子句始终匹配”错误


我设想使用if语句和一个控制器为这两个页面提供服务,不幸的是,我找不到关于如何实现这种策略的文档。

最有可能的情况是,您要做的是在控制器和视图渲染层而不是在路由器中处理此问题


在您的“根”或主控制器(无论谁提供“/”作为处理程序)中,您可以检查您的操作是否有有效的授权用户,并基于此呈现所需的视图。

这不是您所要求的,但我个人认为更好的处理方法是使用两个不同的名称空间,
“/”
用于未经身份验证的用户,而
“/app”
(或其他)用于经身份验证的用户。这使得您和您的用户更容易区分两者,并降低了系统复杂性。然后,如果未经身份验证的用户尝试转到
“/app”
路径,您可以返回
401未经授权的
响应(从
app.AuthHandler
内部)以及正确的错误消息,例如“您需要登录才能这样做”

但是,如果您坚持执行您编写的操作,那么我只需在
ApplicationController.index
中简单地处理该场景-无需使用
FrontController
。该索引操作可能如下所示:

defmodule MyApp.Web.ApplicationController do

  def index(conn, _) do
    case logged_in?(conn) do
      true ->
        user = Guardian.Plug.current_resource(conn)
        render conn, "logged_in_page.html", user: user
      false ->
        render conn, "front_page.html"
    end
  end

  # Note: This could be in a helper module
  defp logged_in?(conn) do
    Guardian.Plug.authenticated?(conn)
  end
end
这样,当用户转到
“/”
时,根据他们是否拥有有效的JWT,会为他们提供不同的页面


同样,尽管这种方法使您的系统更加复杂。一般来说,除非您有很好的理由,否则您应该避免复杂性。尽可能遵循惯例,稍后您会很感激的。

我认为这不可能在Phoenix的路由器中实现。您可以将路由指向一个全新的控制器,然后从中调用
ApplicationController.index
,如果用户已登录,则调用
FrontController.index
,否则调用
FrontController.index
。@Dogbert或从内部
FrontController.index
委托给
ApplicationController.index。