## 루비 온 레일즈에서 devise gem 없이 로그인 기능 구현하기 3 (How to build authentication system without devise gem in Ruby on Rails)
[지난 포스트](https://ghkdgh2365.blogspot.com/2020/07/devise-gem-2-how-to-build.html) 에서 쿠키(Cookie)를 이용한 로그인, 로그아웃을 구현했습니다. 이번에는 세션을 이용한 로그인, 로그아웃을 구현하겠습니다. 차이점은 다음과 같습니다. 쿠키를 이용했을 때는 사용자 브라우저에 아이디, 비밀번호를 저장하고 이를 서버에 보내서 검증했다면, 세션을 이용할 때에는 서버에서 검증에 필요한 정보를 저장한 뒤 그 정보를 사용자 브라우저에게 보내주고, 다시 그 정보를 서버에 보내 검증한다는 점이 차이점입니다. 아래 구현 방법을 보시면서 차이점을 확인해보면 이해가 더 잘 될 것입니다.
#### 3. 세션을 이용한 로그인
세션을 이용한 로그인, 로그아웃 구현을 위해 새로운 컨트롤러를 생성합니다. `rails g controller session` 으로 생성하거나, 직접 디렉토리(`controllers`)에 파일(`sessions_controller.rb`)을 만들어도 됩니다. 만들고 나면 `controller/sessions_controller.rb` 파일이 생성되고 아래와 같은 코드가 보일 것입니다.
```
class SessionsController < ApplicationController
end
```
그 다음 Cookie를 이용한 로그인 때와 같이 `new`, `create`, `destroy` 액션을 만들어 로그인 화면을 보여주고(`new`), 아이디와 비밀번호를 입력 후 로그인을 시도하고(`create`), 로그아웃(`destroy`)을 할 수 있도록 만들 것입니다. 먼저 `new` 부터 진행하겠습니다. `new` 액션을 정의해줍니다.
```
class SessionsController < ApplicationController
def new
end
end
```
그 다음, `routes.rb` 에 가서 아래와 같이 정의합니다.
```
get 'sessions/sign_in', to: 'sessions#new'
```
그리고 `views/sessions/new.html.erb` 파일을 생성한 뒤 아래와 같이 입력합니다. 그 다음 `localhost:3000/sessions/sign_in`에 들어가 확인해봅니다.
```
세션 로그인
<%= form_with(url: "/sessions/sign_in") do |f|%>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "로그인" %>
<% end %>
```
확인이 되었으면 `home/index.html.erb` 에 아래와 같이 추가합니다.
```
Hello World !
<% if current_user.present? %>
<%= link_to "로그아웃", cookie_sign_out_path, method: :delete %>
<% else %>
<%= link_to "로그인", cookie_new_path %>
<%= link_to "세션 로그인", sessions_sign_in_path %>
<% end %>
<%= link_to "회원가입", new_user_path %>
```
이제 로그인 화면이 생겼으니 로그인할 수 있도록 `controllers/sessions_controller.rb` 에 가서 아래와 같이 입력합니다.
```
def create
if params[:email].present? && params[:password].present?
user = User.find_by(email: params[:email])
if user
if user.authenticate(params[:password])
session[:user_id] = user.id
flash[:notice] = "세션 로그인 성공"
redirect_to '/home/index'
return
else
flash[:notice] = "잘못된 비밀번호 입니다. 다시 확인해주세요."
end
else
flash[:notice] = "잘못된 이메일입니다. 다시 확인해주세요."
end
else
flash[:notice] = "이메일, 비밀번호 모두 입력해주세요"
end
redirect_to sessions_sign_in_path
end
```
그 다음, `routes.rb` 에 가서 아래와 같이 입력하면 로그인 기능이 완성되었습니다.
```
post 'sessions/sign_in', to: 'sessions#create'
```
이를 확인하기 위해서 `controllers/application_controller.rb` 에 가서 아래와 같이 입력합니다.
```
class ApplicationController < ActionController::Base
helper_method :current_user
def current_user
@current_user ||= User.find_by(email: cookies[:email], password_digest: cookies[:password]) || User.find_by(id: session[:user_id])
end
end
```
그 다음, `views/home/index` 에 가서 아래와 같이 수정합니다. 이로써 로그인이 된 것을 확인할 수 있습니다. 현재는 `sessions_sign_out_path`가 없으므로 세션 로그아웃 버튼을 누르면 오류가 날 것입니다. 이제 세션 로그아웃 기능을 만들겠습니다.
```
Hello World !
<% if current_user.present? %>
<%= link_to "로그아웃", cookie_sign_out_path, method: :delete %>
<%= link_to "세션 로그아웃", sessions_sign_out_path, method: :delete %>
<% else %>
<%= link_to "로그인", cookie_new_path %>
<%= link_to "세션 로그인", sessions_sign_in_path %>
<% end %>
<%= link_to "회원가입", new_user_path %>
```
`controllers/sessions_controller.rb` 에 가서 아래와 같이 입력합니다.
```
def destroy
if current_user.present?
reset_session
flash[:notice] = "세션 로그아웃 성공"
redirect_to '/home/index'
end
end
```
그리고 다시 `views/home/index` 에 가서 세션 로그인을 한 뒤, 세션 로그아웃을 해보면 로그아웃이 되어있는 것을 확인할 수 있습니다.
다음은 JWT(JSON Web Token)를 이용한 로그인을 구현하겠습니다.
참고 : https://pragmaticstudio.com/tutorials/rails-session-cookies-for-api-authentication
댓글
댓글 쓰기