16. Session을 통한 로그인 구현

2020. 6. 30. 16:16Rails 5 on aws c9

16. Session을 통한 로그인 구현

로그인 기능을 구현해보자

세션이라는 기능을 사용해야한다

사용자와 서버간의 반영구적인 연결을 만든다

액션단위는 각각 독립적으로 어떤 정보를 전달해줄 방법이 없다

세션을 활용하게되면 로그인한 사용자정보를 계속 관리할수있다

쿠키는 브라우저에 저장된 사용자의 흔적이다.

여기에 사용자의 정보를 저장하고 서버코드에서 불러다 쓸 수있다.

세션을 관리할 컨트롤러를 만들어보자

로그인은 create, 로그아웃은 destroy에서 할거라 new 만 추가하면 된다.

ubuntu:~/environment/hello_world (master) $ rails g controller Sessions new                                                   

Running via Spring preloader in process 9789
      create  app/controllers/sessions_controller.rb
       route  get 'sessions/new'
      invoke  erb
      create    app/views/sessions
      create    app/views/sessions/new.html.erb
      invoke  test_unit
      create    test/controllers/sessions_controller_test.rb
      invoke  helper
      create    app/helpers/sessions_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/sessions.coffee
      invoke    scss
      create      app/assets/stylesheets/sessions.scss

이렇게 보면 세션 뉴 액션에 대한 주소밖에 없다.

ubuntu:~/environment/hello_world (master) $ rake routes

      Prefix Verb URI Pattern             Controller#Action
sessions_new GET  /sessions/new(.:format) sessions#new
    contacts GET  /contacts(.:format)     contacts#index
             POST /contacts(.:format)     contacts#create
 new_contact GET  /contacts/new(.:format) contacts#new
       users POST /users(.:format)        users#create
    new_user GET  /users/new(.:format)    users#new
             GET  /                       home#hello_world
       index GET  /index(.:format)        home#index
     contact GET  /contact(.:format)      home#contact

먼저 routes.rb 에 가서

Rails.application.routes.draw do

  #지금은 쓰고싶은 액션이 3개 뿐이다.
  resources :contacts, only: [:index, :create, :new] 
  #리소스 이용해서 유저라우트 규칙 생성
  resources :users, only: [:new, :create]
  resources :sessions, only: [:new, :create, :destroy]

    get '/' => 'home#hello_world' 
    get '/index' => 'home#index'
    get '/contact' => 'home#contact'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

그다음에 rake routes 하면 생겨난걸 볼 수 있다.

ubuntu:~/environment/hello_world (master) $ rake routes
     Prefix Verb   URI Pattern             Controller#Action
   contacts GET    /contacts(.:format)     contacts#index
            POST   /contacts(.:format)     contacts#create
new_contact GET    /contacts/new(.:format) contacts#new
      users POST   /users(.:format)        users#create
   new_user GET    /users/new(.:format)    users#new
   sessions POST   /sessions(.:format)     sessions#create
new_session GET    /sessions/new(.:format) sessions#new
    session DELETE /sessions/:id(.:format) sessions#destroy
            GET    /                       home#hello_world
      index GET    /index(.:format)        home#index
    contact GET    /contact(.:format)      home#contact

이제 로그인폼을 작성하자

<h1>Sign in</h1>
<%= form_tag sessions_path do %>
    Email :
    <input type="email" name="email"><br>
    Password :
    <input type="password" name="password"><br>
    <input type="submit" value="Sign in"><br>
<% end %>

작성하고 주소로 들어가면

 

sign in 하면 에러가 뜬다

sessions controller 에서 create 엑션을 만들어야 한다.

class SessionsController < ApplicationController
  def new
  end

  def create
    #유저를 이메일로 찾아서 있으면 user가 ture취급
    #그리고 비밀번호를 해싱해서 일치하나 확인 
    #둘다 참이면 로그인
    user = User.find_by(email: params[:email])
    if user && user.authenticate(params[:password])
      #세션이라는 키워드에 해시처럼 관리
      #다음부터 세션하고 유저아이디로 불러오면, 로그인한 사용자의 아이디를 불러올 수 있게 된다. 
      #어느 액션에서나 볼 수 있다.
      #세션에 user_id가 있으면 전부 로그인된 사용자로 처리
      session[:user_id] = user.id
      redirect_to '/'
    else
      #sessions/new.html.erb에서 맨 위에 소스코드 추가필요 <%= flash[:alert]%>
      flash[:alert] = 'Invalid email/password combination'
      #sessions/new의 prefix가 new_session 이므로
      redirect_to new_session_path
    end
  end
end

또, new.html.erb에 코드를 추가해줘야한다

<h1>Sign in</h1>
***<%= flash[:alert]%>***
<%= form_tag sessions_path do %>
    Email :
    <input type="email" name="email"><br>
    Password :
    <input type="password" name="password"><br>
    <input type="submit" value="Sign in"><br>
<% end %>

여기까지 하고 틀린조합으로 로그인 시도하면, 이렇게 뜬다.

제대로 로그인하면

 

첫페이지로 연결된다.

이제는 로그인되었으면 메뉴명의 Sign up 옆에 유저이름이 나오게 해보자

임시로 하는것이고, 실제로 코드를 짤 땐 뷰에서 모델을 호출하는 코드는 안쓰는게 좋다.

<!DOCTYPE html>
<html>
  <head>
    <title>HelloWorld</title>
    <%= csrf_meta_tags %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <div id="global-header">
      <div class="container">
        <div class="logo">My Profile</div>
        <ul class="menu">
          <a href="/">
            <li class="item">Hello World</li>
          </a>
          <!--link_to 헬퍼를 이용 해보자-->
          <!--<a href="/contacts/new">-->
          <%= link_to new_contact_path do %>
            <li class="item">Contact</li>
          <!--</a>-->
          <% end %>
          <%= link_to new_user_path do %>
            <li class="item">Sign up</li>
          <% end %>
          ***<% if session[:user_id] %>
            <li class="item"><%= User.find_by(id: session[:user_id]).name %></li>
          <% end %>***
        </ul>
      </div>
    </div>

    <%= yield %>
  </body>
</html>

잘 뜨는걸 볼 수 있다.