一、两种storage 如何监听他们的变化?
localStorage
和 sessionStorage
并没有内置的事件监听机制,因此无法直接监听它们的变化。但是可以使用以下方法实现监听:
(1)使用 storage 事件:localStorage
和 sessionStorage
对象都会触发 storage
事件,当其他窗口或标签页对存储进行更改时会触发该事件。您可以通过添加 storage
事件监听器来捕获变化,并在回调函数中执行相应的操作。
// 方法一:监听 storage 事件
window.addEventListener('storage', function(event) {
if (event.storageArea === localStorage) {
// localStorage 发生变化
console.log('localStorage 发生变化');
console.log('Key发生变化的值是: ' + event.key);
console.log('New Value发生变化的值是: ' + event.newValue);
} else if (event.storageArea === sessionStorage) {
// sessionStorage 发生变化
console.log('sessionStorage 发生变化');
console.log('Key发生变化的值是: ' + event.key);
console.log('New Value发生变化的值是:' + event.newValue);
}
});
(2)使用定时器:通过使用定时器,在一定的时间间隔内轮询检查存储的值是否发生变化,并在变化时执行相应的操作。
// 监听 localStorage 变化
function startLocalStorageListener() {
// 获取初始的 localStorage 值
var initialValue = JSON.stringify(localStorage);
// 每隔一段时间检测 localStorage 是否变化
setInterval(function() {
var updatedValue = JSON.stringify(localStorage);
if (updatedValue !== initialValue) {
// localStorage 发生变化,执行相应的操作
console.log("localStorage 发生变化");
// 更新初始的 localStorage 值
initialValue = updatedValue;
}
}, 1000);
}
// 监听 sessionStorage 变化
function startSessionStorageListener() {
// 获取初始的 sessionStorage 值
var initialValue = JSON.stringify(sessionStorage);
// 每隔一段时间检测 sessionStorage 是否变化
setInterval(function() {
var updatedValue = JSON.stringify(sessionStorage);
if (updatedValue !== initialValue) {
// sessionStorage 发生变化,执行相应的操作
console.log("sessionStorage 发生变化");
// 更新初始的 sessionStorage 值
initialValue = updatedValue;
}
}, 1000); // 检测间隔为1秒
}
// 启动监听
startLocalStorageListener();
startSessionStorageListener();
(3)使用 Proxy 对象:通过创建一个 Proxy
对象来代理localStorage
或sessionStorage
,可以拦截对存储的读写操作,并在变化时执行自定义的操作。
// 监听存储变化的封装函数
function addStorageListener(storageType, callback) {
// 根据存储类型选择 localStorage 或 sessionStorage
var storage = (storageType === 'localStorage') ? localStorage : sessionStorage;
// 创建 Proxy 对象
var proxy = new Proxy(storage, {
set: function(target, key, value) {
// 存储值发生变化,执行回调函数
callback(key, value);
// 在实际存储前设置新的值
target[key] = value;
return true;
}
});
}
// 使用示例
addStorageListener('localStorage', function(key, value) {
console.log('localStorage 发生改变');
console.log('Key发生变化的值是: ' + key);
console.log('Value发生变化的值是: ' + value);
});
addStorageListener('sessionStorage', function(key, value) {
console.log('sessionStorage 发生改变');
console.log('Key发生变化的值是: ' + key);
console.log('Value发生变化的值是: ' + value);
});
(4)封装自定义函数:使用自定义的封装函数来检测 localStorage
和 sessionStorage
的变化,您可以创建一个函数,该函数在存储值发生变化时被调用,并通过监听 storage
事件来触发回调函数。
// 监听存储变化的封装函数
function addStorageListener(storageType, callback) {
// 根据存储类型选择 localStorage 或 sessionStorage
var storage = (storageType === 'localStorage') ? localStorage : sessionStorage;
// 事件监听器回调函数
function storageEventListener(event) {
if (event.storageArea === storage) {
// 存储值发生变化,执行回调函数
callback(event.key, event.newValue);
}
}
// 添加事件监听器
window.addEventListener('storage', storageEventListener);
}
// 使用示例
addStorageListener('localStorage', function(key, value) {
console.log('localStorage 发生改变');
console.log('Key发生变化的值是: ' + key);
console.log('Value发生变化的值是: ' + value);
});
addStorageListener('sessionStorage', function(key, value) {
console.log('sessionStorage 发生改变');
console.log('Key发生变化的值是: ' + key);
console.log('Value发生变化的值是: ' + value);
});
二、如果要给localstorage存储的数据设置过期时间,你会怎么设计技术方案?
(1)手动添加时间戳:在存储数据时,同时将数据和过期时间(时间戳)一起存储。在读取数据时,先检查当前时间是否超过了过期时间,如果是则认为数据已过期,可以进行相应的处理。
// 存储数据到 localStorage,并设置过期时间
function setStorageTime(key, value, time) {
var dataTime = time * 60 * 1000; // 转换为毫秒
var item = {
value: value,
expiration: Date.now() + dataTime // 当前时间加上过期时间
};
localStorage.setItem(key, JSON.stringify(item));
}
// 从 localStorage 读取数据,并检查过期时间
function getStorageTime(key) {
var item = localStorage.getItem(key);
if (item) {
item = JSON.parse(item);
if (item.expiration && Date.now() > item.expiration) {
// 数据已过期
localStorage.removeItem(key);
return null;
}
return item.value;
}
return null;
}
// 使用示例
setStorageTime('username', 'Cheng Dong', 10); // 存储数据并设置过期时间为 10 分钟
var username = getStorageTime('username'); // 读取数据
console.log(username); // 输出 'Cheng Dong',如果在 10 分钟内执行,否则输出 null
(2)结合定时器清理过期数据:使用定时器定期检查存储的数据的过期时间,并清理已过期的数据。您可以使用 setInterval
函数设置一个定时器,在固定的时间间隔内检查存储的数据的过期时间,并删除已过期的数据。这样可以保持存储空间的有效利用,同时确保过期数据不会被使用。
// 存储数据到 localStorage,并设置过期时间
function setStorageTime(key, value, time) {
var dataTime = time * 60 * 1000; // 转换为毫秒
var item = {
value: value,
expiration: Date.now() + dataTime // 当前时间加上过期时间
};
localStorage.setItem(key, JSON.stringify(item));
}
// 从 localStorage 读取数据,并检查过期时间
function getStorageTime(key) {
var item = localStorage.getItem(key);
if (item) {
item = JSON.parse(item);
if (item.expiration && Date.now() > item.expiration) {
// 数据已过期
localStorage.removeItem(key);
return null;
}
return item.value;
}
return null;
}
// 清理过期数据
function clearDataTime() {
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
var item = localStorage.getItem(key);
if (item) {
item = JSON.parse(item);
if (item.expiration && Date.now() > item.expiration) {
// 数据已过期,从 localStorage 中移除
localStorage.removeItem(key);
}
}
}
}
// 设置定时器定期清理过期数据
setInterval(function() {
clearDataTime();
}, 60 * 1000); // 每分钟清理一次
// 使用示例
setStorageTime('username', 'Cheng Dong', 10); // 存储数据并设置过期时间为 10 分钟
var username = getStorageTime('username'); // 读取数据
console.log(username); // 输出 'Cheng Dong',如果在 10 分钟内执行,否则输出 null
(3)使用自定义封装函数:创建一个封装函数来包装 localStorage
的存储和读取操作,并在其中实现过期时间的逻辑。该函数可以接收一个过期时间参数,并在存储数据时同时存储过期时间。在读取数据时,检查当前时间是否超过了过期时间,如果是则返回空值或默认值。
// 存储数据到 localStorage,并设置过期时间
function setStorageTime(key, value, time) {
var dataTime = time * 60 * 1000; // 转换为毫秒
var item = {
value: value,
expiration: Date.now() + dataTime // 当前时间加上过期时间
};
localStorage.setItem(key, JSON.stringify(item));
}
// 从 localStorage 读取数据,并检查过期时间
function getStorageTime(key) {
var item = localStorage.getItem(key);
if (item) {
item = JSON.parse(item);
if (item.expiration && Date.now() > item.expiration) {
// 数据已过期
localStorage.removeItem(key);
return null;
}
return item.value;
}
return null;
}
// 使用示例
setStorageTime('username', 'Cheng Dong', 10); // 存储数据并设置过期时间为 10 分钟
var username = getStorageTime('username'); // 读取数据
console.log(username); // 输出 'Cheng Dong',如果在 10 分钟内执行,否则输出 null
三、用以上提到的api中的一种或几种来实现跨Tab页通信,你会怎么来做?
(1)localStorage实现跨Tab页通信
// 设置
localStorage.setItem('message', '我是localStorage的值');
// 监听使用
window.addEventListener('storage', function(event) {
if (event.key === 'message') {
var message = event.newValue;
console.log('message:', message);
}
});
(2)sessionStorage实现跨Tab页通信
sessionStorage.setItem('message', '我是sessionStorage的值');
// 触发自定义事件来通知其他标签页
var event = new Event('sessionStorageUpdated');
window.dispatchEvent(event);
window.addEventListener('storage', function(event) {
if (event.key === 'message') {
var message = sessionStorage.getItem('message');
console.log('message:', message);
}
});
// 监听自定义事件来检测 `sessionStorage` 的更新
window.addEventListener('sessionStorageUpdated', function() {
var message = sessionStorage.getItem('message');
console.log('message:', message);
});
(3)cookie实现跨Tab页通信
// 设置cookie
document.cookie = "message = 我是设置的Cookie值";
// 自定义函数
function getCookie(name) {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
if (cookie.startsWith(name + "=")) {
return cookie.substring(name.length + 1);
}
}
return "";
}
// 使用
var message = getCookie("message");
console.log("message:", message);
注:
1、Cookies
在每个 HTTP
请求中都会被发送到服务器,而不仅仅限于同一浏览器标签页之间,而且会增加网络传输的负担。
2、Cookies
的大小有限制,一般为几 KB。因此,适用于较小量的数据通信。
3、Cookies
受浏览器安全问题。
4、storage
事件只在其他标签页中触发,而在进行写入操作的标签页上不会触发该事件。
5、localStorage
存储的数据是共享的,因此需要小心处理数据的同步和更新,以避免冲突和数据不一致的问题。
6、storage
事件在更新同一 sessionStorage
的标签页之间不会触发。
7、storage
事件无法提供更改的具体值,因此我们需要手动读取 sessionStorage
的值来获取更新的数据。
8、sessionStorage
实现跨Tab
页面的通信没有localStorage
那样直接和简单。
四、cookie是否会导致安全性问题?
cookie
会导致安全性问题:
例如:
1、信息泄露:不适当地处理和存储 Cookie 可能导致敏感信息泄露
解决办法:
-
仅在必要的情况下存储敏感信息,并在不再需要时立即删除。
-
使用加密技术来保护敏感信息的存储和传输。
2、会话劫持:攻击者通过获取合法用户的会话信息,冒充该用户与系统进行交互,从而获取未经授权
的访问权限或执行恶意操作。
解决办法:
-
使用安全的传输层协议(如 HTTPS)来加密会话数据,防止被窃听和篡改。
-
定期更新会话 Cookie 的值,使攻击者更难截获有效的会话。
3、跨站点脚本攻击(XSS):攻击者利用该漏洞向目标网站注入恶意脚本代码,从而在用户的浏览器
中执行恶意代码。
解决办法:
-
对用户输入进行验证和过滤,确保不允许注入恶意脚本。
-
对敏感的 Cookie 设置 Secure 标记,仅在通过 HTTPS 连接时传输。
4、跨站点请求伪造(CSRF):攻击者通过诱使用户点击恶意链接或访问包含恶意代码的页面,以利用
用户在目标网站上的已认证会话
解决办法:
-
使用 CSRF 令牌(也称为防护令牌)来验证请求的来源和合法性。
-
在关键操作(如修改或删除数据)上使用 POST 请求而不是 GET 请求。
-
验证请求的来源,例如检查 Referer 头部。
五、同域名下的 sessionStorage
数据会不会共享
sessionStorage
的作用域限定在当前会话中,关闭窗口或标签页后数据将被清除。即使是同一域名的不同窗口或者标签,他们之间的sessionStorage
数据也是相互隔离的,无法直接共享。每个窗口或者标签都有自己独立的sessionStorage
对象,他们之间的数据互不干扰。
六、不同的子域名之间cookie
互通吗
不同的子域名之间cookie
是不互通的,每个子域名都会被视为不同的域,浏览器会将其视为独立的上下文,各自维护自己的cookie
。