主頁 > 企業開發 > 記錄--通過手寫,分析axios核心原理

記錄--通過手寫,分析axios核心原理

2022-09-20 08:21:40 企業開發

這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

一、axios簡介

axios是什么?

Axios 是一個基于 promise 的 HTTP 庫,可以用在瀏覽器和 node.js 中,

axios有什么特性?(不得不說面試被問到幾次)

  • 從瀏覽器中創建 XMLHttpRequests
  • 從 node.js 創建 http 請求
  • 支持 Promise API
  • 攔截請求和回應
  • 轉換請求資料和回應資料
  • 取消請求
  • 自動轉換 JSON 資料
  • 客戶端支持防御 XSRF

實際上,axios可以用在瀏覽器和 node.js 中是因為,它會自動判斷當前環境是什么,如果是瀏覽器,就會基于XMLHttpRequests實作axios,如果是node.js環境,就會基于node內置核心模塊http實作axios

簡單來說,axios的基本原理就是

  1. axios還是屬于 XMLHttpRequest, 因此需要實作一個ajax,或者基于http
  2. 還需要一個promise物件來對結果進行處理

有什么不理解的或者是建議歡迎評論提出.專案已經放到 github:github.com/Sunny-lucki…

二、基本使用方式

axios基本使用方式主要有

  1. axios(config)
  2. axios.method(url, data , config)
// index.html檔案
<html>
<script type="text/javascript" src="https://www.cnblogs.com/smileZAZ/archive/2022/09/19/axios"></script>
<body>
<button >點我發送請求</button>
<script>
    document.querySelector('.btn').onclick = function() {
        // 分別使用以下方法呼叫,查看myaxios的效果
        axios.post('/postAxios', {
          name: '小美post'
        }).then(res => {
          console.log('postAxios 成功回應', res);
        })

        axios({
          method: 'post',
          url: '/getAxios'
        }).then(res => {
          console.log('getAxios 成功回應', res);
        })
    }
</script>
</body>
</html>
</html>

三、實作axios和axios.method

從axios(config)的使用上可以看出匯出的axios是一個方法,從axios.method(url, data , config)的使用可以看出匯出的axios上或者原型上掛有get,post等方法

實際上匯出的axios就是一個Axios類中的一個方法,

如代碼所以,核心代碼是request,我們把request匯出,就可以使用axios(config)這種形式來呼叫axios了,

class Axios {
    constructor() {

    }

    request(config) {
        return new Promise(resolve => {
            const {url = '', method = 'get', data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{}} = config;
            // 發送ajax請求
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            }
            xhr.send(data);
        })
    }
}
怎么匯出呢?十分簡單,new Axios,獲得axios實體,再獲得實體上的request方法就好了,
// 最侄訓出axios的方法,即實體的request方法
function CreateAxiosFn() {
    let axios = new Axios();
    let req = axios.request.bind(axios);
    return req;
}

// 得到最后的全域變數axios
let axios = CreateAxiosFn();

點擊查看此時的myAxios.js

現在axios實際上就是request方法,

你可能會很疑惑,因為我當初看原始碼的時候也很疑惑:干嘛不直接寫個request方法,然后匯出呢?非得這樣繞這么大的彎子,別急,后面慢慢就會講到,

現在一個簡單的axios就完成了,我們來引入myAxios.js檔案并測驗一下可以使用不?

簡單的搭建服務器:

//server.js
var express = require('express');
var app = express();

//設定允許跨域訪問該服務.
app.all('*', function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Content-Type');
    res.header('Access-Control-Allow-Methods', '*');
    res.header('Content-Type', 'application/json;charset=utf-8');
    next();
});

app.get('/getTest', function(request, response){
    data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{'FrontEnd':'前端',
        'Sunny':'陽光'
    };
    response.json(data);
});
var server = app.listen(5000, function(){
    console.log("服務器啟動");
});

index.html

//index.html
<script type="text/javascript" src="https://www.cnblogs.com/smileZAZ/archive/2022/09/19/myAxios.js"></script>

<body>
<button >點我發送請求</button>
<script>
    document.querySelector('.btn').onclick = function() {
        // 分別使用以下方法呼叫,查看myaxios的效果
        axios({
          method: 'get',
          url: 'http://localhost:5000/getTest'
        }).then(res => {
          console.log('getAxios 成功回應', res);
        })
    }
