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