国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

【web安全】API的安全策略

RobinQu / 1000人閱讀

摘要:最近正在負(fù)責(zé)一個(gè)新平臺(tái)的構(gòu)建和開發(fā),有一個(gè)場(chǎng)景需要對(duì)應(yīng)用做新增,修改和撤回的操作起先是因?yàn)橹皩戇^(guò)類型的功能,不想在和以前一樣一個(gè)操作類型一個(gè),覺(jué)得代碼太過(guò)冗余了。

最近正在負(fù)責(zé)一個(gè)新平臺(tái)的構(gòu)建和開發(fā),有一個(gè)場(chǎng)景需要對(duì)應(yīng)用做新增,修改和撤回的操作
起先是因?yàn)橹皩戇^(guò)類型的功能,不想在和以前一樣一個(gè)操作類型一個(gè)api,覺(jué)得代碼太過(guò)冗余了。
于是有了以下的構(gòu)思

第一版
將當(dāng)前界面所有api請(qǐng)求,合并成一個(gè)request,以type作為操作類型的區(qū)分,data為提交的數(shù)據(jù)

這樣當(dāng)前界面所有操作都使用一個(gè)接口來(lái)處理,并且問(wèn)題統(tǒng)一處理

處理token失效

處理catch

處理通信成功后都通知

處理權(quán)限

優(yōu)化版
當(dāng)設(shè)計(jì)成第一版后,我覺(jué)得操作類型暴露在外面有些不妥,起先想的是后端生成隨機(jī)碼和對(duì)應(yīng)的加密值,通過(guò)解密拿到方法名。
后來(lái)優(yōu)化了一下,加入了url來(lái)源的判斷,還能防止postman的攻擊
后端代碼如下:

redisImp為redis
utils為工具類
token和權(quán)限的檢查放在了外層,進(jìn)入方法的都當(dāng)成token和權(quán)限通過(guò)的