</script>
</body>

點擊按鈕,看看是否能成功獲得資料,

可喜可賀,成功,

現在我們來實作下axios.method()的形式,

思路,我們可以再Axios.prototype添加這些方法,而這些方法內部呼叫request方法即可,如代碼所示:

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
    Axios.prototype[met] = function() {
        console.log('執行'+met+'方法');
        // 處理單個方法
        if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個引數(url[, config])
            return this.request({
                method: met,
                url: arguments[0],
                ...arguments[1] || {}
            })
        } else { // 3個引數(url[,data[,config]])
            return this.request({
                method: met,
                url: arguments[0],
                data: arguments[1] || {},
                ...arguments[2] || {}
            })
        }

    }
})

我們通過遍歷methodsArr陣列,依次在Axios.prototype添加對應的方法,注意的是'get', 'delete', 'head', 'options'這些方法只接受兩個引數,而其他的可接受三個引數,想一下也知道,get不把引數放body的,

但是,你有沒有發現,我們只是在Axios的prototype上添加對應的方法,我們匯出去的可是request方法啊,那怎么辦? 簡單,把Axios.prototype上的方法搬運到request上即可,

我們先來實作一個工具方法,實作將b的方法混入a;

const utils = {
  extend(a,b, context) {
    for(let key in b) {
      if (b.hasOwnProperty(key)) {
        if (typeof b[key] === 'function') {
          a[key] = b[key].bind(context);
        } else {
          a[key] = b[key]
        }
      }
      
    }
  }
}

然后我們就可以利用這個方法將Axios.prototype上的方法搬運到request上啦,

我們修改一下之前的CreateAxiosFn方法即可

function CreateAxiosFn() {
  let axios = new Axios();
  
  let req = axios.request.bind(axios);
  增加代碼
  utils.extend(req, Axios.prototype, axios)
  
  return req;
}

點擊查看此時的myAxios.js

現在來測驗一下能不能使用axios.get()這種形式呼叫axios,

<body>
<button >點我發送請求</button>
<script>
    document.querySelector('.btn').onclick = function() {

        axios.get('http://localhost:5000/getTest')
            .then(res => {
                 console.log('getAxios 成功回應', res);
            })

    }
</script>
</body>

害,又是意料之中成功,

再完成下一個功能之前,先給上目前myAxios.js的完整代碼

class Axios {
    constructor() {

    }

    request(config) {
        return new Promise(resolve => {
            const {url = '', method = 'get', data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{}} = config;
            // 發送ajax請求
            console.log(config);
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            }
            xhr.send(data);
        })
    }
}

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
    Axios.prototype[met] = function() {
        console.log('執行'+met+'方法');
        // 處理單個方法
        if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個引數(url[, config])
            return this.request({
                method: met,
                url: arguments[0],
                ...arguments[1] || {}
            })
        } else { // 3個引數(url[,data[,config]])
            return this.request({
                method: met,
                url: arguments[0],
                data: arguments[1] || {},
                ...arguments[2] || {}
            })
        }

    }
})


// 工具方法,實作b的方法或屬性混入a;
// 方法也要混入進去
const utils = {
  extend(a,b, context) {
    for(let key in b) {
      if (b.hasOwnProperty(key)) {
        if (typeof b[key] === 'function') {
          a[key] = b[key].bind(context);
        } else {
          a[key] = b[key]
        }
      }
      
    }
  }
}


// 最侄訓出axios的方法-》即實體的request方法
function CreateAxiosFn() {
    let axios = new Axios();

    let req = axios.request.bind(axios);
    // 混入方法, 處理axios的request方法,使之擁有get,post...方法
    utils.extend(req, Axios.prototype, axios)
    return req;
}

// 得到最后的全域變數axios
let axios = CreateAxiosFn();

四、請求和回應攔截器

我們先看下攔截器的使用

// 添加請求攔截器
axios.interceptors.request.use(function (config) {
    // 在發送請求之前做些什么
    return config;
  }, function (error) {
    // 對請求錯誤做些什么
    return Promise.reject(error);
  });

// 添加回應攔截器
axios.interceptors.response.use(function (response) {
    // 對回應資料做點什么
    return response;
  }, function (error) {
    // 對回應錯誤做點什么
    return Promise.reject(error);
  });

