1

我想知道如何使用 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 提供“/”而不是“/page”时,会抛出“此子句无法匹配,因为第 1 行的前一个子句始终匹配”错误。

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

4

2 回答 2

3

这不是您所要求的,但以我的拙见,处理此问题的更好方法是使用两个不同的命名空间,"/"用于未经身份验证的用户和"/app"(或其他)用于经过身份验证的用户。这使您和您的用户更容易区分两者,并降低系统复杂性。然后,如果未经身份验证的用户尝试转到某个"/app"路线,您可以返回401 Unauthorized响应(从您的内部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。

同样,尽管这种方法使您的系统更加复杂。一般来说,除非你有充分的理由,否则你应该避免复杂性。尽可能遵守约定,以后您将不胜感激。:)

于 2017-03-27T16:56:28.073 回答
0

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

在您的“根”或家庭控制器(无论哪个提供“/”作为处理程序)中,您可以检查您的操作,如果您有一个有效的经过身份验证的用户,并基于此呈现您想要的视图。

于 2017-03-26T16:58:08.007 回答