token认证

token认证

1、CSRF是什么?

CSRF(Cross-site request forgery),中文名称:跨站请求伪造。攻击者盗用你的身份,以你的名义发送恶意请求。CSRF可以作的事情包括:以你名义发送邮件,发消息,盗取你的帐号,甚至于购买商品,虚拟货币转帐......形成的问题包括:我的隐私泄露以及财产安全。javascript

2、CSRF攻击原理

图片描述

3、防护CSRF的策略:token认证

一、token验证方法html

(1)、CSRF 攻击之因此可以成功,是由于黑客能够彻底伪造用户的请求,该请求中全部的用户验证信息都是存在于 cookie 中,所以黑客能够在不知道这些验证信息的状况下直接利用用户本身的 cookie 来经过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,而且该信息不存在于 cookie 之中。能够在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端创建一个拦截器来验证这个 token,若是请求中没有 token 或者 token 内容不正确,则认为多是 CSRF 攻击而拒绝该请求。前端

(2)、这种方法要比检查 Referer 要安全一些,token 能够在用户登录后产生并放于 session 之中,而后在每次请求时把 token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。对于 GET 请求,token 将附在请求地址以后,这样 URL 就变成 http://url?csrftoken=tokenvalue。 而对于 POST 请求来讲,要在 form 的最后加上 <input type=”hidden” name=”csrftoken” value=”tokenvalue”/>,这样就把 token 以参数的形式加入请求了。可是,在一个网站中,能够接受请求的地方很是多,要对于每个请求都加上 token 是很麻烦的,而且很容易漏掉,一般使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中全部的 a 和 form 标签后加入 token。这样能够解决大部分的请求,可是对于在页面加载以后动态生成的 html 代码,这种方法就没有做用,还须要程序员在编码时手动添加 token。java

(3)、该方法还有一个缺点是难以保证 token 自己的安全。特别是在一些论坛之类支持用户本身发表内容的网站,黑客能够在上面发布本身我的网站的地址。因为系统也会在这个地址后面加上 token,黑客能够在本身的网站上获得这个 token,并立刻就能够发动 CSRF 攻击。为了不这一点,系统能够在添加 token 的时候增长一个判断,若是这个连接是链到本身本站的,就在后面添加 token,若是是通向外网则不加。不过,即便这个 csrftoken 不以参数的形式附加在请求之中,黑客的网站也一样能够经过 Referer 来获得这个 token 值以发动 CSRF 攻击。这也是一些用户喜欢手动关闭浏览器 Referer 功能的缘由。程序员

二、token产生ajax

Token是在服务端产生的。若是前端使用用户名和密码向服务端发送请求认证,服务端认证成功,那么在服务端会返回Token给前端。前端能够在每次请求的时候带上Token证实本身的合法地位。若是Token在服务端持久化,那他就是一个永久的身份令牌。spring

三、Token设置有效期json

Q: 用户在正常操做的过程当中,Token 过时失效了,要求用户从新登陆……用户体验会很糟糕。segmentfault

A: 方法一,使用 Refresh Token。这种方法中,服务端不须要刷新 Token 的过时时间,一旦 Token 过时,就反馈给前端,前端使用 Refresh Token 申请一个全新 Token 继续使用。这种方法中,服务端只须要在客户端请求更新 Token 的时候对 Refresh Token 的有效性进行一次检查,大大减小了更新有效期的操做,也就避免了频繁读写。固然 Refresh Token 也是有有效期的,可是这个有效期就能够长一点了,好比,以天为单位的时间。api

(1)、实例以下:
//通常是登陆时向服务器发请求获取到Token
function login(username,password){
    var param = {"username":username,"password":password};
    $.post("/api/v1/login",param,function(data){
        //将response获得的Token缓存到sessionStorage里面
        sessionStorage.setItem('Token',data.TOKEN);
    }).error(function(error){
        alert(JSON.parse(error.responseText).errorMsg);
    })
}

//登陆事件
$("#login").click(function(){
    var username=$('input[name=username]').val();
    var password=$('input[name=password]').val(); 
    login(username,password);
})
(2)、token请求验证:

客户端拿sessionStorage中存储的Token去向服务端进行验证:

function ajaxRequest = function(option) {
    $.ajax({
      url: getDmsFuncIdUrl(newUrl, currentToken),
      type: option.type,
      data: option.data,
      dataType: "json",
      async: option.async != undefined ? option.async : true,
      cache: false,
      beforeSend: function(xhr) {
        xhr.setRequestHeader("Accept", "application/json;charset=UTF-8");
        //设置数据格式:发送json格式数据,并带有字符编码:"charset=UTF-8"
        xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
        //将Token放在请求头header中,此处格式与后台一一对应。
        xhr.setRequestHeader(
          "Authorization",
          "Bearer " + getParamsStorage("Token")
        );
        if (option.beforeSend) {
          option.beforeSend(xhr);
        }
      },
      success: function(data, textStatus, jqXHR) {
        //结束ajax请求
        ajaxRestEnd(option);
      },
      error: function(XMLHttpRequest, textStatus, errorThrown) {
        //结束ajax请求
        ajaxRestEnd(option);
      }
    })
  };

以下图:

注意:图中定义的Token验证接口(只要是请求的 "http://${spring.cloud.client.ipAddress}:${server.port}/xxx" 这个端口号下的任何路径都会先进行Token验证的),请求参数为Content-Type和Authorization,且Authorization的请求数据格式为:Authorization : Bearer token,因此咱们上面的代码是: xhr.setRequestHeader("Authorization","Bearer " + getParamsStorage("Token"));

图片描述

(3)、总结:

这样咱们每次的请求都调用 ajaxRequest 方法便可,即在每次请求接口数据的的时候都会带上咱们登录后得到的Token值,这样就能经过服务器的验证,打开服务器的大门,进而进行不一样接口数据的调用啦!是否是很清楚呢~~~

(4)、Refresh Token

通常是在获取页面的公共经常使用数据的时候刷新Token值

//刷新Token
  function refreshToken() {
    dmsCommon.ajaxRestRequest({
      url:"/api/v1/login/refreshToken",
      type: "GET",
      async: false,
      sucessCallBack: function(data) {
        currentToken = data;
      }
      });
    }


  //每5分钟刷新一次token 值
  function refreshTokenInterval() {
    setInterval(refreshToken, 5 * 60 * 1000);
  }
  

  //初始化常规数据
  function getMainnData(){
   
    // coding
    
    //进行定时刷新
    refreshTokenInterval();
   }
借鉴大牛的文章,浅显易懂, URL: https://segmentfault.com/a/11...
相关文章
相关标签/搜索