我在我的应用程序中创建了几条路径
scope "/", Socialistical do
pipe_through :browser # Use the default browser stack
get "/", UserController, :index
get "/sign_up", UserController, :sign_up
post "/create_user", UserController, :create
options "/create_user", UserController, :nothing
post "/session", SessionController, :create
delete "/logout", SessionController, :delete
get "/dashboard", DashboardController, :index
end
除仪表板之外的其他路线是可供公众使用的路线。但我想仅为经过身份验证的用户保护仪表板路由。我创建了一个会话模型
defmodule Socialistical.Session do
alias Socialistical.User
def current_user(conn) do
id = Plug.Conn.get_session(conn, :current_user)
if id, do: Socialistical.Repo.get(User, id)
end
def logged_in?(conn), do: !!current_user(conn)
end
我想利用这两种方法来保护所有即将推出的路由,这些路线仅供真实用户使用,请帮助我。我不知道如何制作/转换为插件。
答案 0 :(得分:1)
这是一个简单的例子。此示例仅处理验证登录用户。它不处理重定向到登录页面。
这是插件
defmodule Socialistical.Session do
@behaviour Plug
import Plug.Conn
alias Socialistical.Accounts.User
alias Socialistical.Repo
def current_user(conn), do: conn.assigns[:current_user]
def logged_in?(conn), do: !!current_user(conn)
def init(opts \\ []) do
# simple example to show how options can be passed
%{error: opts[:error] || "Not authorized"}
end
def call(conn, opts \\ []) do
if user = get_user(conn) do
# we have a session so store it for latter access
assign conn, :current_user, user
else
# not session
halt_with_error conn, opts[:error]
end
end
defp halt_with_error(conn, error) do
conn
|> send_resp(401, error)
|> halt
end
defp get_user(conn) do
case Plug.Conn.get_session(conn, "current_user") do
nil -> nil
id -> Repo.get(User, id)
end
end
end
路由器:
defmodule Socialistical.Web.Router do
use Socialistical.Web, :router
# ...
pipeline :protected do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug Socialistical.Session
end
scope "/", Socialistical.Web do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
get "/login/:id", PageController, :login
# just here for the example
resources "/users", UserController
end
scope "/", Socialistical.Web do
pipe_through :protected
get "/protected", PageController, :protected
end
end
这是一个用于测试的控制器。我添加了一个登录操作,只是为了测试它的全部工作。它仅用于演示目的,因为它不验证用户,只创建会话。
defmodule Socialistical.Web.PageController do
use Socialistical.Web, :controller
alias Socialistical.Accounts
def index(conn, _params) do
render conn, "index.html"
end
def protected(conn, _params) do
render conn, "protected.html"
end
def login(conn, %{"id" => id}) do
user = Accounts.get_user!(id)
conn
|> put_session("current_user", user.id)
|> assign(:current_user, user)
|> redirect(to: "/")
end
end
我测试了它,它应该都可以工作。您应该查看Plug docs。同样,您可以查看我的身份验证包Coherence Session plug以获取更多想法。