两个根页面;一种用于未经身份验证的用户,一种用于经过身份验证的用户
Two root pages; one for unauthenticated users, one for authenticated users
我想知道如何使用 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”时,抛出 "this clause cannot match because a previous clause at line 1 always matches" 错误。
我设想使用 if 语句和一个控制器来为两个页面提供服务,不幸的是我找不到关于如何实现这种策略的文档。
很可能,您想要做的是在控制器和视图渲染层处理它,而不是在路由器中。
在您的 "root" 或家庭控制器(任何一个提供“/”作为处理程序的控制器)中,您可以检查您的操作是否具有有效的授权用户,并呈现您的视图想要基于此。
这不是你问的,但在我看来,更好的处理方法是使用两个不同的命名空间,"/"
用于未经身份验证的用户,"/app"
(或其他)用于经过身份验证的用户。这使您和您的用户更容易区分两者,并降低系统复杂性。然后,如果未经身份验证的用户试图转到 "/app"
路由,您可以 return 一个 401 Unauthorized
响应(来自您的 App.AuthHandler
内部以及正确的错误消息,例如 "You need to be logged in to do that."
但是如果你坚持按照你写的去做,那么我会在 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 在同一个根“/”中实现两个页面?一种用于未经身份验证的用户,一种用于经过身份验证的用户。发生这种情况的用例示例是 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”时,抛出 "this clause cannot match because a previous clause at line 1 always matches" 错误。
我设想使用 if 语句和一个控制器来为两个页面提供服务,不幸的是我找不到关于如何实现这种策略的文档。
很可能,您想要做的是在控制器和视图渲染层处理它,而不是在路由器中。
在您的 "root" 或家庭控制器(任何一个提供“/”作为处理程序的控制器)中,您可以检查您的操作是否具有有效的授权用户,并呈现您的视图想要基于此。
这不是你问的,但在我看来,更好的处理方法是使用两个不同的命名空间,"/"
用于未经身份验证的用户,"/app"
(或其他)用于经过身份验证的用户。这使您和您的用户更容易区分两者,并降低系统复杂性。然后,如果未经身份验证的用户试图转到 "/app"
路由,您可以 return 一个 401 Unauthorized
响应(来自您的 App.AuthHandler
内部以及正确的错误消息,例如 "You need to be logged in to do that."
但是如果你坚持按照你写的去做,那么我会在 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。
同样,这种方法会使您的系统更加复杂。一般来说,除非你有充分的理由,否则你应该避免复杂性。尽可能遵守约定,您以后会感激不尽。 :)