浅谈service-worker

前言

第一次接触service-worker是在基于Service Worker 的XSS攻击面拓展这一篇博客上,然后再2019RCTF Jail&Password上有一道题利用service-worker来绕过CSP,这里学习一下。

service-worker的生命周期

可以参考:Service Worker那些事

Service Worker 简介

使用 Service Workers

我的第一个Service Worker

代码来自:sw-test

注册

1
2
3
4
5
6
7
8
9
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(function(registration) {
// 注册成功
console.log('ServiceWorker registration successful with scope: ', registration.scope);
}).catch(function(err) {
// 注册失败
console.log('ServiceWorker registration failed: ', err);
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {

if(reg.installing) {
console.log('Service worker installing');
} else if(reg.waiting) {
console.log('Service worker installed');
} else if(reg.active) {
console.log('Service worker active');
}
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
}

SW的注册还有一些要求:

1
2
3
<script>
navigator.serviceWorker.register("/sw.js")
</script>

除了script标签以外,link标签也可以用来注册service worker,像

1
<link rel="serviceworker" href="/sw.js">

1、只能注册同源下的js

2、站内必须支持Secure Context,也就是站内必须是https://或者http://localhost/

3、Content-Type必须是js

  • text/javascript
  • application/x-javascript
  • application/javascript

安装激活

在你的 Service Worker 注册成功之后呢,我们的浏览器中已经有了一个属于你自己 web App 的 worker context 啦, 在此时,浏览器就会马不停蹄的尝试为你的站点里面的页面安装并激活它,并且在这里可以把静态资源的缓存给办了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open('v1').then(function(cache) {
return cache.addAll([
'/sw-test/',
'/sw-test/index.html',
'/sw-test/style.css',
'/sw-test/app.js',
'/sw-test/image-list.js',
'/sw-test/star-wars-logo.jpg',
'/sw-test/gallery/bountyHunters.jpg',
'/sw-test/gallery/myLittleVader.jpg',
'/sw-test/gallery/snowTroopers.jpg'
]);
})
);
});

self.addEventListener('fetch', function(event) {
event.respondWith(caches.match(event.request).then(function(response) {
// caches.match() always resolves
// but in case of success response will have value
if (response !== undefined) {
return response;
} else {
return fetch(event.request).then(function (response) {
// response may be used only once
// we need to save clone to put one copy in cache
// and serve second one
let responseClone = response.clone();

caches.open('v1').then(function (cache) {
cache.put(event.request, responseClone);
});
return response;
}).catch(function () {
return caches.match('/sw-test/gallery/myLittleVader.jpg');
});
}
}));
});

注销

注销所有已注册的sw

1
2
3
4
5
6
7
8
9
var serviceWorker = navigator.serviceWorker;

serviceWorker.getRegistrations ? serviceWorker.getRegistrations().then(function(sws) {
sws.forEach(function(sw) {
sw.unregister();
});
}) : serviceWorker.getRegistration && serviceWorker.getRegistration().then(function(sw) {
sw && sw.unregister();
});
-------------本文结束感谢您的阅读-------------