我想知道如何在同一根中实现两个页面" /"用凤凰?一个用于未经身份验证的用户,另一个用于经过身份验证的用户。发生这种情况的用例的例子是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语句和一个控制器来提供这两个页面,遗憾的是我无法找到有关如何实现这种策略的文档。
答案 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用户,您可以检查您的操作,并根据该用户渲染您想要的视图