攔截器是什么意思呢?其實就是在我們發送一個請求的時候會先執行請求攔截器的代碼,然后再真正地執行我們發送的請求,這個程序會對config,也就是我們發送請求時傳送的引數進行一些操作,

而當接收回應的時候,會先執行回應攔截器的代碼,然后再把回應的資料回傳來,這個程序會對response,也就是回應的資料進行一系列操作,

怎么實作呢?需要明確的是攔截器也是一個類,管理回應和請求,因此我們先實作攔截器

class InterceptorsManage {
  constructor() {
    this.handlers = [];
  }

  use(fullfield, rejected) {
    this.handlers.push({
      fullfield,
      rejected
    })
  }
}

我們是用這個陳述句axios.interceptors.response.useaxios.interceptors.request.use,來觸發攔截器執行use方法的,

說明axios上有一個回應攔截器和一個請求攔截器,那怎么實作Axios呢?看代碼

class Axios {
    constructor() {
        新增代碼
        this.interceptors = {
            request: new InterceptorsManage,
            response: new InterceptorsManage
        }
    }

    request(config) {
        return new Promise(resolve => {
            const {url = '', method = 'get', data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{}} = config;
            // 發送ajax請求
            console.log(config);
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            };
            xhr.send(data);
        })
    }
}

可見,axios實體上有一個物件interceptors,這個物件有兩個攔截器,一個用來處理請求,一個用來處理回應,

所以,我們執行陳述句axios.interceptors.response.useaxios.interceptors.request.use的時候,實作獲取axios實體上的interceptors物件,然后再獲取response或request攔截器,再執行對應的攔截器的use方法,

而執行use方法,會把我們傳入的回呼函式push到攔截器的handlers陣列里,

到這里你有沒有發現一個問題,這個interceptors物件是Axios上的啊,我們匯出的是request方法啊(欸?好熟悉的問題,上面提到過哈哈哈~~~額),處理方法跟上面處理的方式一樣,都是把Axios上的方法和屬性搬到request過去,也就是遍歷Axios實體上的方法,得以將interceptors物件掛載到request上,

所以只要更改下CreateAxiosFn方法即可,

function CreateAxiosFn() {
  let axios = new Axios();
  
  let req = axios.request.bind(axios);
  // 混入方法, 處理axios的request方法,使之擁有get,post...方法
  utils.extend(req, Axios.prototype, axios)
  新增代碼
  utils.extend(req, axios)
  return req;
}

好了,現在request也有了interceptors物件,那么什么時候拿interceptors物件中的handler之前保存的回呼函式出來執行,

沒錯,就是我們發送請求的時候,會先獲取request攔截器的handlers的方法來執行,再執行我們發送的請求,然后獲取response攔截器的handlers的方法來執行,

因此,我們要修改之前所寫的request方法 之前是這樣的,

request(config) {
    return new Promise(resolve => {
        const {url = '', method = 'get', data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{}} = config;
        // 發送ajax請求
        console.log(config);
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.onload = function() {
            console.log(xhr.responseText)
            resolve(xhr.responseText);
        };
        xhr.send(data);
    })
}
但是現在request里不僅要執行發送ajax請求,還要執行攔截器handlers中的回呼函式,所以,最好下就是將執行ajax的請求封裝成一個方法
request(config) {
    this.sendAjax(config)
}
sendAjax(config){
    return new Promise(resolve => {
        const {url = '', method = 'get', data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{}} = config;
        // 發送ajax請求
        console.log(config);
        const xhr = new XMLHttpRequest();
        xhr.open(method, url, true);
        xhr.onload = function() {
            console.log(xhr.responseText)
            resolve(xhr.responseText);
        };
        xhr.send(data);
    })
}
好了,現在我們要獲得handlers中的回呼
request(config) {
    // 攔截器和請求組裝佇列
    let chain = [this.sendAjax.bind(this), undefined] // 成對出現的,失敗回呼暫時不處理

    // 請求攔截
    this.interceptors.request.handlers.forEach(interceptor => {
        chain.unshift(interceptor.fullfield, interceptor.rejected)
    })

    // 回應攔截
    this.interceptors.response.handlers.forEach(interceptor => {
        chain.push(interceptor.fullfield, interceptor.rejected)
    })

    // 執行佇列,每次執行一對,并給promise賦最新的值
    let promise = Promise.resolve(config);
    while(chain.length > 0) {
        promise = promise.then(chain.shift(), chain.shift())
    }
    return promise;
}

