我一直在检查代码,我所做的如下:
- 清除所有 cookie
- 启动一个空的登录请求
- 捕获 PHPSessID cookie
- 使用该 PHPSessID 启动登录请求
- 之后,后续的提取请求将自动生成一个 PHPSessID cookie,并带有有效的登录用户,因此我们可以通过简单的提取来使用该站点
这里有一些代码,但重要的是您首先执行一个空登录请求,捕获 PHPSessid 并使用该 PHPSessid 启动真正的登录请求。
这将是主要功能:
import Cookie from 'react-native-cookie';
// I think this is used only to clear the cookies
function login(user, pass){
// clear all cookies for all domains
// We need to start withouth authorization token
Cookie.clear();
const makeLoginRequest = (sessid) =>
makeLoginRequestForUserAndPass(user,pass,sessid);
return makeInitialRequest()
.then(getSessionIDFromResponse)
.then(makeLoginRequest)
.then(checkIfLoggedAndGetSessionID);
}
初始请求是对登录脚本的请求。请注意,我使用 GET 是因为它适用于我的网站,可能需要一个空帖子:
function makeInitialRequest() {
const INIT_PATH = '/index.php?r=site/login';
const INIT_URL = site + INIT_PATH;
const request = new Request(INIT_URL, options....);
return fetch(request);
}
我们在响应中有会话 ID。我使用了一个简单的正则表达式来提取它。请注意,我们没有登录; PHP 已经创建了一个会话,这就是我们在这里所拥有的:
function getSessionIDFromResponse(response) {
return getPHPSessIdFromCookie(response.headers.get('set-cookie'));
}
function getPHPSessIdFromCookie(header) {
const regex = /PHPSESSID=(\w*)/;
const match = regex.exec(header);
return match ? match[1] : '';
}
现在是登录请求。请注意,我不能在这里停止重定向,但我不必这样做,因为我们可以稍后再使用 PHPSessid。在 POST 请求中重定向必须设置为手动:
function makeLoginRequestForUserAndPass(user, pass, sessid) {
const request = buildLoginRequest(user, pass, sessid);
return fetch(request);
}
// This is where we build the real login request
function buildLoginRequest(user, pass, sessid) {
const LOGIN_PATH = '/index.php?r=site/login';
const LOGIN_URL = site + LOGIN_PATH;
const fields = [
{name: 'LoginForm[username]', value: user},
{name: 'LoginForm[password]', value: pass},
etc...
];
const data = translateFieldsToURLEncodedData(fields);
const headers = {
'Content-type': 'application/x-www-form-urlencoded',
Cookie: `PHPSESSID=${sessid}`, // HERE is where you put the data
};
const options = { method: 'POST',
headers: headers,
mode: 'cors',
cache: 'default',
agent: proxy,
body: data,
redirect: 'manual' // VERY IMPORTANT: if you don't do it, the cookie is lost
};
return new Request(LOGIN_URL, options);
}
// Simple utility function
function translateFieldsToURLEncodedData(fields){
let pairs = fields.map( (field) => {
return encodeURIComponent(field.name) + '=' + encodeURIComponent(field.value);
});
return pairs.join('&');
}
这是最后一部分。为了查看我是否已登录,我检查了响应是否包含属于登录错误页面的文本。我也得到了PHPSessid(我认为它在登录后发生了变化,不确定,是一年前的)但我不知道我是否使用过它,我相信它会自动包含在后续请求中。我认为这部分可以简化和改进:
function checkIfLoggedAndGetSessionID(response) {
return (
checkIfLoggedOK(response)
.then(() => getSessionIDFromResponse(response))
);
}
function checkIfLoggedOK(response){
return getTextFromResponse(response)
.then(throwErrorIfNotLogedOk);
}
function getTextFromResponse(response) {
return response.text();
}
function throwErrorIfNotLogedOk(page) {
if(isErrorPage(page)) throw new Error("Login failed");
}
function isErrorPage(text) {
const ERROR_MESSAGE = 'Something that appears in login failed page of your site';
let n = text.search(ERROR_MESSAGE);
return n !== -1;
}
希望这能有用。