Я использую MediaWiki в качестве своего бэкэнда, и он работает на «localhost/name».
Мой файл login.js:
import React, {useState} from 'react';
import axios from 'axios';
function Login() {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
async function login() {
console.info(username, password);
let url = 'http://localhost/wikimedia/api.php';
let params = {
action: "query",
meta: "tokens",
format: "json",
type: "login"
};
// fetch login
const response = await axios.get(url + '?' + params + '&origin=*');
console.info(response);
let loginToken = response.data.query.tokens.logintoken
let cookie = response.headers['set-cookie'].join(';');
let body = {
action: 'login',
lgname: username,
lgpassword: password,
lgtoken: loginToken,
format: 'json'
}
let bodyData = new URLSearchParams(body).toString();
axios.post(url, bodyData, {
headers: {
Cookie: cookie,
}
}).then(response => {
let cookie = response.headers['set-cookie'].join(';')
console.info(response.data);
})
}
return (
<div>
<h1>Sign In</h1>
<input
type = "text"
onChange = {(e) => setUsername(e.target.value)}
placeholder = "username"
/>
<br/>
<input
type = "password"
onChange = {(e) => setPassword(e.target.value)}
placeholder = "password"
/>
<br/>
<button onClick = {login} type = "submit">Login</button>
</div>
)
};
export default Login;
Однако я получаю следующий ответ, который не соответствует ожидаемому согласно документации:
{
"data": "a-bunch-of-irrelevant-stuff",
"status": 200,
"statusText": "OK",
"headers": {
"cache-control": "private, must-revalidate, max-age=0",
"content-language": "en",
"content-type": "text/html; charset=utf-8",
"expires": "Thu, 01 Jan 1970 00:00:00 GMT",
"mediawiki-login-suppressed": "true"
},
"config": {
"transitional": {
"silentJSONParsing": true,
"forcedJSONParsing": true,
"clarifyTimeoutError": false
},
"transformRequest": [
null
],
"transformResponse": [
null
],
"timeout": 0,
"xsrfCookieName": "XSRF-TOKEN",
"xsrfHeaderName": "X-XSRF-TOKEN",
"maxContentLength": -1,
"maxBodyLength": -1,
"env": {},
"headers": {
"Accept": "application/json, text/plain, */*"
},
"method": "get",
"url": "http://localhost/wikimedia/api.php?[object Object]&origin=*"
},
"request": {}
}
До сих пор я вывожу в консоль ответ первого токена fetch ->, но я не получаю ответа, как ожидалось:
{
"batchcomplete": "",
"query": {
"tokens": {
"logintoken": "9ed1499d99c0c34c73faa07157b3b6075b427365+\\"
}
}
}
Я бы просто использовал состояния для обработки передачи данных имени пользователя и пароля. Я добавил рабочий код ниже. Функцию doSomethingWithCreds можно использовать для передачи ваших данных по какому-то маршруту и в конечном итоге привязать к нему токен.
Я настоятельно рекомендую вам уделить время изучению состояний и некоторых общих ловушек, таких как useRef и useEffect. Это значительно упростит разработку и понимание некоторых ключевых тем в React.
Если у вас есть какие-либо вопросы, не стесняйтесь комментировать, и я сделаю все возможное, чтобы ответить.
Справочник государственных документов
import {useEffect, useState} from 'react'
import './App.css';
function App() {
const[pass,setPass] = useState()
const[user,setUser] = useState()
const handlePassChange = event =>{//Updates pass every time a new char is entered instead of on submit
setPass(event.target.value)
}
const handleUserChange = event =>{
setUser(event.target.value)
}
const doSomethingWithCreds = () =>{
console.info('password: ' + pass)
console.info('user' + user)
}
return (
<div className = "form">
<h1>Login Page</h1>
<form>
<div className = "input-container">
<label>Username </label>
<input onChange = {handleUserChange} type = "text" name = "uname" required />
</div>
<div className = "input-container">
<label>Password </label>
<input onChange = {handlePassChange} type = "password" name = "pass" required />
</div>
<div className = "button-container">
<input onClick = {doSomethingWithCreds} type = "submit" value = "Login" />
</div>
</form>
</div>
);
}
export default App;
Какой-то большой вопрос, почти такой же большой, как «создайте мое приложение для меня». Проверьте https://stackoverflow.com/help/how-to-ask
Но на высоком уровне вы хотите связать входные значения с состоянием реакции. Ссылка на документацию, которую вы разместили, описывает, как это сделать. Может быть, сначала попробуйте console.info значения состояния в ответ на изменения ввода, чтобы убедиться, что вы правильно подключили входы.
Когда у вас есть входные значения, доступные в состоянии, вы, вероятно, захотите вызвать метод getToken, используя имя пользователя и пароль. Документация реагирования на события описывает, как действовать в ответ на такие события, как нажатие кнопки или отправка формы. https://reactjs.org/docs/handling-events.html
Я предполагаю, что после вызова getToken вы захотите войти в систему, используя полученный токен. Поэтому вызовите этот метод, используя имя пользователя, пароль и токен.
Вам, вероятно, потребуется базовое понимание обещаний javascript, чтобы понять, как упорядочивать вызовы, т.е. только звонить в систему ПОСЛЕ получения ответа от getToken
https://web.dev/promises/https://javascript.info/promise-basicshttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Итак, 3 основных шага:
Есть ли более конкретный аспект, с которым вам нужна помощь?
Вы получаете ошибку CORS. См. https://www.mediawiki.org/wiki/API:Cross-site_requests о том, как делать запросы CORS к MediaWiki API.
Я проверял эту страницу, но чтобы сделать аутентифицированный запрос, он говорит: «Установите это для исходного домена». Мое приложение React работает здесь «localhost: 3000». Разве не должно быть origin: 'http://localhost:3000'
? Я очень потерян!
MediaWiki нужен список разрешенных доменов (представьте, если бы любой случайный веб-сайт, который вы посещаете, мог бы отправлять запросы от вашего имени в вашу вики, это было бы довольно плохо). localhost не является настоящим доменом, поэтому я не уверен, что вы можете использовать его таким образом. Также некоторые браузеры просто отказываются от CORS от localost: stackoverflow.com/questions/10883211/…
В зависимости от того, чего вы пытаетесь достичь, лучшим вариантом может быть установка расширения OAuth и отправка вашим скриптом ключа API (токена носителя OAuth 2) с запросами вместо входа в систему. Или используйте бота пароль. Хотя вам, вероятно, все равно придется иметь дело с проблемой CORS в какой-то момент.
Что касается CORS, вы можете либо использовать реальный домен (возможно, с помощью какого-либо инструмента, такого как ngrok ), либо добавить его в настройку вашей вики $wgCrossSiteAJAXdomains; или вы можете использовать OAuth и написать крошечное бэкэнд-приложение для проксирования ваших запросов (которые ваш интерфейс затем будет отправлять на локальный хост) в вики.
Спасибо! Я смог найти решение позже, к счастью! Как вы сказали, мне пришлось настроить параметр источника, а также значение файла cookie.
Я загрузил свой вопрос с пробной версией, но теперь я застрял в другом месте. Я не получаю ответа, которого ожидал.