const apiPrefix = "ApiType:";
// 通過(guò)viewConfig生成對(duì)應(yīng)配置
async function generateConfig (owner, viewConfig) {
    var viewName = viewConfig.name; // 界面名稱
    var viewMethods = viewConfig.methods; // 界面所支持的操作方法

    let key = apiPrefix + owner + ":" + viewName;
    await redisImp.del(key);
    let para = [], config = [], secret = [];
    // 生成10個(gè)長(zhǎng)度為12的隨機(jī)碼
    for (var i = 0; i < 10; i++) {
      var randomKey = utils.generateRandomStr(12);
      config.push(randomKey);
    }
    // 生成三個(gè)10一下的數(shù)字
    var random1 = Math.ceil(Math.random() * 10);
    var random2 = Math.ceil(Math.random() * 10);
    var random3 = Math.ceil(Math.random() * 10);
    // todo 檢查3個(gè)隨機(jī)數(shù)是否相等
    var randomList = [random1, random2, random3];
    // 生成隨機(jī)碼和操作方法的關(guān)聯(lián)數(shù)據(jù)
    viewMethods.forEach(function (value, index) {
      para.push(config[randomList[index]]);
      para.push(value);
      secret.push(randomList[index]);
    })
    // aes加密
    var enc = utils.cryptedAES(secret.toString());
    let redisResult = await redisImp.hSet(key, para);
    if (redisResult.code === 200) {
      return {
        apis: config,
        secret: enc
      }
    }
    return null;
  }
  // 獲取界面的配置
  function getViewConfig (ctx) {
    var referer = ctx.request.header.referer; // 原始url
    var origin = ctx.request.header.origin; // 來(lái)源
    var config;
    if (!referer || !origin) {
        // todo 處理異常訪問(wèn)
        return config;
    } else {
        var fontUrl = referer.replace(origin, "").split("?"); // 去除domain和url參數(shù)后的路徑
        switch (fontUrl[0]) {
          case "/app/base": {
            config = {
              name: "appBase", // 界面名稱
              methods: ["add", "modify", "retract"] // 界面操作權(quán)限
            }
            break;
          }
          default: {
          // todo 處理異常攻擊
          }
        }
    }
    return config;
  }
  
  // 獲取配置,暴露給前端的api接口
  const getConfig = async (ctx) => {
    const fName = _name + "getConfig";
    lifecycleLog.info("[Enter] " + fName);
    // 獲取當(dāng)前用戶id
    const redisResult = await redis.GetTokenValue(ctx, "id");
    let owner;
    if (redisResult.code === 200) {
        owner = redisResult.data;
    } else {
        ctx.body = redisResult;
        return;
    }
    // 獲取界面配置
    var viewConfig = getViewConfig(ctx);
    if (viewConfig) {
      var result = await generateConfig(owner, viewConfig);
      if (result) {
        // 生成成功后返回給前端
        ctx.body = Object.assign({code: 200}, result);
      } else {
        ctx.body = controller.dataError();
      }
    } else {
      ctx.body = controller.dataError();
    }
    lifecycleLog.info("[Return] " + fName);
  }

  const appBase = require("./appBase")
  // 處理應(yīng)用界面的接口
  const handleAppBaseData = async (ctx) => {
    const fName = _name + "handleAppBaseData";
    lifecycleLog.info("[Enter] " + fName);

    var viewConfig = getViewConfig(ctx);
    if (viewConfig) {
      const name = ctx.request.body.name; // 前端傳過(guò)來(lái)的操作碼
      const para = ctx.request.body.data; // 前端傳過(guò)來(lái)的數(shù)據(jù)
      let data;
      try {
        data = JSON.stringify(para);
      } catch (err) {
        ctx.body = controller.dataError();
        return;
      }
      // 驗(yàn)證數(shù)據(jù)完整性
      if (controller.dataMissed(ctx, fName, ctx.request.body, name + data)) {
        return;
      }

      const redisResult = await redis.GetTokenValue(ctx, "id");
      let owner;
      if (redisResult.code === 200) {
         owner = redisResult.data;
       } else {
         ctx.body = redisResult;
         return;
       }
      // 從redis拿到當(dāng)前用戶在當(dāng)前界面的操做類型
      let apiType = await redisImp.hGet(apiPrefix + owner + ":" + viewConfig.name, name);
      if (apiType.code === 200) {
        if (apiType.data.length) {
          var methods = apiType.data[0];
          // 添加操作
          if (methods === "add") {
            await appBase.add(ctx, para, owner);
          } else {
            let option = {
              _id: para._id,
              owner: owner
            };
            // 檢測(cè)該用戶是否擁有該app
            const gameResult = await commonModel.getInfo(ctx, collection, option);
            if (gameResult) {
              if (gameResult.code === 200) {
                var gameDoc = gameResult.info["_doc"];
              } else {
                ctx.body = controller.dataError();
                return;
              }
            } else {
              ctx.body = controller.serverError();
              return;
            }
            // 修改操作
            if (methods === "modify") {
              await appBase.modify(ctx, para, gameDoc);
            } else if (methods === "retract") { // 撤回炒作
              await appBase.retract(ctx, gameDoc);
            } else {
              ctx.body = controller.dataError();
              return;
            }
          }
          // 如果入庫(kù)成功,則將新一輪的操作碼反給前端
          if (ctx.body.code === 200) {
            var result = await generateConfig(owner, viewConfig);
            ctx.body = Object.assign(ctx.body, result);
          }
        } else {
          ctx.body = controller.dataError();
        }
      } else {
        ctx.body = controller.serverError();
      }
    } else {
      ctx.body = controller.dataError();
    }
    lifecycleLog.info("[Return] " + fName);
  }

這是返回的結(jié)構(gòu)

    前端就不上代碼了,稍微說(shuō)下應(yīng)該都能明白
    1. 進(jìn)入界面的時(shí)候,請(qǐng)求getConfig
    2. 前端拿到數(shù)據(jù)進(jìn)行解密
    3. 操作界面的時(shí)候,發(fā)送操作碼和數(shù)據(jù)
    4. 請(qǐng)求完成,拿到新的操作碼進(jìn)行本地更新,并對(duì)之前的操作作出反應(yīng)(數(shù)據(jù)更新/界面跳轉(zhuǎn)/彈框提示等)

延伸版
獲取界面配置,可以放在一個(gè)任何界面都會(huì)訪問(wèn)的地方,統(tǒng)一處理,后端配好路由的url即可

