2017-05-26 146 views
0

我按照指南http://rny.io/elixir/phoenix/ldap/2016/09/20/ldap-authenication-with-phoenix.html與Phoenix中的Guardian設置LDAP身份驗證。我對菲尼克斯和Elixir相當新穎,所以我正在完成設置和測試的動作。通過Guardian.Plug.EnsureAuthenticated測試通過LDAP進行身份驗證時

我有一切按照指南工作,但是,我無法弄清楚如何在編寫控制器測試時通過Guardian.Plug.EnsureAuthenticated。我遵循了在這裏找到的幾個指南,但似乎沒有任何工作。

是否有人使用exLDAP和Guardian設置了LDAP身份驗證,以及可以提供一些指導的適當用戶登錄以進行測試?任何幫助,將不勝感激。

下面是我的設置:

的lib/ldap_example/guardian_serializer.ex

defmodule LdapExample.GuardianSerializer do 
@behaviour Guardian.Serializer 
alias LdapExample.User 
alias LdapExample.Repo 

def for_token(user = %User{}), do: { :ok, "User:#{user.id}" } 
def for_token(_), do: { :error, "Unknown resource type" } 

def from_token("User:" <> id), do: { :ok, Repo.get(User, id) } 
def from_token(_), do: { :error, "Unknown resource type" } 
end 

的lib/ldap_example/ldap.ex

defmodule LdapExample.Ldap do 

    def authenticate(uid, password) do 
     {:ok, ldap_conn} = Exldap.open 
    bind = "uid=#{uid},dc=example,dc=com" 
    case Exldap.verify_credentials(ldap_conn, bind, password) do 
     :ok -> :ok 
     _ -> {:error, "Invalid username/password"} 
    end 
    end 



def get_by_uid(uid) do 
    {:ok, ldap_conn} = Exldap.connect 
    {:ok, search_results} = Exldap.search_field(ldap_conn, "uid", uid) 
    case search_results do 
     [] -> {:error, "Could not find user with uid #{uid}"} 
     _ -> search_results |> Enum.fetch(0) 
    end 
    end 



def to_map(entry) do 
    username = Exldap.search_attributes(entry, "uid") 
    name = Exldap.search_attributes(entry, "cn") 
    email = Exldap.search_attributes(entry, "mail") 
    %{username: username, name: name, email: email} 
    end 
end 

網/控制器/ session_controller.ex

defmodule LdapExample.SessionController do 
    use LdapExample.Web, :controller 
    alias LdapExample.{User, Repo, Ldap} 

    def new(conn, _params) do 
    render conn, "new.html", changeset: User.login_changeset 
    end 



def create(conn, %{"user" => params}) do 
    username = params["username"] 
    password = params["password"] 
    case Ldap.authenticate(username, password) do 
     :ok -> handle_sign_in(conn, username) 
     _ -> handle_error(conn) 
    end 
    end 

defp handle_sign_in(conn, username) do 
    {:ok, user} = insert_or_update_user(username) 
    conn 
    |> put_flash(:info, "Logged in.") 
    |> Guardian.Plug.sign_in(user) 
    |> redirect(to: page_path(conn, :index)) 
end 

defp insert_or_update_user(username) do 
    {:ok, ldap_entry} = Ldap.get_by_uid(username) 
    user_attributes = Ldap.to_map(ldap_entry) 
    user = Repo.get_by(User, username: username) 
    changeset = 
    case user do 
     nil -> User.changeset(%User{}, user_attributes) 
     _ -> User.changeset(user, user_attributes) 
    end 
    Repo.insert_or_update changeset 
end 

defp handle_error(conn) do 
    conn 
    |> put_flash(:error, "Wrong username or password") 
    |> redirect(to: session_path(conn, :new)) 
end 

def delete(conn, _params) do 
    Guardian.Plug.sign_out(conn) 
    |> put_flash(:info, "Logged out successfully.") 
    |> redirect(to: "/") 
end 

結束

網/模型/ user.ex

defmodule LdapExample.User do 
use LdapExample.Web, :model 

schema "users" do 
    field :username, :string 
    field :name, :string 
    field :email, :string 
    field :password, :string, virtual: true 
    timestamps() 
end 



def changeset(struct, params \\ %{}) do 
    struct 
    |> cast(params, [:username, :name, :email]) 
    |> validate_required([:username, :name, :email]) 
    end 



def login_changeset do 
    %__MODULE__{} |> cast(%{}, ~w(username password), ~w()) 
    end 
end 

我創建了一個session_controller_text.ex如下:因爲我重定向到登錄頁面

defmodule LdapExample.SessionControllerTest do 
    use LdapExample.ConnCase 
    alias LdapExample.User 



test "Get to Login page", %{conn: conn} do 
    conn = get conn, session_path(conn, :new) 
    assert html_response(conn, 200) =~ "Sign In" 
    end 

test "shows page only when logged in", %{conn: conn} do 
    conn = get conn, page_path(conn, :index) 
    assert html_response(conn, 200) =~ "Hello" 
    end 
end 

最後一次測試失敗。

回答

0

當然,您應該使用bypass_through來跳過用於測試目的的身份驗證過程。閱讀更多的docs

+0

然而,謝謝你,我更想找到如何模擬一個實際的登錄進行測試。 – willfore

+0

嘗試模擬負責與LDAP連接的模塊,做類似於此處介紹的事情:http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ – PatNowak

+0

在圍繞方式這些回答了我的問題。謝謝 – willfore

相關問題