登录/注册按钮

我们至今还没有在页面上添加登录/注册按钮,这对普通用户来说非常不友好。

老规则,先写测试,我们不再新增,而是加在旧测试中:

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
+    # 未登录情况下访问首页,应带有登录/注册文字
+    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

全部通过。

在进入下一章前,我们还有个安全相关的问题需要略作修改:

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.exuser_controller.ex 两个文件中加入了 configure_session(renew: true),用于预防 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)

下一章,我们要对用户相关页面做些限制,以保证数据的安全。

上一章:退出登录 下一章:安全限制

最后更新于