- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我为用户资源创建身份验证,它工作正常,但现在我想使用从 user_controller.ex 到 project_controller.ex 的身份验证功能。
如果我将身份验证私有(private)函数从 user_controller 复制到 project_controller,则身份验证适用于项目资源,但我不想在每个 Controller 中复制此身份验证功能。我需要知道干燥此代码的最佳方法是什么。我认为路由器是添加身份验证插件的好地方,但我需要知道我应该在哪里添加代码。
路由器.ex
defmodule Auth.Router do
use Auth.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug Auth.Auth, repo: Auth.Repo
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", Auth do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
resources "/users", UserController
resources "/sessions", SessionController, only: [:new, :create, :delete]
resources "/projects", ProjectController
end
end
defmodule Auth.UserController do
use Auth.Web, :controller
plug :authenticate when action in [:index, :show]
alias Auth.User
plug :scrub_params, "user" when action in [:create, :update]
def index(conn, _params) do
users = Repo.all(User)
render(conn, "index.html", users: users)
end
def new(conn, _params) do
changeset = User.changeset(%User{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"user" => user_params}) do
changeset = User.registration_changeset(%User{}, user_params)
case Repo.insert(changeset) do
{:ok, user} ->
conn
|> Auth.Auth.login(user)
|> put_flash(:info, "#{user.username} created successfully.")
|> redirect(to: user_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
user = Repo.get!(User, id)
render(conn, "show.html", user: user)
end
def edit(conn, %{"id" => id}) do
user = Repo.get!(User, id)
changeset = User.changeset(user)
render(conn, "edit.html", user: user, changeset: changeset)
end
def update(conn, %{"id" => id, "user" => user_params}) do
user = Repo.get!(User, id)
changeset = User.changeset(user, user_params)
case Repo.update(changeset) do
{:ok, user} ->
conn
|> put_flash(:info, "User updated successfully.")
|> redirect(to: user_path(conn, :show, user))
{:error, changeset} ->
render(conn, "edit.html", user: user, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
user = Repo.get!(User, id)
Repo.delete!(user)
conn
|> put_flash(:info, "User deleted successfully.")
|> redirect(to: user_path(conn, :index))
end
defp authenticate(conn, _opts) do
if conn.assigns.current_user do
conn
else
conn
|> put_flash(:error, "You must be login to access that page.")
|> redirect(to: page_path(conn, :index))
|> halt()
end
end
end
defmodule Auth.User do
use Auth.Web, :model
schema "users" do
field :username, :string
field :password_hash, :string
field :password, :string, virtual: true
timestamps
end
def changeset(model, params \\ :empty) do
model
|> cast(params, ~w(username), [])
|> validate_length(:username, min: 3, max: 20)
end
def registration_changeset(model, params) do
model
|> changeset(params)
|> cast(params, ~w(password), [])
|> validate_length(:password, min: 6, max: 100)
|> put_pass_hash()
end
defp put_pass_hash(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
put_change(changeset, :password_hash, Comeonin.Bcrypt.hashpwsalt(pass))
_ ->
changeset
end
end
end
defmodule Auth.Auth do
import Plug.Conn
import Comeonin.Bcrypt, only: [checkpw: 2]
def init(opts) do
Keyword.fetch!(opts, :repo)
end
def call(conn, repo) do
user_id = get_session(conn, :user_id)
user = user_id && repo.get(Auth.User, user_id)
assign(conn, :current_user, user)
end
def login(conn, user) do
conn
|> assign(:current_user, user)
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
end
def login_by_username_and_pass(conn, username, given_pass, opts) do
repo = Keyword.fetch!(opts, :repo)
user = repo.get_by(Auth.User, username: username)
cond do
user && checkpw(given_pass, user.password_hash) ->
{:ok, login(conn, user)}
user ->
{:error, :unauthorized, conn}
true ->
{:error, :not_found, conn}
end
end
def logout(conn) do
# configure_session(conn, drop: true)
delete_session(conn, :user_id)
end
end
defmodule Auth.ProjectController do
use Auth.Web, :controller
plug :authenticate when action in [:index, :new, :show]
alias Auth.Project
plug :scrub_params, "project" when action in [:create, :update]
def index(conn, _params) do
projects = Repo.all(Project)
render(conn, "index.html", projects: projects)
end
def new(conn, _params) do
changeset = Project.changeset(%Project{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"project" => project_params}) do
changeset = Project.changeset(%Project{}, project_params)
case Repo.insert(changeset) do
{:ok, _project} ->
conn
|> put_flash(:info, "Project created successfully.")
|> redirect(to: project_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
project = Repo.get!(Project, id)
render(conn, "show.html", project: project)
end
def edit(conn, %{"id" => id}) do
project = Repo.get!(Project, id)
changeset = Project.changeset(project)
render(conn, "edit.html", project: project, changeset: changeset)
end
def update(conn, %{"id" => id, "project" => project_params}) do
project = Repo.get!(Project, id)
changeset = Project.changeset(project, project_params)
case Repo.update(changeset) do
{:ok, project} ->
conn
|> put_flash(:info, "Project updated successfully.")
|> redirect(to: project_path(conn, :show, project))
{:error, changeset} ->
render(conn, "edit.html", project: project, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
project = Repo.get!(Project, id)
# Here we use delete! (with a bang) because we expect
# it to always work (and if it does not, it will raise).
Repo.delete!(project)
conn
|> put_flash(:info, "Project deleted successfully.")
|> redirect(to: project_path(conn, :index))
end
# defp authenticate(conn, _opts) do
# if conn.assigns.current_user do
# conn
# else
# conn
# |> put_flash(:error, "You must be login to access that page.")
# |> redirect(to: page_path(conn, :index))
# |> halt()
# end
# end
end
最佳答案
这是一个相当普遍的模式。首先你需要你的认证插件:
defmodule Auth.Plug.Authenticate do
@behaviour Plug
import Plug.Conn
import Phoenix.Controller, only: [put_flash: 3, redirect: 2]
def init(opts), do: opts
def call(conn, _opts) do
if conn.assigns.current_user do
conn
else
conn
|> put_flash(:error, "You must be login to access that page.")
|> redirect(to: Auth.Router.Helpers.page_path(conn, :index))
|> halt()
end
end
end
defmodule Auth.Router do
use Auth.Web, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
plug Auth.Auth, repo: Auth.Repo
end
pipeline :authenticated do
plug Auth.Plug.Authenticate, repo: Auth.Repo
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", Auth do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
resources "/sessions", SessionController, only: [:new, :create]
end
scope "/", Auth do
pipe_through [:browser, :authenticated]
resources "/users", UserController
resources "/sessions", SessionController, only: [:delete]
resources "/projects", ProjectController
end
end
关于elixir - 如何在phoenix elixir中添加插件路由器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33219200/
我正在尝试从模板中的列表( )中提取值,但出现此错误: lists in Phoenix.HTML and templates may only contain integers represent
我正在阅读 Programming Phoenix 这本书,一切都很好,直到第 44 页要求我重新启动 Phoenix 服务器。 我用双 Ctrl + C 杀死了当前服务器,但是当我尝试再次运行 mi
我的应用程序和 api json 请求以及常规 html 都可以工作。我的路由器.ex defmodule MyApp.Router do use MyApp.Web, :router pip
我想在模板中将对象呈现为 JSON。我试过: 但是我得到一个错误 protocol Phoenix.HTML.Safe not implemented for %Ecto.Changeset{...
在 phoenix 框架的 View 中,在 div 元素内生成两个 span 元素的方法是什么? 最佳答案 为了做到这一点,可以只使用一个数组并将其作为 div 标签的值传递给内部,如下所示: de
我从 Rails 迁移,并希望这能在我的模板中工作? hello world 似乎没有一个条件得到呈现。如何实现这一目标? 谢
完成示例指南。本章中详细介绍的内容在我的应用程序中不起作用。看起来很简单的事情。我有一个视频模型: defmodule Rumbl.Video do use Rumbl.Web, :model
完成示例指南。本章中详细介绍的内容在我的应用程序中不起作用。看起来很简单的事情。我有一个视频模型: defmodule Rumbl.Video do use Rumbl.Web, :model
通过可选“inputs_for”输入的 Phoenix 嵌套表单导致 Controller 中的 map 无法通过验证。例如,一个帖子有评论。如果我想在创建帖子时为帖子添加评论,嵌套表单将如下所示:
我正在尝试在应用程序中实现不同的语言。所以我所做的是在 Session 的 db 中创建了 lang 变量,它保留了当前选择的语言。 问题是我正在通过更新操作调用和更新值: def update(co
我想在我的网站上实现一个典型的“记住我”功能,它需要一种方法来创建在遥远的 future 过期的 cookie。有没有办法在 Phoenix Framework 中创建它们? 最佳答案 只要给 coo
我正在制作一个多站点应用程序。我想在测试 Controller 之前在连接上设置请求主机。在 Rails 中,我们可以使用 before :each do request.env["HTTP_RE
我知道我可以通过包含以下内容来更新实时取景: if connected?(socket), do: :timer.send_interval(10000, self(), :click) 但是,有没有
Ruby on Rails 带有终端命令 rake routes . Phoenix 有类似的吗? 最佳答案 命令是 $ mix phoenix.routes 关于phoenix-framework
我正在尝试使用 addict包以在我的项目中进行身份验证,但是每当我尝试执行操作(注册、登录...)时,我的 POST 都会出现 CrossDomain 错误。 我已经尝试添加 cors_plug包来
我在 Phoenix 项目,和mix ecto.create , mix ecto.migrate , 和 mix ecto.drop都发出相同的错误: $ mix ecto.drop ==> tzd
在我的帖子模型上,我实现了一个简单的验证 def changeset(model, params \\ :empty) do model |> cast(params, @requ
这主要是为了测试目的,但是我怎样才能在 Heroku 上实现与 mix ecto.reset 相同的效果。这样的命令导致 FATAL: permission denied for database "
我们的 Web 应用程序目前在 C# 中运行在 Windows 和 IIS 上。我们严重依赖此环境中包含的 Windows 身份验证方案。启用 Windows 身份验证后,我们可以检测连接用户的身份,
在我的 Phoenix 应用程序中,我想对单个记录运行 get_by() Ecto 查询 - 但是,我要搜索的字段之一应该评估为 nil ,但 Phoenix/Ecto 禁止使用 nil 作为比较运算
我是一名优秀的程序员,十分优秀!