1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React & Django でログイン機能実装

Last updated at Posted at 2024-10-22

React でログイン画面(username, password)を作成して、Django の APIを使用してログイン機能を実装します。

流れ

React: ログイン情報をDjangoへPOST
↓
Django: Reactから受け取ったログイン情報でユーザー認証
↓
Django: 認証したユーザーのアクセストークンを作成してReactへ return
↓
React: 返されたアクセストークンをブラウザに保存
↓
以降 Djangoのrequest.userでログインしているユーザーの情報が取得可
# 事前にインストールと設定
pip install djangorestframework-simplejwt

# Djagngo.settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

Reactコード

Login.tsx
import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';

const Login = () => {
    const [username, setUsername] = useState('');
    const [password, setPassword] = useState('');
    const navigate = useNavigate();

    interface LoginResponse {
        access: string;
        refresh: string;
    }

    const handleSubmit = async (e: React.SyntheticEvent) => {
        e.preventDefault();
        try {
            const response = await axios.post<LoginResponse>('http://localhost:8000/accounts/api/login/', {
                username,
                password,
            });
            const { access, refresh } = response.data;
            localStorage.setItem('access_token', access);
            localStorage.setItem('refresh_token', refresh);
            navigate('/');
        } catch (error) {
            console.error('Login failed', error);
        }
    };

    return (
        <form onSubmit={handleSubmit}>
            <input 
                type="text" 
                placeholder="Username" 
                value={username} 
                onChange={(e) => setUsername(e.target.value)} 
            />
            <input 
                type="password" 
                placeholder="Password" 
                value={password} 
                onChange={(e) => setPassword(e.target.value)} 
            />
            <button type="submit">Login</button>
        </form>
    );
};

export default Login;

詳細

// Djangoの指定したURLに入力したログイン情報を送信
const response = await axios.post<LoginResponse>('http://localhost:8000/accounts/api/login/', {
                username,
                password,
            });
            
// Django から返された response から アクセストークン, と リフレッシュトークンを取得
const { access, refresh } = response.data;

// ブラウザに取得したアクセストークンを保存
localStorage.setItem('access_token', access);
localStorage.setItem('refresh_token', refresh);

Django コード

urls.py
# project.urls.py--------------------------------
path('accounts/', include('accounts.urls')),

# accounts.urls.py---------------------------
from django.urls import path
from . import views

app_name = "accounts"
urlpatterns = [
    path('api/login/', views.login_api_view, name='api_login'),
]
views.py
@api_view(['POST'])
def login_api_view(request):
    username = request.data.get('username')
    password = request.data.get('password')
    user = authenticate(request, username=username, password=password)
    if user is not None:
        refresh = RefreshToken.for_user(user)
        return Response({
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        }, status=status.HTTP_200_OK)
    else:
        return Response({'message': 'Invalid credentials'}, status=status.HTTP_400_BAD_REQUEST)

詳細

# React から送られてきた username, password でユーザー認証
user = authenticate(request, username=username, password=password)

# 認証されたユーザーに対してアクセストークンを発行し React へ返す
refresh = RefreshToken.for_user(user)
return Response({
    'refresh': str(refresh),
    'access': str(refresh.access_token),
}, status=status.HTTP_200_OK)

認証済みユーザー取得

views.py
@api_view(['GET'])
@permission_classes([IsAuthenticated]) # 認証されたユーザーのみ
def channel_view_set(request):
    user = User.objects.filter(user=request.user)
    serializer = UserInfoSerializer(user, many=True)
    
    if user.exists():
        return Response(serializer.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

Simple JWT を利用することで、リクエストに認証済みユーザーの情報を含めることが可能になり、ユーザーがログイン済みかどうかを簡単に判断できるようになりました。これにより、認証が必要な処理をセキュアかつスムーズに実装できる点が非常に便利だと思います。

1
1
0

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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?