解決/預(yù)防了哪些問(wèn)題
1.代碼冗余問(wèn)題
2.爬蟲問(wèn)題(由于所有的操作入?yún)⒍际莿?dòng)態(tài)返回且隨機(jī)生成,爬蟲們沒(méi)法按著一個(gè)接口和數(shù)據(jù)爬取數(shù)據(jù),增大了難度)
3.非正常的訪問(wèn)

以上就是我對(duì)API安全策略的想法,如有異議或新的方式歡迎評(píng)論留言。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/102750.html

相關(guān)文章

  • 論微服務(wù)安全

    摘要:微服務(wù)能夠?yàn)閼?yīng)用程序設(shè)計(jì)提供一種更具針對(duì)性范圍性與模塊性的實(shí)現(xiàn)方案。安全微服務(wù)部署模式可謂多種多樣但其中使用最為廣泛的當(dāng)數(shù)每主機(jī)服務(wù)模式。在微服務(wù)環(huán)境下,安全性往往成為最大的挑戰(zhàn)。不同微服務(wù)之間可通過(guò)多種方式建立受信關(guān)系。 每個(gè)人都在討論微服務(wù),每個(gè)人也都希望能夠?qū)崿F(xiàn)微服務(wù)架構(gòu),而微服務(wù)安全也日漸成為大家關(guān)注的重要問(wèn)題。今天小數(shù)與大家分享的文章,就從應(yīng)用層面深入探討了應(yīng)對(duì)微服務(wù)安全挑戰(zhàn)...

    plokmju88 評(píng)論0 收藏0
  • 如何構(gòu)建安全企業(yè)混合云

    摘要:幾年前,行業(yè)預(yù)測(cè)分析人員表示,一旦企業(yè)決定了他們的云計(jì)算戰(zhàn)略,他們將會(huì)首先構(gòu)建私有云,并在以后根據(jù)需要添加公共云服務(wù)。如果要在本地實(shí)施容器或作為云計(jì)算部署的一部分實(shí)施容器,則需要確保其工作負(fù)載是安全的。幾年前,行業(yè)預(yù)測(cè)分析人員表示,一旦企業(yè)決定了他們的云計(jì)算IT戰(zhàn)略,他們將會(huì)首先構(gòu)建私有云,并在以后根據(jù)需要添加公共云服務(wù)。但這種事情并沒(méi)有發(fā)生。事實(shí)證明,采用云計(jì)算可以盡快讓組織的董事會(huì)分配資...

    MarvinZhang 評(píng)論0 收藏0
  • Web 應(yīng)用安全性: 使用這些 HTTP 頭保護(hù) Web 應(yīng)用

    摘要:綜上所述,認(rèn)為沒(méi)有提供的保護(hù),用戶會(huì)過(guò)得更好安全研究人員并不完全反對(duì)這一決定。內(nèi)容安全策略是一個(gè)額外的安全層,用于檢測(cè)并削弱某些特定類型的攻擊,包括跨站腳本和數(shù)據(jù)注入攻擊等。 這是關(guān)于web安全性系列文章的第 三 篇,其它的可點(diǎn)擊以下查看: Web 應(yīng)用安全性: 瀏覽器是如何工作的 Web 應(yīng)用安全性: HTTP簡(jiǎn)介 目前,瀏覽器已經(jīng)實(shí)現(xiàn)了大量與安全相關(guān)的頭文件,使攻擊者更難利用漏...

    spademan 評(píng)論0 收藏0
  • 別讓安全問(wèn)題拖慢了 DevOps!

    摘要:文件完整性監(jiān)測(cè)持續(xù)監(jiān)控您的云服務(wù)器,保護(hù)重要的系統(tǒng)二進(jìn)制文件和配置文件不會(huì)受到未經(jīng)授權(quán)的或惡意的變更。首先會(huì)記錄下云服務(wù)器系統(tǒng)的清潔狀態(tài),作為基準(zhǔn)。您可以通過(guò)一個(gè)在線管理控制臺(tái),監(jiān)控所有的云服務(wù)器。 DEVSECOPS 所面臨的挑戰(zhàn) 敏捷開發(fā)和 DevOps 方法的出現(xiàn)使軟件開發(fā)的速度與質(zhì)量都有所提升,但它們不經(jīng)意地也為安全機(jī)構(gòu)增壓不少。從前的安全策略是基于靜態(tài)數(shù)據(jù)的,而在產(chǎn)品上線前才...

    forsigner 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<