我一直在检查代码,我的操作如下:
- 清除所有的cookies
- 发起一个空的登录请求
- 捕获PHPSessID cookie
- 使用该PHPSessID发起登录请求
- 此后,随后的获取请求将自动带有一个有效的已登录用户的PHPSessID cookie,因此我们可以使用简单的获取请求来使用该网站
这里是一些代码,但重要的是你需要先进行一个空的登录请求,捕获PHPSessid并使用该PHPSessid发起真正的登录请求。
这将是主要的函数:
import Cookie from 'react-native-cookie';
function login(user, pass){
Cookie.clear();
const makeLoginRequest = (sessid) =>
makeLoginRequestForUserAndPass(user,pass,sessid);
return makeInitialRequest()
.then(getSessionIDFromResponse)
.then(makeLoginRequest)
.then(checkIfLoggedAndGetSessionID);
}
最初的请求是对登录脚本的请求。请注意,我使用了GET方法,因为它适用于我的网站,也许需要一个空的POST请求:
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);
}
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}`,
};
const options = { method: 'POST',
headers: headers,
mode: 'cors',
cache: 'default',
agent: proxy,
body: data,
redirect: 'manual'
};
return new Request(LOGIN_URL, options);
}
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;
}
希望这对你有用。