我們至今還沒有在頁面上添加登錄/注冊按鈕,這對普通用戶來說非常不友好。
老規(guī)則,先寫測試,我們不再新增,而是加在舊測試中:
diff --git a/test/controllers/session_controller_test.exs b/test/controllers/session_controller_test.exs
index 969662a..98fbb5a 100644
--- a/test/controllers/session_controller_test.exs
+++ b/test/controllers/session_controller_test.exs
@@ -14,6 +14,10 @@ defmodule TvRecipe.SessionControllerTest do
user_changeset = User.changeset(%User{}, @valid_user_attrs)
# 插入新用戶
user = Repo.insert! user_changeset
+ # 未登錄情況下訪問首頁,應(yīng)帶有登錄/注冊文字
+ conn = get conn, Routes.page_path(conn, :index)
+ assert html_response(conn, 200) =~ "登錄"
+ assert html_response(conn, 200) =~ "注冊"
# 用戶登錄
conn = post conn, Routes.session_path(conn, :create), session: @valid_user_attrs
# 顯示“歡迎你”的消息
打開 app.html.eex
文件,添加兩個按鈕:
diff --git a/web/templates/layout/app.html.eex b/web/templates/layout/app.html.eex
index 6c87a08..b13f370 100644
--- a/web/templates/layout/app.html.eex
+++ b/web/templates/layout/app.html.eex
@@ -20,6 +20,9 @@
<%= if @current_user do %>
<li><%= link @current_user.username, to: Routes.user_path(@conn, :show, @current_user) %></li>
<li><%= link "退出", to: Routes.session_path(@conn, :delete, @current_user), method: "delete" %></li>
+ <% else %>
+ <li><%= link "登錄", to: Routes.session_path(@conn, :new) %></li>
+ <li><%= link "注冊", to: Routes.user_path(@conn, :new) %></li>
<% end %>
</ul>
</nav>
運行測試:
mix test
....................................
Finished in 0.8 seconds
36 tests, 0 failures
全部通過。
在進(jìn)入下一章前,我們還有個安全相關(guān)的問題需要略作修改:
diff --git a/web/controllers/session_controller.ex b/web/controllers/session_controller.ex
index 6ac524c..0c2eb0a 100644
--- a/web/controllers/session_controller.ex
+++ b/web/controllers/session_controller.ex
@@ -15,6 +15,7 @@ defmodule TvRecipe.SessionController do
conn
|> put_session(:user_id, user.id)
|> put_flash(:info, "歡迎你")
+ |> configure_session(renew: true)
|> redirect(to: Routes.page_path(conn, :index))
# 用戶存在,但密碼錯誤
user ->
diff --git a/web/controllers/user_controller.ex b/web/controllers/user_controller.ex
index 8d8a6f5..8b9b38b 100644
--- a/web/controllers/user_controller.ex
+++ b/web/controllers/user_controller.ex
@@ -21,6 +21,7 @@ defmodule TvRecipe.UserController do
conn
|> put_flash(:info, "User created successfully.")
|> put_session(:user_id, user.id)
+ |> configure_session(renew: true)
|> redirect(to: Routes.page_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
我們在 session_controller.ex
與 user_controller.ex
兩個文件中加入了 configure_session(renew: true)
,用于預(yù)防 session fixation 攻擊。
另外,本著 DRY 的原則,我們可以將登錄的邏輯合并到 auth.ex
文件中:
diff --git a/web/controllers/auth.ex b/web/controllers/auth.ex
index 994112d..e298b68 100644
--- a/web/controllers/auth.ex
+++ b/web/controllers/auth.ex
@@ -15,4 +15,10 @@ defmodule TvRecipeWeb.Auth do
assign(conn, :current_user, user)
end
+ def login(conn, user) do
+ conn
+ |> put_session(:user_id, user.id)
+ |> configure_session(renew: true)
+ end
+
end
diff --git a/web/controllers/session_controller.ex b/web/controllers/session_controller.ex
index 0c2eb0a..6f29ce0 100644
--- a/web/controllers/session_controller.ex
+++ b/web/controllers/session_controller.ex
@@ -13,9 +13,8 @@ defmodule TvRecipe.SessionController do
# 用戶存在,且密碼正確
user && Comeonin.Bcrypt.checkpw(password, user.password_hash) ->
conn
- |> put_session(:user_id, user.id)
|> put_flash(:info, "歡迎你")
- |> configure_session(renew: true)
+ |> TvRecipeWeb.Auth.login(user)
|> redirect(to: Routes.page_path(conn, :index))
# 用戶存在,但密碼錯誤
user ->
diff --git a/web/controllers/user_controller.ex b/web/controllers/user_controller.ex
index 8b9b38b..b9234b1 100644
--- a/web/controllers/user_controller.ex
+++ b/web/controllers/user_controller.ex
@@ -20,8 +20,7 @@ defmodule TvRecipe.UserController do
{:ok, user} ->
conn
|> put_flash(:info, "User created successfully.")
- |> put_session(:user_id, user.id)
- |> configure_session(renew: true)
+ |> TvRecipeWeb.Auth.login(user)
|> redirect(to: Routes.page_path(conn, :index))
{:error, changeset} ->
render(conn, "new.html", changeset: changeset)
更多建議: