登录方法总结


参考

Express+JWT最轻实践
JS的防抖与节流

一、Ajax(Asynchronous JavaScript and XML)

  • 优点:无刷新更新数据,减少用户等待事件;
    Ajax使用异步方式与服务器通信,不需要打断用户的操作,减少不必要的数据传输、时间及降低网络上的数据流量;
    界面呈现与应用数据分离;
  • 缺点:后退与书签收藏功能;解决:1. HTML5创建一个隐藏的iframe来跟踪历史记录,重现页面上的变化;
  1. 使用URL片段标识符(#)来保持追踪;接口暴露,跨站点脚本攻击、SQL注入攻击、基于Credentials的安全漏洞;

二、 XMLHttpRequest

  1. 4个阶段:0: 初始化状态,对象创建或者abort()重置;1: open调用; 2: send调用; 3. receiving:响应头部接收; 4. loaded: http响应完全接收
  2. setRequestHeader()
  3. 手写Ajax

    var ajax = {} ;
    ajax.httpRequest = function () {
     if(window.XMLHttpRequest) {
         return new XMLHttpRequest();
     }
     var version = ["MSXML2.XmlHttp.6.0", "MSXML2.XmlHttp.5.0", "MSXML2.XmlHttp.4.0","MSXML2.XmlHttp.3.0", "MSXML2.XmlHttp.2.0", "MSXML2.XmlHttp"]
     var xhr;
     for(var i = 0; i < versions.length; i++) {
         try {
             xhr = new ActiveXObject(versions[i]);
             break;
         } catch (e) {
    
         }
     }
     return xhr;
    }
    
    ajax.send = function(url, callback, method, data, async) {
     //默认异步
     if(async == undefined) {
     async = true;
     }
     var httpRequest = ajax.httpRequest();
     httpRequest.open(method, urlm async);
     httpRequest.onreadystatechange = function() {
         if(httpRequest.readyState == 4) {
             callback(httpRequest.responseText)
         }
     };
     if(method == 'POST') {
         httpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
     }
     httpRequest.send(data);
    };
    
    ajax.get = function(url, data, callback, async) {
     var query = [];
     for(var key in data) {
         query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
     }
     ajax.send(url + (query.length ? '?' + query.join('&') : ''), callback, 'GET', null, async)
    }
    
    ajax.post = function(url, data, callback, async) {
     var query = [];
     for(var key in data) {
         query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
     }
     ajax.send(url, callback, 'POST', query.join('&'), async);
    }
    

默认 async = true -> 异步
默认 async = false -> 同步

console.log(1);
$.ajax({
    url: "",
    async: false,
    success: function() {
        console.log(2);
    }
});
console.log(3);

三、 Axios

  • 使用
    axios({
      method: 'get',
      url: 'http://example.com/test',
      responseType: 'stream'
    })
    .then(function(response){
      response.data.pipe(fs.createWriteStream('example_img.jpg'))
    })
    .catch(e) {
      console.log(e);
    }
    
  • 手写文件上传
    <form role="form" onsubmit="return false">
      <div class="form-group">
          <label for="file">File</label>
          <input id="file" type="file" class="from-control"></input>
      </div>
      <button id="updload" type="button">Update</button>
    </form>
    <script>
      (function(){
          var output = document.getElementById('output');
          document.getElementById('upload').onclick = function() {
              var data = new FormData();
              data.append('foo', 'bar');
              data.append('file',document.getElementById('file').files[0]);
              var config = {
                  onUploadProgress: function(processEvent) {
                      var percentCompleted = Math.round((processEvent.load * 100 ) / processEvent.total);
                  }
              };
              axios.put('/updload/server', data, config)
                  .then(function(res){
                      output.className = 'container';
                      output.innerHTML = res.data;
                      })
          }
      })();
    </script>
    

四、 session-cookie实现登录

  • session是用来在客户端与服务器之间保持状态的解决方案,在服务器端可以存储在文本文件或者redis;session有生命周期;存储特定用户会话所需的属性及配置信息。
  • 我们通过用户名和密码提交表单,通过api提交服务器之后,首先检查请求头没有携带cookie,有的话就检查cookie中有没有携带session_id字段值是否存在数据库或者文本文件,更新过期时间;
  • 没有的话就重新生成一个session_id,可以通过时间戳再加密生成,在res的响应头部设置Set-Cookie在客户端创建一个cookie(name=value, 域domain, 路径path; 失效时间expires/max-age; 日期格式; secure:只能发送给https; HttpOnly)
  • express-session的中间件: 直接初始化的时候设置了存储的数据库,还用用来加密的字段,用的时候,就直接调用req.session req.session.regenerate req.session.destroy
var sessions = {};
var key = 'session_id';
var EXPIRES = 20*60*1000;
var generate  = function () {
    var session = {};
    session.id = (new Date().getTime()) + Math.random();
    session.cookie = {
        expire: (new Date()).getTime() + EXPIRES
    }
    sessions[session.id] = session
}

function (req, res) {
    var id = req.cookies[key];
    if (!id) {
        req.session = generate();
    } else {
        var session = sessions[id];
        if (session) {
            if (session.cookie.expire > new Date().getTime()) {
                session.cookie.expire = new Date().getTime() + EXPIRES;
                req.session = session;
            } else {
                delete sessions[id];
                req.session = generate();
            }
        } else {
            req.session = generate();
        }
    }
}

五、express + token登录

  • jwt: 头部(tpye, algorithmn),有效载荷和签名
  • 服务器不用存放token数据,用户验证后,服务器生成一个token(一般用hash或者encrypt)存在cookie中发给客户端,客户端每次请求在头部cookie带上token;
  • 把头部和playload和我们提供的密钥进行编码连接生成签名
  • 在vuex中,如果更新的话,通过commit更新token和authUser=user, nuxtServerInit 用户信息+服务端算法=》加密形成token; axios可以做一个请求拦截,给请求带上token. localStorage.getItem

六、跨域

proxyTable: {
      '/api': {
        target: 'http://121.41.130.58:9090',//设置你调用的接口域名和端口号 别忘了加http
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''//这里理解成用‘/api’代替target里面的地址,后面组件中我们掉接口时直接用api代替 比如我要调用'http://40.00.100.100:3002/user/add',直接写‘/api/user/add’即可
        }
      }
    }
        axios.post('/api/yt_api/login/doLogin',postData)
    .then(function (response) {
        console.log(1)
        console.log(response);
    })
    .catch(function (error) {
        console.log(error);
    })
  • CORS: axios设置请求头
    • Origin: http://www.example.com
    • 服务器返回: Access-Control-Allow-Origin: http://www.example.com
  • JSONP
    var script = document.createElement('script');
    script.src = "http://sss/?callback=handleResponse"
    document.body.insertBefore(script, document.body.firstChild)
    
  • 网络安全

    • CSRF(Cross-Site Request Forgery)跨站点请求伪造
    • SQL注入攻击 (查询字符串过滤)
    • 文件上传攻击
    • XSS跨站脚本攻击
    • 程序逻辑漏洞
  • 图片懒加载

    • 原因:因为那个影片查询页面,一个页面的图片很多,一次加载完很影响性能;
    • 原理:页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有js设置了图片路径,浏览器才会发送请求;懒加载的原理就是先在页面中把所有图片统一使用一张占位图进行占位,把真正的路径存在“data-src”属性里;页面加载后,根据scrollTop判断图片是否在用户视野,在就将”data-src”的属性值取出存放到”src”属性;滚动事件中重复判断。
      function isVisible($node) {
          var winH = $(window).height(),                                    //浏览器窗口高度
              scrollTop = $(document).scrollTop(),                          //滚轮滚动高度
              offSetTop = $node.offset().top;                               //元素距离浏览器顶部的距离
          if (offSetTop < winH + scrollTop) {
              let src_value = $node.attr("data-src");
              $node.attr("src", src_value);
              console.log('loading img');
              return true;
          } else {
              return false;
          }
      }
      function loadPartImg() {
          $(".pic").each(function () {
              if ($(this).attr("src") != "") {
                  return;
              } else {
                  isVisible($(this));
              }
          });
      }
      loadPartImg();
      $(window).on("scroll", function () {
          loadPartImg();
      });
      
  • 防抖:函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。如下图,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。

    function debounce(fn, wait) {
      var timeout = null;
      return function() {
          if(timeout !== null)
                  clearTimeout(timeout);
          timeout = setTimeout(fn, wait);
      }
    }
    // 处理函数
    function handle() {
      console.log(Math.random());
    }
    // 滚动事件
    window.addEventListener('scroll', debounce(handle, 1000));
    
  • 节流:函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。

    var throttle = function(func, delay) {
      var prev = Date.now();
      return function() {
          var context = this;
          var args = arguments;
          var now = Date.now();
          if (now - prev >= delay) {
              func.apply(context, args);
              prev = Date.now();
          }
      }
    }
    function handle() {
      console.log(Math.random());
    }
    window.addEventListener('scroll', throttle(handle, 1000));
    

Vue原理复习

  1. 一个Vue实例(一个ViewModel的实例)挂载到页面,编译模板+数据劫持
    https://cloud.tencent.com/developer/article/1164037

文章作者: Susie Chang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Susie Chang !
 上一篇
闭包的理解 闭包的理解
闭包的理解 闭包 是指有权访问另一个函数作用域中变量的函数。创建闭包最常见的方式就是在一个函数的内部创建另一个函数,通过另一个函数访问这个函数的局部变量 利用闭包可以突破作用域链,将函数内部的变量和方法传递到外部 作用域链的理解:当某个函数
2018-09-12
下一篇 
JavaSript数组详解 JavaSript数组详解
创建数组 构造函数 var arr = new Array(); 已知长度:var arr = new Array(20); 传入值:var arr = new Array("red", "yellow&quo
2018-09-03
  目录