Flutter & Django : Как аутентифицировать пользователя по JWT?
Я разрабатываю страницы аутентификации для своего приложения, используя Flutter для мобильного фронтенда и Django для бэкенда.
Функциональность входа в систему работает отлично, но я столкнулся с проблемой при выходе из системы. Когда я пытаюсь выйти из системы, возвращается ошибка «forbidden», указывающая на то, что пользователь не прошел аутентификацию.
Я подозреваю, что проблема может быть связана с тем, как я устанавливаю jwt в заголовках HTTP-запросов во Flutter.
Может кто-нибудь взглянуть и помочь мне устранить неполадки?
Спасибо!
Flutter
class AuthService {
// Base URL for the user endpoints
final String _loginUrl = '$BASE_URL/users/login';
final String _isLoggedInUrl = '$BASE_URL/users/is_logged_in';
final String _logoutUrl = '$BASE_URL/users/logout';
Future<String?> login(String email, String password) async {
final response = await http.post(
Uri.parse(_loginUrl),
headers: {'Content-Type': 'application/json'},
body: json.encode({'email': email, 'password': password}),
);
if (response.statusCode == 200) {
// Store the JWT token in shared preferences
final prefs = await SharedPreferences.getInstance();
final token = json.decode(response.body)['jwt'];
await prefs.setString('jwt', token);
return token;
} else {
throw Exception('Failed to login');
}
}
Future<bool> isLoggedIn() async {
print("In isLoggedIn");
final prefs = await SharedPreferences.getInstance();
final token = prefs.getString('jwt');
// If token is null, the user is not logged in
if (token == null) {
return false;
}
final response = await http.post(
Uri.parse(_isLoggedInUrl),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $token',
},
);
// Check response status and print for debugging
if (response.statusCode == 200) {
final sth = json.decode(response.body);
print(sth);
return true; // User is logged in if the response is successful
} else {
return false; // User is not logged in if the response fails
}
}
Future<void> logout() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('jwt'); // Remove JWT from shared preferences
// Optionally call the logout API
final token = prefs.getString('jwt'); // Get the token for logout request
await http.post(
Uri.parse(_logoutUrl),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token', // Include token if required
},
);
}
}
Django
Сообщение об ошибке
User logged in successfully and JWT token set in cookie
[28/Oct/2024 13:48:24] "POST /users/login HTTP/1.1" 200 166
Forbidden: /users/logout
[28/Oct/2024 13:48:39] "POST /users/logout HTTP/1.1" 403 29
В операции выхода из системы (на стороне Flutter) вы удаляете JWT прямо перед тем, как пытаетесь прочитать его в запросе к /logout
.
await prefs.remove('jwt'); // <-- Delete JWT
// Optionally call the logout API
final token = prefs.getString('jwt'); // <-- Attempt to retrieve JWT
Поскольку JWT был удален, token
становится null
. Что, в свою очередь, означает, что JWT-заголовок запроса, идущего к Django, не содержит действительного токена носителя, и это вызывает HTTP 403
.
Проверить можно, закомментировав строку, удаляющую JWT на стороне клиента, или записав значение заголовка JWT в запросе, который заканчивается на /logout
.