我們先把sendAjax請求和undefined放進了chain陣列里,再把請求攔截器的handlers的成對回呼放到chain陣列頭部,再把回應攔截器的handlers的承兌回呼反倒chain陣列的尾部,

然后再 逐漸取數 chain陣列的成對回呼執行,

promise = promise.then(chain.shift(), chain.shift())

這一句,實際上就是不斷將config從上一個promise傳遞到下一個promise,期間可能回呼config做出一些修改,什么意思?我們結合一個例子來講解一下

首先攔截器是這樣使用的

// 添加請求攔截器
axios.interceptors.request.use(function (config) {
    // 在發送請求之前做些什么
    return config;
  }, function (error) {
    // 對請求錯誤做些什么
    return Promise.reject(error);
  });

// 添加回應攔截器
axios.interceptors.response.use(function (response) {
    // 對回應資料做點什么
    return response;
  }, function (error) {
    // 對回應錯誤做點什么
    return Promise.reject(error);
  });

然后執行request的時候,chain陣列的資料是這樣的

chain = [
  function (config) {
    // 在發送請求之前做些什么
    return config;
  }, 
  
  function (error) {
    // 對請求錯誤做些什么
    return Promise.reject(error);
  }
  this.sendAjax.bind(this), 
  
  undefined,
  
  function (response) {
    // 對回應資料做點什么
    return response;
  }, 
  function (error) {
    // 對回應錯誤做點什么
    return Promise.reject(error);
  }
]

首先

執行第一次promise.then(chain.shift(), chain.shift()),即

promise.then(
  function (config) {
    // 在發送請求之前做些什么
    return config;
  }, 
  
  function (error) {
    // 對請求錯誤做些什么
    return Promise.reject(error);
  }
)

一般情況,promise是resolved狀態,是執行成功回呼的,也就是執行

function (config) {
    // 在發送請求之前做些什么
    return config;
  }, 

而promise.then是要回傳一個新的promise物件的,

為了區分,在這里,我會把這個新的promise物件叫做第一個新的promise物件 這個第一個新的promise物件會把

function (config) {
    // 在發送請求之前做些什么
    return config;
  }, 

的執行結果傳入resolve函式中

resolve(config)

使得這個回傳的第一個新的promise物件的狀態為resovled,而且第一個新的promise物件的data為config,

這里需要對Promise的原理足夠理解,所以我前一篇文章寫的是手寫Promise核心原理,再也不怕面試官問我Promise原理,你可以去看看 接下來,再執行

promise.then(
  sendAjax(config)
  ,
  undefined
)

注意:這里的promise是 上面提到的第一個新的promise物件,

而promise.then這個的執行又會回傳第二個新的promise物件,

因為這里promise.then中的promise也就是第一個新的promise物件的狀態是resolved的,所以會執行sendAjax(),而且會取出第一個新的promise物件的data 作為config轉入sendAjax(),

當sendAjax執行完,就會回傳一個response,這個response就會保存在第二個新的promise物件的data中,

接下來,再執行

promise.then(
  function (response) {
    // 對回應資料做點什么
    return response;
  }, 
  function (error) {
    // 對回應錯誤做點什么
    return Promise.reject(error);
  }
)

同樣,會把第二個新的promise物件的data取出來作為response引數傳入

function (response) {
    // 對回應資料做點什么
    return response;
  }, 

飯后回傳一個promise物件,這個promise物件的data保存了這個函式的執行結果,也就是回傳值response,

然后通過return promise;

把這個promise回傳了,咦?是怎么取出promise的data的,我們看看我們平常事怎么獲得回應資料的

axios.get('http://localhost:5000/getTest')
    .then(res => {
         console.log('getAxios 成功回應', res);
    })

在then里接收回應資料,所以原理跟上面一樣,將回傳的promise的data作為res引數了,

現在看看我們的myAxios完整代碼吧,好有個全面的了解

class InterceptorsManage {
    constructor() {
        this.handlers = [];
    }

