zoukankan      html  css  js  c++  java
  • csrf攻击原理和防御-生成token防御代码

    前言

    CSRF(Cross-site request forgery,跨站请求伪造,恶意网站伪造身份冒充你向目标服务器发送请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

    攻击原理

    csrf攻击通过利用浏览器机制:发送请求的域相同时,浏览器会自动携带相同cookie.具体原理做法如下:

    客户刚登录完目标网站,目标网站下发了信任凭证cookie.客户没有执行登出操作,在目标网站仍然开启的情况下,进入了恶意网站.恶意网站内,攻击行为是向目标网站的服务器发起请求,恶意网站会把请求域名设置的和目标网站cookie的Domain相同.利用同一个浏览器下发送请求时,请求域名和domain相同,会携带该domain属于的cookie这一点,恶意网站请求可以携带上目标网站的cookie.目标网站的服务器接受到请求后,会认为这是用户的操作,就会去执行操作内容

    如下请求,是恶意网站的常见代码,img或a向目标服务器发送请求,由于请求域(xiaodidi.com)和目标网站域相同,请求时就会自动携带上xiaodidi.com域的相关cookie

    <img src="http://www.xiaodidi.com....>
    <a href=
    "http://www.xiaodidi.com....>

    攻击代码举例

    恶意网站只需要发送如下一个请求给银行,银行那边就会给这个id的用户扣款1000

    <img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>

    解决csrf方法

    csrf攻击利用了浏览器在请求域相同时,会携带相同cookie,达到攻击目的.从这个角度想,我们防止csrf攻击可以,我们可以额外添加一个token身份验证,因为token不是cookie,恶意网站没有办法拿到token放到请求中.服务端接受请求时去判断cookie和token是否正确,双管齐下.

    具体到项目中流程是:

    • 第一次登录的时候,服务端生成token,通过响应头返回
    • 客户端拿到响应头的token,存储在localstorage中(一定不能在cookie中)
    • 客户端设置全局的请求配置,给每个请求头都加上token
    • 服务端拿到前端请求的token,解密token对比验证身份

    实现代码:

    ps:用nodejs做服务端

    1.第一次登录的时候,服务端node用插件jsonwebtoken生成token,在express的res.set方法中将token放入响应头中,返回给客户端

    下载jsonwebtoken,生成token,

    //生成token
    const jwt = require('jsonwebtoken');
    let token = jwt.sign(username, privateKey, { algorithm: 'RS256' });

    res.set方法中将token放入响应头中

    res.set('X-ACCESS-TOKEN', token)
          //添加token, 向header里面添加一个自定义的字段,
          req.session.username = user["username"];
          res.send({
            code: 1,
            username: user["username"],
            message: "用户登录成功"
          })

    2.客户端在ajax请求的success回调中拿到响应头的token,存储在localstorage中

    const post = (url, data) => {
      return new Promise((resolve, reject) => {
        $.ajax({
          url,
          type: 'POST',
          data,
         //xhr内部包含响应头内容,具体可查看ajax文档
          success: (res, status, xhr) => {
            res.status = status;
            res.xhr = xhr;
            resolve(res)
          },
          error: (err) => {
            reject(err);
          }
        })
      })
    }
    //rs是resolve()方法中的内容,这里省略了.then
    //jquery.ajax内部参数xhr中通过getResponseHeader可以获取header内的具体内容
    let token = rs.xhr.getResponseHeader("x-access-token")
    localStorage.setItem('token', token);

    3.客户端设置全局的请求配置,给每个请求头都加上token

     $.ajaxSetup({
    //全局发送请求前配置 beforeSend(xhr, setting) { let token
    = localStorage.getItem('token');
           xhr.setRequestHeader(
    'x-access-token', token); }, complete(xhr, setting) { if (xhr.responseJSON.code === 401) { alert(xhr.responseJSON.message) router.go('/index') } } })

    4.服务端拿到前端请求的token,解密token对比验证身份,不合法的身份返回401

    const jwt = require('jsonwebtoken')
    function auth(req, res, next) {
      if (req.session.username) {
        try {
          let token = req.get('x-access-token');
          //对称
          let rs = jwt.verify(token, 'lagouadmin')
          if (rs === req.session.username) {
            next();
          } else {
            res.send({
              code: 401,
              message: "非法访问"
            })
          }
        } catch (error) {
          log.error(req.session.username + " 登录失败 " + error.message)
          res.send({
            code: 401,
            message: "非法访问"
          })
        }
      } else {
        res.send({
          code: 401,
          message: "非法访问"
        })
      }
    }
    
    module.exports = auth;

    以上就是一个csrf防守生成token的代码实现流程

  • 相关阅读:
    如何使用第三方webservice
    SQL零星技术点:SQL中转换money类型数值转换为字符串问题
    P2664 树上颜色统计 点分治 虚树 树上差分 树上莫队
    SPOJ 1825 经过不超过K个黑点的树上最长路径 点分治
    P4149 距离为K的点对(最少边数) n=200000 点分治
    P2634 树上路径长度为3的倍数的点对数 点分治
    P3806 离线多次询问 树上距离为K的点对是否存在 点分治
    POJ 1741 单次询问树上距离<=K的点对数 点分治
    BZOJ 1016 生成树计数
    BZOJ 1015 并查集&连通块
  • 原文地址:https://www.cnblogs.com/liuXiaoDi/p/12994370.html
Copyright © 2011-2022 走看看