mercusuar dan dalang, audit halaman memerlukan otentikasi

Saya memiliki aplikasi web SPA, yang dibuat oleh vue. halaman tersebut dilindungi oleh halaman login (sebenarnya router vue),

setelah login, token disimpan di sessionStorage, lalu lompat ke halaman beranda (router vue lain.)

Saya ingin menggunakan mercusuar untuk mengaudit halaman beranda, tetapi tidak dapat login dengan dalang. kode saya:

'use strict';

const puppeteer = require('puppeteer-core')
const lighthouse = require('lighthouse')
const http = require('http')
const PORT = 8041;

const opts = {
    hostname: 'x.x.x.x',
    port: 9876,
    path: '/lighthouse/scores',
    method: 'POST',
    timeout: 5000,
    headers : {
        'Accept' : 'application/json',
        'Content-Type' : 'application/json'
    }
}

var session;
// 登录
async function login(broswer, origin){
    const loginPage =  (await broswer.pages())[0];
    await loginPage.goto(origin);
    await loginPage.waitForSelector('#pane-pwd > form > div:nth-child(1) > div > div > input', {visible: true});
    const userInput =  await loginPage.$('#pane-pwd > form > div:nth-child(1) > div > div > input');
    await userInput.type('admin');
    const pswdInput =  await loginPage.$('#pane-pwd > form > div:nth-child(2) > div > div > input');
    await pswdInput.type('123456');
    const loginButton = await loginPage.$('#app > div > div.main > div.tabs > div.bt-wrap > button');
    await loginButton.click();

    await loginPage.waitForSelector('.home');

    const states = await loginPage.evaluate(() => {
        //alert(sessionStorage.getItem('default'));
        return JSON.stringify(sessionStorage);
    })
    session = JSON.parse(states);

    return session;
}

// 上传lighthouse结果
function uploadReport(scores){
    console.log('--------------------- uploading lighthouse report --------------------- ');
    const req = http.request(opts, res => {
        console.log(`Update : statusCode: ${res.statusCode}`)
        if(res.statusCode != '204'){
            console.error(res.statusMessage)
        }else{

        }
    });
    req.on('error', error => {
        console.error(error)
    });
    req.write(scores);
    req.end();
}

async function main(){
    const broswer = await puppeteer.launch({
        args : [`--remote-debugging-port=${PORT}`],
        headless : false,
        defaultViewport : null,
        executablePath : '/usr/bin/google-chrome-stable'
    });

    const session = await login(broswer, 'http://x.x.x.x/');

    console.log(session);

    broswer.once('targetchanged', async target => {
        console.log('------- target changed -------');
        const page  = await target.page();
        await page.waitForNavigation();
        page.evaluate((session) => {
            console.log('------- copy session state -------')
            sessionStorage.setItem('___un__solvable___secrets__', session['___un__solvable___secrets__']);
            sessionStorage.setItem('default', session['default']);
        }, session);
    });


    const result = await lighthouse('http://x.x.x.x/#/admin/home', {port: PORT, disableStorageReset : true, disableDeviceEmulation: true, emulatedFormFactor : 'desktop'})
    const scores = {
        project : 'P364',
        url : '/',
        performance : result.lhr.categories.performance.score,
        accessibility : result.lhr.categories.accessibility.score,
        bestPractice : result.lhr.categories['best-practices'].score,
        pwa : result.lhr.categories.pwa.score,
        seo : result.lhr.categories.seo.score,
    }

    console.log(scores);

    uploadReport(JSON.stringify(scores));

    //await broswer.close();

}

if(require.main === module){
    main();
}else{
    module.exports = {
        login
    };
}

Saya ingin menggunakan dalang untuk login terlebih dahulu, di tab terpisah, lalu mengekstrak token dari sessionStorage, dan pada titik tertentu ketika mercusuar mulai memuat url (tab lain), menyuntikkan token ke sessionStorage. tapi gagal dengan :execution context was destroyed, di targetchange pendengar, mohon bantuannya.

selain itu, saya ingin tahu apakah saya harus bersikeras untuk mengaudit halaman beranda, karena ini adalah vue SPA? karena sebagian besar aset sudah dimuat di halaman login.


person WestFarmer    schedule 03.04.2020    source sumber


Jawaban (2)


Saya baru-baru ini mulai mengerjakan tes kinerja. Saya memiliki kasus penggunaan yang tepat. Salah satu solusinya adalah dengan membuat perubahan pada file - mercusuar › lighthouse-core › mengumpulkan › koneksi › CriConnections › cri.js.


Di sini, dalam fungsi 'menghubungkan' di bawah kelas 'CriConnection' beri komentar pada pembuatan tab baru.

connect() {
// return this._runJsonCommand('new')
//   .then(response => this._connectToSocket(/** @type {LH.DevToolsJsonTarget} */(response)))
//   .catch(_ => {
    // Compat: headless didn't support `/json/new` before m59. (#970, crbug.com/699392)
    // If no support, we fallback and reuse an existing open tab
    
    log.warn('CriConnection', 'Cannot create new tab; reusing open tab.');
    return this._runJsonCommand('list').then(tabs => {
      if (!Array.isArray(tabs) || tabs.length === 0) {
        return Promise.reject(new Error('Cannot create new tab, and no tabs already open.'));
      }
      const firstTab = tabs[0];
      // first, we activate it to a foreground tab, then we connect
      return this._runJsonCommand(`activate/${firstTab.id}`)
          .then(() => this._connectToSocket(firstTab));
    });
  // });}

Meskipun demikian, perlu diingat, ini mungkin bukan praktik terbaik. Tapi hanya ini yang kumiliki sejauh ini. Saya secara aktif mencari solusi yang lebih baik. Akan memperbarui, jika saya menemukannya!

person Parbinder Singh    schedule 28.12.2020

Anda dapat menggunakan pengumpul khusus untuk memasukkan token ke penyimpanan sesi: `

    async function createSession(token) {
  if (sessionStorage) {
    sessionStorage.setItem("jwt_token", token);
  }
}

class SessionGatherer extends Gatherer {
  constructor() {
    super();
  }

  async beforePass(options) {
    // if (!credentials[0] == "Login page") {
    const TOKEN = await new TokenService().fetchToken();
    const driver = options.driver;
    return driver.evaluateScriptOnNewDocument(
      `(${createSession.toString()})('${TOKEN}')`
    );
  }
}

Pengumpul khusus perlu ditambahkan ke konfigurasi mercusuar:

   const lighthouse_config = {
  extends: "lighthouse:default",
  settings: {
    formFactor: "desktop",
    screenEmulation: {
      mobile: false,
      width: 1024,
      height: 768,
      deviceScaleFactor: 1,
      disabled: false,
    },
  },
  passes: [
    {
      passName: "defaultPass",
      gatherers: [`session-gatherer`],
    },
  ]}
person Parbinder Singh    schedule 21.01.2021