電腦報在線】絕大多數投資者只關心P2P理財網站的回報是不是高、資金安全能不能得到保障,極少會有人注意P2P理財網站的有沒有安全隱患,會不會給自己帶來潛在的安全威脅。可P2P理財網站的安全隱患一直層出不窮,一年因為黑客事件而關停的平臺超過100家。這不,最近又有一個P2P理財網站爆出奇葩漏洞了……
技術分析
白帽子 牛小帥:無意中看到某P2P理財網站的廣告,就順手走了一個安全監測。注冊一個賬號后,直接定位到找回密碼頁面http://www.***n***u.com/member/common/lookforpwd.html,頁面看著簡潔,實際存在漏洞——在這里動用抓包類黑客工具,就可以看到賬號和密碼,reg_phone后面的數字就是賬號,checkcode后面的數字就是密碼,通過這個方法就可以竄改任意用戶的密碼。
最奇葩的,驗證碼是擺設,無論對錯都可以竄改,這就意味著只需要注冊過的用戶的密碼全部都可以竄改。
無論驗證碼對錯都可以修改
讀者點評
@雪中帶刀行:對了,的確有P2P理財網站以漏洞的名義敲詐,還有被流量攻擊的,我記得以前人人貸就遭過,才宣布獲得1.3億美元的投資,兩小時不到就被黑客盯上了,一口氣發動了7GB的流量攻擊,導致我們訪問人人貸的都困難。
@蒼山獨行:這個方法可以看到用戶的賬戶余額,但無法直接盜取錢財,怕就怕損人不利己的黑客亂買理財產品,那就悲劇了。
篇文章JavaScript基礎——你真的清楚JavaScript是什么嗎?,我們明白了JavaScript是一個單線程、非阻塞、異步、解釋性語言,清楚了什么是單線程、進程、阻塞、調用堆棧、異步回調、任務循環等感念,沒看的或者不清楚的建議點擊《JavaScript基礎——你真的清楚JavaScript是什么嗎?再看一遍,只有理解了,才能輕松閱讀理解本篇文章內容。
什么是callback?
JavaScript 是單線程工作,這意味著兩段腳本不能同時運行,而是必須一個接一個地運行。我們人類是多線程工作。您可以使用多個手指打字,可以一邊開車一邊與人交談。唯一一個會妨礙我們的是打噴嚏,因為當我們打噴嚏的時候,所有當前進行的活動都必須暫停。這真是非常討厭,尤其是當您在開車并想與人交談時。您可不想編寫像打噴嚏似的代碼。JavaScript由于單線程限制,防止阻塞,只能通過異步函數的調用方式,把需要延遲處理的事件放入事件循環隊列。到目前為止,回調是編寫和處理JavaScript程序異步邏輯的最常用方式。說了這么多,既然回調這么重要,到底什么是回調(callback)呢?
簡單的定義:回調就是一個在另外一個函數執行完后要執行的函數
復雜的定義:在JavaScript中,函數是對象。因此函數可以將函數作為參數,并且可以由其他函數進行返回。執行此操作的函數稱為高階函數。任何作為參數傳遞的函數都稱為回調函數。
為什么需要回調?
開篇已經介紹了JavaScript是單線程的,需要通回調函數處理異步相關的邏輯,理論還是過于生硬,我們還是來看段代碼吧:
function first(){ console.log(1); } function second(){ console.log(2); } first(); second();
正如你所料,先執行first函數,再執行second函數,控制臺將輸出以下內容:
1 2
目前看來沒什么問題,如果first()函數中含有某種無法立即執行的函數呢?例如,我們必須發送請求然后等待結果響應的API請求?為了模擬API請求,我們可以使用setTimeout函數模擬。我們將函數延遲500毫秒來模擬請求,我們更改后代碼如下:
function first(){ // Simulate a code delay setTimeout( function(){ console.log(1); }, 500 ); } function second(){ console.log(2); } first(); second();
我們將 console.log(1) 延遲500毫秒輸出,這段代碼會怎么輸出呢?
2 1
我們希望的順序先執行first,再執行second,但是由于JavaScript是異步的,所有的延遲處理都要放入循環隊列里,因此事與愿違,不能按照我們的希望順序輸出。如果希望這段代碼按照我們的意愿輸出,我們可以使用回調函數,確保某些代碼執行完了,在循序執行另外一段代碼。
創建回調
說了這么多,讓我們創建一個簡單的回調!
我們打開編輯器,先輸入如下代碼:
function doHomework(subject) { alert(`Starting my ${subject} homework.`); }
上面我們創建了doHomeWork的函數,我們接受一個變量,通過控制臺調用,將得到下面的提示:
doHomework('math'); // Alerts: Starting my math homework.
接著,我們開始添加回調,在doHomework函數中添加一個參數callback,然后在第二個參數中回調我們定義的函數。代碼如下:
function doHomework(subject, callback) { alert(`Starting my ${subject} homework.`); callback(); } doHomework('math', function() { alert('Finished my homework'); });
正如你希望的,我們在控制臺里運行上述代碼,將會受到兩個連續的alert,Starting my math homework,然后彈出 Finished my homework。
但是回調函數并不是非得在調用函數中定義,我們可以單獨定義,修改后的代碼如下:
function doHomework(subject, callback) { alert(`Starting my ${subject} homework.`); callback(); } function alertFinished(){ alert('Finished my homework'); } doHomework('math', alertFinished);
此示例的輸出結果和上段代碼的結果一致,我們實現了在doHomework函數中調用alertFinished,實現了函數作為參數進行傳遞,實現了回調函數的創建。
用回調寫一段真實業務場景的代碼!
例如我們有一個需求,用NodeJs實現從論壇帖子列表中顯示其中的一個帖子的信息及留言列表信息,代碼如下:
DB/posts.json(帖子列表數據)
[ { "id": "001", "title": "Greeting", "text": "Hello World", "author": "Jane Doe" }, { "id": "002", "title": "JavaScript 101", "text": "The fundamentals of programming.", "author": "Alberta Williams" }, { "id": "003", "title": "Async Programming", "text": "Callbacks, Promises and Async/Await.", "author": "Alberta Williams" } ]
DB/comments.json(評論列表)
[ { "id": "phx732", "postId": "003", "text": "I don't get this callback stuff." }, { "id": "avj9438", "postId": "003", "text": "This is really useful info." }, { "id": "gnk368", "postId": "001", "text": "This is a test comment." } ]
Index.js
const fs = require('fs'); const path = require('path'); const postsUrl = path.join(__dirname, 'db/posts.json'); const commentsUrl = path.join(__dirname, 'db/comments.json'); //return the data from our file function loadCollection(url, callback) { fs.readFile(url, 'utf8', function(error, data) { if (error) { console.log(error); } else { return callback(JSON.parse(data)); } }); } //return an object by id function getRecord(collection, id, callback) { var collectobj=collection.find(function(element){ return element.id == id; }); callback(collectobj); return collectobj; } //return an array of comments for a post function getCommentsByPost(comments, postId) { return comments.filter(function(comment){ return comment.postId == postId; }); } loadCollection(postsUrl, function(posts){ loadCollection(commentsUrl, function(comments){ getRecord(posts, "001", function(post){ const postComments = getCommentsByPost(comments, post.id); console.log(post); console.log(postComments); }); }); });
大家請注意,我們在loadCollection函數中我們沒有使用try/catch,使用的是if/else,因為catch無法從readFile方法中獲取錯誤。上述代碼還需要完善,我沒有包含任何錯誤處理。如果在任何步驟中發生錯誤,程序將無法繼續。
錯誤處理是很重要的事情,我們寫代碼時要嚴格對待,比如我們要編寫一個用戶登錄的功能。涉及從網頁表單里獲取用戶名和密碼,查詢我們的數據庫,確認用戶信息是否正確,驗證通過后,將用戶引導到用戶中心頁面。如果用戶名密碼格式不正確,用戶名密碼不正確,我們應該將錯誤信息返回給用戶,并引導用戶重新登錄。
總結
很好!我們一起把回調的內容學完了,理解了什么是回調,異步編程是我們的代碼中使用的一種方法,用于推遲事件以便以后執行。當您處理異步任務時,回調是一種解決方案,以便它們按順序執行。
如果我們有多個任務依賴于前幾個任務的結果,那我們就要使用多個嵌套回調,但是就會引發“回調地域”(過多的回調嵌套會使得代碼變得難以理解與維護),還好Promise解決了“回調地獄”的問題,讓我們以同步的方式編寫代碼,小編將會再下篇文章里進行詳細介紹,敬請期待!
更多精彩內容,請微信關注”前端達人”公眾號!
篇文章《JavaScript基礎——你真的了解JavaScript嗎?》,我們明白了JavaScript是一個單線程、非阻塞、異步、解釋性語言,清楚了什么是單線程、進程、阻塞、調用堆棧、異步回調、任務循環等概念,沒看的或者不清楚的建議點擊《JavaScript基礎——你真的了解JavaScript嗎?》再看一遍,只有理解了,才能輕松閱讀理解本篇文章內容。
JavaScript 是單線程工作,這意味著兩段腳本不能同時運行,而是必須一個接一個地運行。我們人類是多線程工作。您可以使用多個手指打字,可以一邊開車一邊與人交談。唯一一個會妨礙我們的是打噴嚏,因為當我們打噴嚏的時候,所有當前進行的活動都必須暫停。這真是非常討厭,尤其是當您在開車并想與人交談時。您可不想編寫像打噴嚏似的代碼。JavaScript由于單線程限制,防止阻塞,只能通過異步函數的調用方式,把需要延遲處理的事件放入事件循環隊列。到目前為止,回調是編寫和處理JavaScript程序異步邏輯的最常用方式。說了這么多,既然回調這么重要,到底什么是回調(callback)呢?
簡單的定義:回調就是一個在另外一個函數執行完后要執行的函數
復雜的定義:在JavaScript中,函數是對象。因此函數可以將函數作為參數,并且可以由其他函數進行返回。執行此操作的函數稱為高階函數。任何作為參數傳遞的函數都稱為回調函數。
開篇已經介紹了JavaScript是單線程的,需要通回調函數處理異步相關的邏輯,理論還是過于生硬,我們還是來看段代碼吧:
function first(){ console.log(1);} function second(){ console.log(2);} first(); second();
正如你所料,先執行first函數,再執行second函數,控制臺將輸出以下內容:
1 2
目前看來沒什么問題,如果first()函數中含有某種無法立即執行的函數呢?例如,我們必須發送請求然后等待結果響應的API請求?為了模擬API請求,我們可以使用setTimeout函數模擬。我們將函數延遲500毫秒來模擬請求,我們更改后代碼如下:
function first(){ // Simulate a code delay setTimeout( function(){ console.log(1); }, 500 ); } function second(){ console.log(2);} first(); second();
我們將 console.log(1) 延遲500毫秒輸出,這段代碼會怎么輸出呢?
2 1
我們希望的順序先執行first,再執行second,但是由于JavaScript是異步的,所有的延遲處理都要放入循環隊列里,因此事與愿違,不能按照我們的希望順序輸出。如果希望這段代碼按照我們的意愿輸出,我們可以使用回調函數,確保某些代碼執行完了,再執行另外一段代碼。
說了這么多,讓我們創建一個簡單的回調!
我們打開編輯器,先輸入如下代碼:
function doHomework(subject) { alert(`Starting my ${subject} homework.`); }
上面我們創建了doHomeWork的函數,我們接受一個變量,通過控制臺調用,將得到下面的提示:
doHomework('math'); // Alerts: Starting my math homework.
接著,我們開始添加回調,在doHomework函數中添加一個參數callback,然后在第二個參數中回調我們定義的函數。代碼如下:
function doHomework(subject, callback) { alert(`Starting my ${subject} homework.`); callback(); } doHomework('math', function() { alert('Finished my homework'); });
正如你希望的,我們在控制臺里運行上述代碼,將會受到兩個連續的alert,Starting my math homework,然后彈出 Finished my homework。
但是回調函數并不是非得在調用函數中定義,我們可以單獨定義,修改后的代碼如下:
function doHomework(subject, callback) { alert(`Starting my ${subject} homework.`); callback(); } function alertFinished(){ alert('Finished my homework'); } doHomework('math', alertFinished);
此示例的輸出結果和上段代碼的結果一致,我們實現了在doHomework函數中調用alertFinished,實現了函數作為參數進行傳遞,實現了回調函數的創建。
例如我們有一個需求,用NodeJs實現從論壇帖子列表數據中顯示其中的一個帖子的信息及留言列表信息,代碼如下:
DB/posts.json(帖子列表數據)
[ { "id": "001", "title": "Greeting", "text": "Hello World", "author": "Jane Doe" }, { "id": "002", "title": "JavaScript 101", "text": "The fundamentals of programming.", "author": "Alberta Williams" }, { "id": "003", "title": "Async Programming", "text": "Callbacks, Promises and Async/Await.", "author": "Alberta Williams" } ]
DB/comments.json(評論列表)
[ { "id": "phx732", "postId": "003", "text": "I don't get this callback stuff." }, { "id": "avj9438", "postId": "003", "text": "This is really useful info." }, { "id": "gnk368", "postId": "001", "text": "This is a test comment." } ]
Index.js
大家請注意,在loadCollection函數中小編沒有使用try/catch捕捉異常,使用的是if/else,因為catch無法從readFile方法中獲取異常。上述代碼還需要完善,我沒有包含任何錯誤處理。如果在任何步驟中發生錯誤,程序將無法繼續。
錯誤處理是很重要的事情,我們寫代碼時要認證嚴格對待,比如我們要編寫一個用戶登錄的功能。涉及從網頁表單里獲取用戶名和密碼,查詢我們的數據庫,確認用戶信息是否正確,驗證通過后,將用戶引導到用戶中心頁面。如果用戶名密碼格式不正確,用戶名密碼不正確,我們應該將錯誤信息返回給用戶,并引導用戶重新登錄。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。