    use(fullfield, rejected) {
        this.handlers.push({
            fullfield,
            rejected
        })
    }
}

class Axios {
    constructor() {
        this.interceptors = {
            request: new InterceptorsManage,
            response: new InterceptorsManage
        }
    }

    request(config) {
        // 攔截器和請求組裝佇列
        let chain = [this.sendAjax.bind(this), undefined] // 成對出現的,失敗回呼暫時不處理

        // 請求攔截
        this.interceptors.request.handlers.forEach(interceptor => {
            chain.unshift(interceptor.fullfield, interceptor.rejected)
        })

        // 回應攔截
        this.interceptors.response.handlers.forEach(interceptor => {
            chain.push(interceptor.fullfield, interceptor.rejected)
        })

        // 執行佇列,每次執行一對,并給promise賦最新的值
        let promise = Promise.resolve(config);
        while(chain.length > 0) {
            promise = promise.then(chain.shift(), chain.shift())
        }
        return promise;
    }
    sendAjax(){
        return new Promise(resolve => {
            const {url = '', method = 'get', data = https://www.cnblogs.com/smileZAZ/archive/2022/09/19/{}} = config;
            // 發送ajax請求
            console.log(config);
            const xhr = new XMLHttpRequest();
            xhr.open(method, url, true);
            xhr.onload = function() {
                console.log(xhr.responseText)
                resolve(xhr.responseText);
            };
            xhr.send(data);
        })
    }
}

// 定義get,post...方法,掛在到Axios原型上
const methodsArr = ['get', 'delete', 'head', 'options', 'put', 'patch', 'post'];
methodsArr.forEach(met => {
    Axios.prototype[met] = function() {
        console.log('執行'+met+'方法');
        // 處理單個方法
        if (['get', 'delete', 'head', 'options'].includes(met)) { // 2個引數(url[, config])
            return this.request({
                method: met,
                url: arguments[0],
                ...arguments[1] || {}
            })
        } else { // 3個引數(url[,data[,config]])
            return this.request({
                method: met,
                url: arguments[0],
                data: arguments[1] || {},
                ...arguments[2] || {}
            })
        }

    }
})


// 工具方法,實作b的方法混入a;
// 方法也要混入進去
const utils = {
    extend(a,b, context) {
        for(let key in b) {
            if (b.hasOwnProperty(key)) {
                if (typeof b[key] === 'function') {
                    a[key] = b[key].bind(context);
                } else {
                    a[key] = b[key]
                }
            }

        }
    }
}


// 最侄訓出axios的方法-》即實體的request方法
function CreateAxiosFn() {
    let axios = new Axios();

    let req = axios.request.bind(axios);
    // 混入方法, 處理axios的request方法,使之擁有get,post...方法
    utils.extend(req, Axios.prototype, axios)
    return req;
}

// 得到最后的全域變數axios
let axios = CreateAxiosFn();
來測驗下攔截器功能是否正常
<script type="text/javascript" src="https://www.cnblogs.com/smileZAZ/archive/2022/09/19/myAxios.js"></script>

<body>
<button >點我發送請求</button>
<script>
    // 添加請求攔截器
    axios.interceptors.request.use(function (config) {
        // 在發送請求之前做些什么
        config.method = "get";
        console.log("被我請求攔截器攔截了,哈哈:",config);
        return config;
    }, function (error) {
        // 對請求錯誤做些什么
        return Promise.reject(error);
    });

    // 添加回應攔截器
    axios.interceptors.response.use(function (response) {
        // 對回應資料做點什么
        console.log("被我回應攔截攔截了,哈哈 ");
        response = {message:"回應資料被我替換了,啊哈哈哈"}
        return response;
    }, function (error) {
        // 對回應錯誤做點什么
        console.log("錯了嗎");
        return Promise.reject(error);
    });
    document.querySelector('.btn').onclick = function() {
        // 分別使用以下方法呼叫,查看myaxios的效果
        axios({
          url: 'http://localhost:5000/getTest'
        }).then(res => {
          console.log('response', res);
        })
    }
</script>
</body>

攔截成功!!!!!

本文轉載于:

https://juejin.cn/post/6856706569263677447

如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/509145.html

標籤:其他

上一篇:深入淺出 JavaScript 中的 this

下一篇:[通明境 · React架構]通俗地講React,優雅地理解React

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more