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

时间:2017-03-25 19:38:24

标签: authentication routes elixir phoenix-framework ueberauth

我想知道如何在同一根中实现两个页面" /"用凤凰?一个用于未经身份验证的用户,另一个用于经过身份验证的用户。发生这种情况的用例的例子是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",a"此子句无法匹配,因为第1行的前一个子句始终匹配"抛出错误。

我想使用if语句和一个控制器来提供这两个页面,遗憾的是我无法找到有关如何实现这种策略的文档。

2 个答案:

答案 0 :(得分:2)

这不是你提出的问题,但我认为更好的方法是使用两个不同的命名空间,"/"用于未经身份验证的用户和"/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。

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

答案 1 :(得分:0)

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

在“root”或家庭控制器内(无论是作为处理程序提供的“/”),如果您拥有有效的auth'd用户,您可以检查您的操作,并根据该用户渲染您想要的视图