LoginSignup
40

More than 5 years have passed since last update.

Elixir, PhoenixでLoginページを作成

Last updated at Posted at 2015-06-16

やりたいことはログインページでemailpasswordを入力して、ログインするとユーザー一覧ページに遷移します。

スクリーンショット 2015-06-16 13.04.08.png

スクリーンショット 2015-06-16 13.04.44.png
スクリーンショット 2015-06-16 13.06.35.png

まずユーザー一覧ページを用意するためにPhoenixのEctoに関するドキュメントを読むといいです。

ログインページはネット上で探したものを使っています。その中にBootstrap3が含まれているので、Bootstrap3も使いたいです。自分のこの前の投稿を参照にするといいです。

  • プロジェクトを作成します。--no-brunchについての説明はここにあります。
13:29:11 [N1210A001 => ~/Playground/elixir]
$ mix phoenix.new hello_phoenix --no-brunch
  • ユーザー一覧のページを用意します。下のコマンドを実行するとhello_phoenix/priv/repo/migrations/ディレクトリの下にmigrationファイルが生成されて、後で使う$ mix ecto.migrateコマンドの為です。
13:34:30 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix phoenix.gen.html User users name:string email:string password:string
  • resources "/users", UserControllerhello_phoenix/web/router.exに追加します。

  • hello_phoenix_devデータベースを作成します。なぜhello_phoenix_devを作成するかはhello_phoenix/config/dev.exsファイルの中に定義されています。

postgresのroleがないなどのエラー出ている場合はこのページで答えは探せます。

13:37:18 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix ecto.create
  • 作成されたデーターベスにテーブルを作成します。
13:47:53 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix ecto.migrate
  • これでアプリを立ち上げてみます。下の図のようになっているはずです。
13:48:01 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix phoenix.server

スクリーンショット 2015-06-16 13.49.03.png

* 画面上でユーザを複数を作成します。

スクリーンショット 2015-06-16 13.55.00.png

1) hello_phoenix/web/templates/layout/application.html.eexを下のように修正します。

 <!DOCTYPE html>
 <html lang="en">
   <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="description" content="">
     <meta name="author" content="">

     <title>Hello Phoenix!</title>
     <link rel="stylesheet" href="<%= static_path(@conn, "/css/bootstrap.css") %>">
     <link rel="stylesheet" href="<%= static_path(@conn, "/css/login.css") %>">
     <link rel="stylesheet" href="<%= static_path(@conn, "/js/bootstrap.js") %>">
   </head>

   <body>
     <%= @inner %>
   </body>
 </html>

2) hello_phoenix/web/templates/page/index.html.eexを下のように修正します。

 <div class="container">
     <div class="row">
         <div class="col-sm-6 col-md-4 col-md-offset-4">
             <div class="account-wall">
               <form class="form-signin" action="<%= page_path(@conn, :login) %>" method="post">
                 <input type="text" class="form-control" name="user[email]" placeholder="Email" required autofocus>
                 <input type="password" class="form-control" name="user[password]" placeholder="Password" required>
                 <input type="hidden" name="_csrf_token" value="<%= get_csrf_token() %>">
                 <button class="btn btn-lg btn-primary btn-block" type="submit">
                     Sign in</button>
                 <label class="checkbox pull-left">
                     <input type="checkbox" value="remember-me">
                     Remember me
                 </label>
                 <a href="#" class="pull-right need-help">Need help? </a><span class="clearfix"></span>
                 </form>
             </div>
             <a href="#" class="text-center new-account">Create an account </a>
         </div>
     </div>
 </div>

なぜ<input type="hidden" name="_csrf_token" value="<%= get_csrf_token() %>">を入れているかはstackoverflowの質問を参照するといいです。この1行を入れないと、下のようなエラーが出ます。
invalid CSRF (Cross Site Forgery Protection) token, make sure all requests include a '_csrf_token' param or an 'x-csrf-token' header

スクリーンショット 2015-06-16 15.09.07.png

3) login.cssファイルを下の中身で作成して、hello_phoenix/priv/static/css/ディレクトリ下に移動します。

.form-signin
{
    max-width: 330px;
    padding: 15px;
    margin: 0 auto;
}
.form-signin .form-signin-heading, .form-signin .checkbox
{
    margin-bottom: 10px;
}
.form-signin .checkbox
{
    font-weight: normal;
}
.form-signin .form-control
{
    position: relative;
    font-size: 16px;
    height: auto;
    padding: 10px;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.form-signin .form-control:focus
{
    z-index: 2;
}
.form-signin input[type="text"]
{
    margin-bottom: -1px;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}
.form-signin input[type="password"]
{
    margin-bottom: 10px;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}
.account-wall
{
    margin-top: 20px;
    padding: 40px 0px 20px 0px;
    background-color: #f7f7f7;
    -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.login-title
{
    color: #555;
    font-size: 18px;
    font-weight: 400;
    display: block;
}
.profile-img
{
    width: 96px;
    height: 96px;
    margin: 0 auto 10px;
    display: block;
    -moz-border-radius: 50%;
    -webkit-border-radius: 50%;
    border-radius: 50%;
}
.need-help
{
    margin-top: 10px;
}
.new-account
{
    display: block;
    margin-top: 10px;
}

4) hello_phoenix/web/router.exファイルに/loginを部分を追加して、下のようになります。注意して欲しいのはpostを使っています。

 defmodule HelloPhoenix.Router do
   use HelloPhoenix.Web, :router

   pipeline :browser do
     plug :accepts, ["html"]
     plug :fetch_session
     plug :fetch_flash
     plug :protect_from_forgery
   end

   pipeline :api do
     plug :accepts, ["json"]
   end

   scope "/", HelloPhoenix do
     pipe_through :browser # Use the default browser stack

     get "/", PageController, :index
     post "/login", PageController, :login
     resources "/users", UserController
   end
 end

5) これでアプリを起動して、ログインページが表示されるようになっているはずです。

14:28:36 [N1210A001 => ~/Playground/elixir/hello_phoenix]
$ mix phoenix.server

スクリーンショット 2015-06-16 14.29.17.png

  • これからログイン処理に入ります。hello_phoenix/web/controllers/page_controller.exファイルを以下のように修正します。
 defmodule HelloPhoenix.PageController do
   use HelloPhoenix.Web, :controller

   # `query = from u in User,`部分
   # の`User`が使える為にaliasしている

   alias HelloPhoenix.User

   # `redirect conn, to: Helpers.user_path(conn, :index)`部分
   # の`Helpers.user_path`が使えるためにaliasをしている

   alias HelloPhoenix.Router.Helpers

   plug :action

   def index(conn, _params) do
     render conn, "index.html"
   end

   def login(conn, %{"user" => %{"email" => email, "password" => password}}) do
     query = from u in User,
               where: u.email == ^email,
               where: u.password == ^password,
               select: u.id
     result = HelloPhoenix.Repo.all(query)
     # ユーザーが存在すればユーザー一覧ページにリダイレクトされます
     case length(result) > 0 do
       true ->
         redirect conn, to: Helpers.user_path(conn, :index)
       false ->
         text conn, "ログイン失敗"
     end
   end
 end

これで一番簡単なログインページができました。また実装していない部分は

1) パスワードの暗号化
2) ログインしていないユーザーはユーザー一覧を見られないように

どなたか上のような機能実装したら、教えてください。特に2)番目です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40