0

我们被来自我们自己的客户端(已知 IP)的大量请求击中了“/assets/workers/null”端点。

我们可能会在 2 分钟的窗口内看到来自 25 个已知 IP 地址的 6000 个请求,几个小时后会看到少数对该端点的请求。

这看起来与我们的浏览器推送事件通知服务工作者有关,它托管为“/assets/workers/notification.service.worker.js”,但我看不到任何看起来会解析为“null”的东西”。

我没有编写原始代码,并且在这一点上与浏览器服务人员合作的机会有限,我正在尝试确定是否有任何东西可以解释“/assets/workers/null”的奇怪流量。任何帮助是极大的赞赏。

这是服务工作者的代码:

// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ @ ║ Service worker responsible to manage browser push notifications          ║
// ╠═══╬══════════════════════════════════════════════════════════════════════════╣
// ║ ! ║ Change this module structure can compromise the functionality            ║
// ╠═══╩══════════════════════════════════════════════════════════════════════════╣
// ║ This worker depends on the SystemUI object to be initialized, so the         ║
// ║ worker should be register and initialized after the application is loaded    ║
// ╚══════════════════════════════════════════════════════════════════════════════╝
'use strict';
// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ § ║ Event listener for notifications received by the service worker          ║
// ╚═══╩══════════════════════════════════════════════════════════════════════════╝
self.addEventListener('push', function (event) { event.waitUntil(ParseReceivedEvent(event)); });
async function ParseReceivedEvent(event) {
    try {

        // => ~/assets/workers/notification.service.worker.js?m=1&c=APP.Configuration.Web&v=0.1.8
        const moduleId = new URL(event.currentTarget.location.href).searchParams.get('m');

        // => { PushNotificationMessage } from '../push.notification.model.ts'
        const data = event.data.json(); 
        
        if (data.VisualMessage != undefined) {
            if (data.Module == moduleId || data.Module == undefined || data.Module == 0) {
                // If the client is not focused, send the message to the desktop/mobile
                if (!await isClientFocused()) {
                    const title = data.VisualMessage.Title;
                    const options = BuildNotificationMessage(data);
                    await self.registration.showNotification(title, options);

                    // We mark the message as silent, since we already displayed the notification
                    data.Silent = true;
                }
            }
        }

        await SendClientsMessage('message', null, data);
        return SendClientsMessage('log', '[Service Worker] Push Received.', data);
    }
    catch (ex) { console.error('[Service Worker] ParseReceivedEvent Error', ex); }
}
// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ § ║ Event listener for clicks on the desktop/mobile notification pop-up      ║
// ╚═══╩══════════════════════════════════════════════════════════════════════════╝
self.addEventListener('notificationclick', function (event) { event.waitUntil(ParseNotificationClick(event)); });
async function ParseNotificationClick(event) {
    try {
        await event.notification.close();
        if (event.notification.data != undefined && event.notification.data.Url != undefined && event.action == 'open') {

            const data = event.notification.data;
            const urlToOpen = new URL(data.Url, self.location.origin).href;

            const windowClients = await clients.matchAll({ type: 'window', includeUncontrolled: true });
            let matchingClient = windowClients.find(function (item) { return item.url === urlToOpen; });

            if (matchingClient) {
                // There is already a client with this URL
                await matchingClient.focus();
            }
            else {
                let urlObject = new URL(urlToOpen);
                let matchingClientHost = await findClientHost(urlObject.host);
                // There is a client open with the same web module
                if (matchingClientHost) {
                    await SendClientsMessage('redirect', urlObject.pathname);
                }
                // Check if this URL can be docked
                else if (event.notification.data.Dock && event.notification.data.RecordId != undefined) {
                    let matchingClientDomain = await findClientHost(urlObject.hostname, true);
                    if (matchingClientDomain) {
                        SendClientMessage(matchingClientDomain, 'dock', event.notification.data.RecordId, event.notification.data);
                    }
                    // There is not client with the web module, so open another tab
                    else { await clients.openWindow(urlToOpen); }
                }
                // There is not client with the web module, so open another tab
                else { await clients.openWindow(urlToOpen); }
            }
        }

    }
    catch (ex) { console.error('[ServiceWorker] Error parsing notification click', ex); }

    return SendClientsMessage('log', `[Service Worker] Notification click Received (Action)="${event.action || 'None'}"`, event.notification.data);
}
// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ § ║ Send a message to all listening clients with the specified data          ║
// ╚═══╩══════════════════════════════════════════════════════════════════════════╝
async function SendClientsMessage(type, message, value) {
    return clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (windowClients) {
        windowClients.forEach(function (windowClient) {
            windowClient.postMessage({ type: type, message: message, value: value });
        });
    });
}
function SendClientMessage(client, type, message, value) {
    client.postMessage({ type: type, message: message, value: value });
}
// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ § ║ Check if tab of this event is currently focused                          ║
// ╚═══╩══════════════════════════════════════════════════════════════════════════╝
async function isClientFocused() {
    return clients.matchAll({ type: 'window', frameType: 'top-level', includeUncontrolled: true })
        .then((windowClients) => {
            let clientIsFocused = false;

            for (let i = 0; i < windowClients.length; i++) {
                const windowClient = windowClients[i];
                if (windowClient.focused) {
                    clientIsFocused = true;
                    break;
                }
            }

            return clientIsFocused;
        });
}
// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ § ║ Finds a client tag with the same URL host as the defined parameter       ║
// ╚═══╩══════════════════════════════════════════════════════════════════════════╝
async function findClientHost(host, useHostName) {
    return clients.matchAll({ type: 'window', frameType: 'top-level', includeUncontrolled: true })
        .then((windowClients) => {
            let clientFound = undefined;

            for (let i = 0; i < windowClients.length; i++) {
                const windowClient = windowClients[i];

                var found = (!useHostName ?
                    new URL(windowClient.url).host :
                    new URL(windowClient.url).hostname) == host;

                if (found) { clientFound = windowClient; break; }
            }

            return clientFound;
        });
}
// ╔═══╦══════════════════════════════════════════════════════════════════════════╗
// ║ § ║ Build the notification message to broadcast                              ║
// ╚═══╩══════════════════════════════════════════════════════════════════════════╝
function BuildNotificationMessage(data) {
    const options = data.VisualMessage;
    var res = {
        data: options,
        tag: options.Group,
        icon: options.Icon,
        badge: options.Badge,
        image: options.Image,
        body: options.Message,
        message: options.Message,
        requireInteraction: options.RequireInteraction
    };
    if (options.Actions && options.Actions.length > 0) {
        res.actions = options.Actions.map(function (item) { return { action: item.Name, title: item.Title, icon: item.Icon }; });
    }
    return res;
}
4

0 回答 0