Как я могу отправить запрос POST с токеном CSRF и телом JSON в конечную точку Django?Android

Форум для тех, кто программирует под Android
Ответить
Гость
 Как я могу отправить запрос POST с токеном CSRF и телом JSON в конечную точку Django?

Сообщение Гость »

Я разрабатываю приложение Android Studio, которое взаимодействует с сервером, на котором работает Django. Я занимаюсь процессом входа в систему на телефоне, однако сервер всегда возвращает 403 Forbidden на мои POST-запросы, даже с установленным заголовком X-CSRFToken.
В приложении на начальном экране выполняется запрос GET к конечной точке /phone/login, чтобы получить токен CSRF из заголовков (я использую декоратор @ensure_csrf_cookie) в представлении Django, чтобы убедиться, что оно отправлено). На основании ответа приложение переходит к экрану входа в систему, где пользователь может ввести свои данные. Затем этот экран отправляет POST-запрос к конечной точке /phone/login с токеном, установленным в заголовках, и подробностями в виде JSON в теле (преобразованными gson). Затем сервер получает это и обрабатывает (не реализовано).
Я вижу в журналах, что запрос POST отправляется с заголовком и правильным токеном csrf (то есть таким же, как я получил от сервера). Несмотря на это, сервер всегда отвечает 403 Forbidden.
Чтобы убедиться, что проблема не связана с именем заголовка, я явно установил для CSRF_HEADER_NAME значение по умолчанию в моем файле настроек Django. Я также попытался отправить пустую строку в теле и получить токен csrf с помощью get_token(request), который я включил в объект LoginRequestBody, как если бы он был включен в html-форму, к тому же результату. Страница входа в браузере работает нормально, это просто запросы от приложения. Очевидно, я мог бы использовать @crsf_exempt для представления, но, поскольку оно по-прежнему доступно из браузера, не будет ли это проблемой безопасности? Любая помощь приветствуется.
ViewModel.kt:
fun getLogin() {
viewModelScope.launch {
try {
val response = CheckInApi.retrofitService.getLoggedIn()
val body = response.body() ?: LoginResponse()
if (response.code() == 200 ) {
if (body.result == "LOGGED IN") {
_uiState.update { currentState -> currentState.copy(result = AuthenticationState.SUCCESS)}
}
else if (body.result == "NOT LOGGED IN") {
val cookies = response.headers().get("Set-Cookie")
val csrfCookieHeader = cookies?.substring(10,42) ?: "No cookie"
_uiState.update { currentState -> currentState.copy(result = AuthenticationState.LOGIN_REQUIRED,csrfCookieHeader = csrfCookieHeader)}
}
}
}
catch (e: IOException) {
Log.d(TAG, e.toString())
}
}
}

fun postLogin() {
viewModelScope.launch {
val loginRequestBody = LoginRequestBody(_uiState.value.username, _uiState.value.password)
try {
val result = CheckInApi.retrofitService.requestLogin(
uiState.value.csrfCookieHeader,
loginRequestBody)
}
catch (e: IOException) {
Log.d(TAG, e.toString())
}
}
}

CheckInApiService.kt:
private val retrofit = Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(BASE_URL)
.build()

interface CheckInApiService {

@POST("phone/login/")
suspend fun requestLogin(@Header("X-CSRFToken") token : String, @Body loginBody : LoginRequestBody): Response

@GET("phone/login/")
suspend fun getLoggedIn(): Response
}

object CheckInApi {
val retrofitService : CheckInApiService by lazy {
retrofit.create(CheckInApiService::class.java)
}
}

views.py:
@ensure_csrf_cookie
def login(request):

if request.method not in ["GET", "POST"]:
return HttpResponseNotAllowed(["GET", "POST"])

if request.user.is_authenticated:
return HttpResponse("LOGGED IN")

if request.method == "GET":
response = {
"result" : "NOT LOGGED IN"
}
return JsonResponse(response)

else:
# Log user in
pass


Подробнее: https://stackoverflow.com/questions/799 ... jango-endp
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»