我也是很頭疼,我這個小破網站竟然有人攻擊。還特麼的連續攻擊。原本吧小網站我以爲就是本身寫寫博客,而後你們給我評論下。互幫互助,團結友愛。結果吧,我被教育了。挺慘痛的回憶。前端
而後就是我的站長的流量問題。java
這個很重要,就是,必定要服務端渲染。node
沒有別的緣由,你的網站若是是面向搜索引擎的你必須是服務端渲染。否則是無法被很好的搜索,提高排名的。redis
我我的網站比較隱私,就沒搞那些東西了。不過我下一次必需要嘗試下服務端渲染,否則目前爲止經驗尚淺啊。數據庫
這裏說的流量問題和搜索之類沒有什麼關係,就是單純的記住,別把圖片放上去。太吃流量了。你只是個小破站,就別搞那麼多了。後端
我爲了圖片訪問速度和服務器資源節省,把圖片放在了oss存儲上面,可是我想說。仍是很貴的。api
我給你們算一筆賬瀏覽器
目前服務器(1核1G1M)是aliyun的,三年300,很便宜是吧,可是這是搞特價,正常一年須要一千。緩存
若是你的網站開發的時候優化作的還能夠,那麼首屏流量能控制在1M左右。這樣其實很快。bash
可是主要是圖片這塊。你若是把圖片放本身服務器,那麼帶寬就不能很低,否則卡死。
若是放oss,那麼流量是按訪問量計算的。具體好像是1G2毛,總之挺貴的。你要是圖片不少,注意,隨便頁面切換,刷新單人就能給你刷走上百流量。人數稍微多點……,以前知道一個公司。半年,流量費用20萬(主要用於視頻監控)。
因此我的博主們,本身的小破站圖片少放。
圖片最好是作好防盜鏈。否則流量也會很痛苦。
這裏我先copy下阿里在eggjs方面的防護,主要你們就是遇到這些了。
我此次遇到的攻擊是CSRF方面的攻擊。
後端:記錄下每一個接口每次調用的的記錄。
前端:記錄下每一個路由的變化以後的訪問記錄
這兩個是很簡單的記錄方式,可是能讓你最直觀的感覺到,網站訪問的量是多少。還有就是監控你的網站是否惡意調用接口,惡意訪問等等。很直觀,很用好。
自己我是沒有增長該項功能的。可是通過慘痛教訓以後,我痛定思痛。增長了對應的記錄。
經過接口調用的分析,得出對方是軟件刷新頁面不斷惡意給我發送評論
這裏我貼下我中間件的代碼,上面的說實在沒什麼意義,隨便寫一下中間件,數據庫記錄下數據便可。很簡單。
這裏我增長了redis,若是用數據庫性能不合適,而且不須要這麼笨重。緩存比較不錯。至於爲何不存在全局變量。這個我得和你們科普下,不論是nodejs仍是java等後端。是存在多線程或者多進程的。那麼一旦負載的時候,系統切換另外一個進程,那麼就訪問不到數據了。
下面是限制訪問的中間件代碼。
'use strict';
module.exports = (options, app) => {
return async function(ctx, next) {
try {
const ip = ctx.request.header['x-forwarded-for'];
const req_url = ctx.request.url;
// 獲得最終url地址
const url = req_url.indexOf('?') === -1 ?
req_url :
req_url.substring(0, req_url.indexOf('?'));
// 存儲當前接口訪問信息,後續有統計
ctx.service.interface.apiVisit.add({
ip,
url,
});
// 當前時間
const time = new Date().getTime();
// 獲取這個用戶該接口上次調用時間
const usr_api = await app.redis.get(ip + url);
// 攔截的接口
const intercept_api = options.api[url];
// 參數獲取完畢,設置最新參數
// 設置接口最新調用時間
await app.redis.set(ip + url, new Date().getTime());
if (intercept_api) {
if (time - usr_api > 5000) {
await next();
} else {
ctx.body = ctx.helper.result('', -1, '限制訪問' + intercept_api / 1000 + '秒', 0);
}
} else {
await next();
}
} catch (e) {
ctx.logger.warn(e);
}
};
};複製代碼
配置部分config.js
// 給'interfaceRestriction'傳入參數
config.interfaceRestriction = {
// api封禁
api: {
'/dream-admin/noauth/blog/discuss/add': 1000 * 8,
},
// ip封禁,
ip: [
// '127.0.0.1',
],
};複製代碼
上面的ip封禁沒有寫。暫時用不到
功能還能夠拓展,好比限制ip,限制某個接口的訪問頻率等等。
上面失敗的主要緣由在於,ip其實是能夠僞造的。並且ip僞形成本很低。因此,你經過ip來限制對方這種爬蟲的惡意攻擊效果並很差,這隻能防止那些惡意灌水的人罷了。爬蟲分分鐘幾十上百萬給你攻擊過來,效果很差。
後來我在想怎麼才合適。
自己攻擊屬於csrf,可是經過csrf的方式來防護對方沒有用。由於csrf自己是一種基於口令的方式。經過爬蟲工具,很容易能夠竊取你的口令。
最後我就想着實在沒什麼好辦法就增長驗證碼了。
最後,用了 svg-captcha包。
下面是使用方式,比較簡單:
controller代碼:
const { ctx, app } = this;
try {
// 生成算數驗證碼
const verify = svgCaptcha.createMathExpr({
size: 4,
ignoreChars: '0o1i',
noise: 5,
color: true,
background: '#7E7D78',
});
// 以ip爲單位存儲驗證碼
const ip = ctx.request.header['x-forwarded-for'];
await app.redis.set(ip, verify.text);
ctx.response.type = 'image/svg+xml'; // 知道你個返回的類型
ctx.body = verify.data;
} catch (e) {
ctx.body = ctx.helper.result('', -1, e);
}複製代碼
最後在建立評論的地方,增長驗證便可。
一、全部的一切都是爲了增長對方破譯的難度
二、不要對外開放建立數據的接口(萬惡之源)
三、作好數據監控,防範於未然。而且讓你能儘快的發現問題
四、若是你對外開放接口了,那麼請作好防小人的準備。(驗證碼真的是一個好東西)
五、全部驗證碼不如手機驗證碼來的可靠。
其實最後下來仍是比較老套的一些東西。只是吧,好不容易勝利了。得發發動態。