前端XSS相關整理

来源:https://www.cnblogs.com/imwtr/archive/2018/09/29/9721563.html
-Advertisement-
Play Games

前端安全方面,主要需要關註 XSS(跨站腳本攻擊 Cross-site scripting) 和 CSRF(跨站請求偽造 Cross-site request forgery) 當然了,也不是說要忽略其他安全問題:後端範疇、DNS劫持、HTTP劫持、加密解密、釣魚等 CSRF主要是借用已登錄用戶之手 ...


前端安全方面,主要需要關註 XSS(跨站腳本攻擊 Cross-site scripting) 和 CSRF(跨站請求偽造 Cross-site request forgery)

當然了,也不是說要忽略其他安全問題:後端範疇、DNS劫持、HTTP劫持、加密解密、釣魚等

CSRF主要是借用已登錄用戶之手發起“正常”的請求,防範措施主要就是對需要設置為Post的請求,判斷Referer以及token的一致性,本文不展開

相對來說,XSS的內容就非常龐大了,下麵就來整理一下一些XSS的知識點。比較匆忙,可能有點亂哈~

 

一、XSS

惡意攻擊者向頁面中註入可執行的JS代碼來實現XSS的攻擊。

如常見的

Payload:<script>alert(1)</script>
<div>[輸出]</div>
 
<div><script>alert(1)</script></div>

這個 Payload 可以從編輯區域而來

<input type="text" value="[輸入]" />

當然,輸入和輸出的位置還可以出現在其他地方,根據輸入輸位置的不同,可以形成不同類型的XSS,相應的防範措施也不同。

 

1.1 XSS的分類

一般來說,可以將XSS分為三類:反射型XSS、存儲型XSS、DOM-base 型XSS

1.1.1 反射型XSS

大多通過URL進行傳播,發請求時,XSS代碼出現在URL中,提交給服務端。服務端未進行處理或處理不當,返回的內容中也帶上了這段XSS代碼,最後瀏覽器執行XSS代碼

比如在 php的smarty模板中直接獲取url的參數值

Payload: <script>alert(1)</script>
http://local.abc.com/main/?r=abc/index&param=<script>alert(1)</script>
 
<div><{$smarty.get.param}></div>

X-XSS-Protection

新版Chrome和Safari中,已自動屏蔽了這種XSS,形如

這個屏蔽是由 XSS Auditor操作的,它由HTTP返回頭部進行控制,有四個可選值

X-XSS-Protection : 0    關閉瀏覽器的XSS防護機制
X-XSS-Protection : 1    刪除檢測到的惡意代碼(如果不指定,IE將預設使用這個)
X-XSS-Protection : 1; mode=block   如果檢測到惡意代碼,將不渲染頁面 (如果不指定,Chrome將預設使用這個)
X-XSS-Protection : 1; report=<reporting-uri> 刪除檢測到的惡意代碼,並通過report-uri發出一個警告。

前三個在IE和Chrome中有效,最後一個只在Chrome中有效

可以手動在設置請求頭看看變化

header('X-XSS-Protection: 1; mode=block');

建議配置為後兩個的結合,禁止頁面渲染併進行上報

header('X-XSS-Protection: 1; mode=block; report=www.xss.report');

不建議僅僅配置為1,因為它刪除惡意代碼的功能有時比較雞肋,可能會弄巧成拙。

另外,這個配置只能充當輔助作用,不能完全依賴,其也可能會產生一些問題

 

不過在Firefox中並未屏蔽

在IE中的XSS Filter也預設也開啟了屏蔽,也可手動關閉試試,或者通過HTTP頭部進行控制

 

1.1.2 存儲型XSS

提交的XSS代碼會存儲在伺服器端,服務端未進行處理或處理不當,每個人訪問相應頁面的時候,將會執行XSS代碼

如本文開始的第一個例子

1.1.3 DOM-base 型XSS

這個類型和反射型的有點類似,區別是它不需要服務端參與

比如在JS中直接獲取URL中的值

Payload: alert('xss')
http://local.abc.com/main/?r=abc/index#alert('xss')
 
<script>
    var hash = eval(location.hash.slice(1));
</script>

 

 

另外,有些攻擊方式的類型是單一的,有些是混合的。防範攻擊,不應僅根據類型來防範,而應根據輸入輸出的不同來應對。

在反射型和DOM-base型中,一般會通過設置一些有誘導性質的鏈接,用戶點擊鏈接後則觸發鏈接中的XSS

Content Security Policy(CSP)內容安全策略

為了防範XSS,CSP出現了。

CSP 的實質就是白名單制度,開發者明確告訴客戶端,哪些外部資源可以載入和執行,提供了這種白名單之後,實現和執行則由瀏覽器完成

通過一系列的自定義配置,可以在很大程度上防止惡意腳本的攻擊,建議進行配置。

不過策略比較新,在各瀏覽器也有一些相容性的問題。另外,似乎還是可以通過一些手段繞過的,這裡就不展開了

Cookie 配置

大多使用cookie來實現對用戶的認證。如果攻擊者拿到了這個認證cookie,就可以登錄了用戶的賬號了

XSS的主要目的是為了得到cookie,當然也不僅是為了獲取cookie

cookie安全註意點

Httponly:防止cookie被xss偷

https:防止cookie在網路中被偷

Secure:阻止cookie在非https下傳輸,很多全站https時會漏掉

Path :區分cookie的標識,安全上作用不大,和瀏覽器同源衝突

通過設置 cookie的幾個屬性,可以在一定程度上保障網站的安全

不過並沒有十全十美的東西,雖然攻擊門檻提高了,但HttpOnly在某些特定情況下還是能繞過的,道高一尺魔高一點一尺呀

 

1.2 執行JS代碼

XSS的目的一般是盜取cookie,一般需要通過JS 的 document.cookie來獲取這個值。

所以要先思考的是:在什麼地方可以執行JS相關的代碼

然後要思考的是:攻擊者能不能在這些地方構造出能夠執行的腳本

1.2.1  <script>標簽中

<script>alert(1);</script>

1.2.2 HTML中的某些事件

<img src="1" onerror="alert(1)" >
 
<input type="text" onfocus="alert(1)">
 
<span onmouseover="alert(1)"></span>

1.2.3  javascript: 偽協議

<a href="javascript:alert(1)">test</a>
<iframe src="javascript:alert(1)"></iframe>
 
 
location.href = 'javascript:alert(1)'

對於事件的執行觸發,是有機會防禦的,圍觀 這篇文章

1.2.4  base64編碼的  data: 偽協議

Payload: <script>alert('XSS')</script> ,它的base64編碼為PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">test</a>

1.2.5  css中的expression表達式

僅在IE8以下才支持expression,可以忽略這個了

<span style="color:1;zoom:expression(alert(1));"></span>

1.2.6 css中的src

很多文章都說到這個payload,然鵝並沒有生效,不知真假

根據一些討論,在css中是很難實現xss的

.abc {
    background: url(...)
} 

1.2.7 使用 eval、new Function、setTimeout 執行字元串時

setTimeout('alert(1)');
 
eval('alert(2)');
 
var f = new Function('alert(3)');
f();

 

 

1.3 編碼與解碼

防範XSS,比較通用的做法是:提交保存前對特殊字元進行過濾轉義,進行HTML實體的編碼

var escape = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
};

事實上,僅僅這樣做還是不夠的

那為什麼要進行HTML實體的編碼呢?

這涉及到瀏覽器的解析過程。

瀏覽器在解析HTML文檔期間,根據文檔中的內容,會經過 HTML解析、JS解析和URL解析幾個過程

 

首先瀏覽器接收到一個HTML文檔時,會觸發HTML解析器對HTML文檔進行詞法解析,這完成HTML解碼工作並創建DOM樹。

如果HTML文檔中存在JS的上下文環境,JavaScript解析器會介入對內聯腳本進行解析,完成JS的解碼工作。

如果瀏覽器遇到需要URL的上下文環境,URL解析器也會介入完成URL的解碼工作。

 URL解析器的解碼順序會根據URL所在位置不同,可能在JavaScript解析器之前或之後解析

1.3.1 HTML實體編碼

瀏覽器會對一些字元進行特殊識別處理,比如將 < > 識別為標簽的開始結束。

要想在HTML頁面中呈現出特殊字元,就需要用到對應的字元實體。比如在HTML解析過程中,如果要求輸出值為 < > ,那麼輸入值應該為其對應的實體 &lt; &gt;

 

字元實體以&開頭 + 預先定義的實體名稱,以分號結束,如“<”的實體名稱為&lt; 

或以&開頭 + #符號 以及字元的十進位數字,如”<”的實體編號為&#60;

或以&開頭 + #x符號 以及字元的十六進位數字,如”<”的實體編號為&#x3c;

字元都是有實體編號的但有些字元沒有實體名稱。

 

普通編碼與實體編碼的線上轉換

1.3.2 Javascript編碼

Unicode 是字元集,而 utf-8,utf-16,utf-32 是編碼規則

最常用的如“\uXXXX”這種寫法為Unicode轉義序列,表示一個字元,其中xxxx表示一個16進位數字

如”<” Unicode編碼為“\u003c”,不區分大小寫

普通編碼與Unicode轉義序列的線上轉換

Unicode字元集大全

1.3.3 URL編碼

%加字元的ASCII編碼對於的2位16進位數字,如”/”對應的URL編碼為%2f

轉換可以使用 JS 自帶的 encodeURIComponent 和 decodeURLComponent 方法來對特殊字元進行轉義,也可以對照ASCII表為每個字元進行轉換

1.3.4 編碼解碼分析

<span class="a<b">abc</span>
等價於
<span class="a&lt;b">abc</span>

上述代碼中

編碼順序:HTML編碼

解碼順序:HTML解碼

 

<a href="//www.baidu.com?a=1&b=2">abc</a>
等價於
<a href="//www.baidu.com?a=1%26b=2">abc</a>
等價於
<a href="//www.baidu.com?a=1&#37;&#50;&#54;b=2">abc</a>

上述代碼中

編碼順序:URL編碼 -> HTML編碼

解碼順序:HTML解碼 -> URL解碼

 

<a href="#" onclick="alert(1)">abc</a>
等價於
<a href="#" onclick="\u0061\u006c\u0065\u0072\u0074(1)">abc</a>
等價於
<a href="#" onclick="&#92;&#117;&#48;&#48;&#54;&#49;&#92;&#117;&#48;&#48;&#54;&#99;&#92;&#117;&#48;&#48;&#54;&#53;&#92;&#117;&#48;&#48;&#55;&#50;&#92;&#117;&#48;&#48;&#55;&#52;&#40;&#49;&#41;">abc</a>

上述代碼中

編碼順序:Javascript編碼 -> HTML編碼

解碼順序:HTML解碼 -> Javascript解碼

需要註意的是,在JS的解碼中,相關的標識符才能被正確解析(如這裡的 alert 標識符),

像圓括弧、雙引號、單引號等等這些控制字元,在進行JavaScript解析的時候僅會被解碼為對應的字元串文本(比如這裡並未對 (1) 進行編碼,如果對括弧及括弧裡面內容做JS編碼,將無法執行alert函數 )

 

<a href="javascript:alert(1<2)">abc</a>
等價於
<a href="javascript:\u0061\u006c\u0065\u0072\u0074(1<2)">abc</a>
等價於(使用JS的方法進行的URL編碼)
<a href="javascript:alert(1%3C2)">abc</a>
等價於(使用轉換成對應ASCII編碼對應2位16進位數字的URL編碼)
<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34%28%31%3C%32%29">abc</a>
等價於
<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#49;&#37;&#51;&#67;&#50;&#41;">abc</a>

上述代碼中

編碼順序:Javascript編碼 -> URL編碼 -> HTML編碼

解碼順序:HTML解碼 -> URL解碼 -> Javascript解碼

這裡還需要註意的是,在URL的編碼中,不能對協議類型(這裡的 javascript: )進行編碼,否則URL解析器會認為它無類型,導致無法正確識別

 

應用這個解析順序,看以下這個例子

輸入源 abc為URL中的值,如果後端僅進行了HTML的編碼,還是有問題的

Payload-0: http://local.abc.com/main/?r=abc/index&abc=');alert('11
<span onclick="test('<{$abc}>')">test</span>
 
<span onclick="test('&#x27;);alert(&#x27;11')">test</span>

解碼順序先是進行HTML解碼,此時會將 &#x27解析成 ' 號,接著進行Javascript的解碼,識別到 ' 即可閉合test函數,調用成功

所以,這種情況下,後端需要先進行Javascript編碼再進行HTML的編碼

 

當然,還有其他順序的混合。也需要考慮編碼工作能不能正確地進行過濾

<a href="javascript:window.open('[輸入源]')">

解碼順序:

HTML解碼 -> URL解碼 -> Javascript解碼 -> URL解碼

 

引申出去,還有一些字元集的知識點,腦殼疼,就不在這整理了

 

1.4 常見XSS攻擊方式

XSS的攻擊腳本多種多樣,在使用了模板(前端模板和後端模板)之後,需要格外註意數據的輸入輸出

下麵列舉幾個常見的

 

1.4.1 PHP使用Yii框架中的Smarty模板

有時候會使用 $smarty.get.abc 獲取URL中的參數,未經轉義

Payload-1: http://local.abc.com/main/?r=abc/index&abc=<script>alert(1)</script>
<span><{$smarty.get.abc}></span>
 
<span><script>alert(1)</script></span>
 
 
Payload-2: http://local.abc.com/main/?r=abc/index&abc="><script>alert(1)</script>
<a href="/main/?param=<{$smarty.get.abc}>">abc</a>
 
<a href="/main/?param="><script>alert(1)</script>">abc</a>
 
 
Payload-3: http://local.abc.com/main/?r=abc/index&abc=" onmouseover=alert(1)
<a href="/main/?param=<{$smarty.get.abc}>">abc</a>
 
<a href="/main/?param=" onmouseover="alert(1)" ">abc</a>
 
 
Payload-4: http://local.abc.com/main/?r=abc/index&urlTo=javascript:alert(1)
<a href="<{$smarty.get.urlTo}>">urlTo</a>
 
<a href="javascript:alert(1)">urlTo</a>
 
 
Payload-5: http://local.abc.com/main/?r=abc/index&urlTo=data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=
<a href="<{$smarty.get.urlTo}>">urlTo</a>
 
<!-- 對 <script>alert(1)</script> 進行 base64編碼 為 PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo= -->
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo=">urlTo</a>
 
 
Payload-6: http://local.abc.com/main/?r=abc/index&abc=</script><script>alert(1)//
<script>
    var abc = '<{$smarty.get.abc}>';
</script>
 
<script>
    // 第一個 script標簽被閉合,雖然會報錯,但不會影響第二個script標簽,註意需要閉合後面的引號或註釋,防止報錯
    var abc = '</script><script>alert(1)//';
</script>
 
 
Payload-7: http://local.abc.com/main/?r=abc/index&abc=alert(1)
<script>
    if (<{$smarty.get.abc}> == 'abc') {
        console.log(1);
    }
</script>
 
<script>
    // 此處因為沒有用引號,所以可以直接執行 alert(1)
    if (alert(1) == 'abc') {
        console.log(1);
    }
</script>
 
 
Payload-8: http://local.abc.com/main/?r=abc/index&abc='){}if(alert(1)){//
<script>
    if ('<{$smarty.get.abc}>' == 'abc') {
        console.log(1);
    }
</script>
 
 
<script>
    // 用了引號之後,閉合難度增加,不過還是可以閉合起來的
    if (''){}if(alert(1)){//' == 'abc') {
        console.log(1);
    }
</script>
 
 
Payload-9: http://local.abc.com/main/?r=abc/index&abc=');alert('1
Payload-10: http://local.abc.com/main/?r=abc/index&abc=%26%2339%3B);alert(%26%2339%3B1    對參數進行了HTML的實體編碼
<span onclick="test('<{$smarty.get.abc}>')">test</span>
 
<span onclick="test('');alert('1')">test</span>
 
 
Payload-11: http://local.abc.com/main/?r=abc/index&abc=" onfocus="alert(1)" autofocus="autofocus"
<input type="text" id="input" value="<{$smarty.get.abc}>">
 
<input id="input" value="" onfocus="alert(1)" autofocus="autofocus" "="" type="text">

線上 base64編碼解碼

解決方式為:

不使用 $smarty.get 相關獲取參數,改用後端過濾數據後再返回參數;

Yii框架中相應位置配置:'escape_html' => true

在頁面標簽內嵌的腳本中直接使用後端返回的數據並不安全,後端可能過濾不完善(見Payload-7和Payload-0)避免直接使用

可以改用將數據存儲在屬性中,再通過腳本獲取屬性的方式

 

1.4.2 JS操作DOM的時候是否會有XSS隱患?

使用 jQuery的append相關方法時(比如 html方法)可能會

// 執行
$($0).html('<script>alert(1);</script>');
 
// 執行
$($0).html('\u003cscript\u003ealert(1);\u003c/script\u003e');
 
// 執行
$($0).append('<script>alert(1);</script>');
 
// 不執行
$0.innerHTML = '<script>alert(1);</script>';

原因是在jQuery中使用了eval方法執行相應的腳本,需要註意的是,Unicode編碼的字元在運算中會被解析出來

所以,要註意的是

使用jQuery設置DOM內容時,記得先對內容進行轉義

 

對於設置輸入框的值,是安全的

<input type="text" id="input">
<textarea value="12" id="textarea"></textarea>
 
<script>
    // 不執行
    document.getElementById('input').value = '"><script>alert(1);<\/script>';
    document.getElementById('textarea').value = '"><script>alert(1);<\/script>';
     
    // 不執行
    $('#input').val('" onmouseover="alert(1)"');
    $('#textarea').val('" onmouseover="alert(1)"');
</script>

對於設置屬性的值,是安全的

<input type="text" id="input">
<textarea value="12" id="textarea"></textarea>
 
<script>
    // 不執行
    document.getElementById('input').setAttribute('abc', '"><script>alert(1);<\/script>');
    document.getElementById('textarea').setAttribute('abc', '"><script>alert(1);<\/script>');
 
    // 不執行
    $('#input').attr('abc', '" onmouseover="alert(1)"');
    $('#textarea').attr('abc', '" onmouseover="alert(1)"');
</script>

1.4.3 前端Handlebars模板中的安全問題

後端有Smarty模板,前端也可以有Handlebars模板,使用模板有利於開發維護代碼。不過和後端一樣,使用模板也要考慮到XSS的問題

Handlebars模板中可選擇是否開啟轉義

<!-- 轉義,如果name的值已經被後端轉義為實體符&gt; 那麼Handlebars將會轉換成 &amp;gt; 在瀏覽器中將會顯示 &gt; -->
<!-- 所以此時需要先將 &gt; 轉回 > 再傳入Handlebars模板,才能看到正確的 > 符號 -->
<span>{{name}}</span>
 
<!-- 不轉義 -->
<span>{{{name}}}</span>

所以要註意的第一點是:

如果使用了轉義占位符,就需要先進行還原;如果不使用轉義,就不要還原,否則將造成XSS

另外,Handlebars模板可以自定義helper,helper有兩種使用方式,直接返回數據或返回子層

<!-- 模板 [A] -->
<script type="text/template" id="test-tpl">
    <span abc="{{#abc attrData}}{{/abc}}">111{{#abc data}}{{/abc}}</span>
    <span>
        <input type="text" value="{{#abc attrData}}{{/abc}}">
    </span>
</script>
 
<!-- 模板 [B] -->
<!-- <script type="text/template" id="test-tpl">
    <span abc="{{#abc attrData}}{{attrData}}{{/abc}}">111{{#abc data}}{{data}}{{/abc}}</span>
    <span>
        <input type="text" value="{{#abc attrData}}{{attrData}}{{/abc}}">
    </span>
</script> -->
 
 
<!-- 容器 -->
<span id="test"></span>
 
<script src="........./handlebars/handlebars-v4.0.5.js"></
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MongoDB 是什麼 MongoDB 是一種非關係型資料庫(NoSQL)。 MongoDB中的術語解釋 文檔(document):形如 { name: "sue", 區分大小寫 field唯一 , 不可重覆 文檔可嵌套 鍵值對是有序的 集合:集合就是一組文檔 SQL 與 MongoDB 術語比較 ...
  • 自己的庫里有索引在用insert導入數據時會變慢很多 使用事務+批量導入 可以配置使用spring+mybatis整合的方式關閉自動提交事務(地址),選擇批量導入每一百條導入使用list存儲值傳入到mybatis中 http://x125858805.iteye.com/blog/2369243 或 ...
  • 最近公司項目需要從SQL Server轉到MySQL, 在轉的過程中遇到兩者語法之間的一些差異,在網上找瞭解決方案後,特記錄在此。由於解決方案可能有很多種,我只記錄了自己使用過的,僅作參考。 1. 拼接字元串 使用 方法 MSSQL MySQL 2. MySQL中和update set select ...
  • ...
  • AIDL使用以及IPC原理分析(進程間通信) 概要 為了大家能夠更好的理解android的進程間通信原理,以下將會從以下幾個方面講解跨進程通訊信: 1. 必要瞭解的概念 2. 為什麼要使用aidl進程間通信 3. 可能遇到的問題以及解決辦法 4. aidl的使用,通過android提供的aidl實現 ...
  • Objective-C的本質 Objective-C的本質 1、我們編寫的Objective-C,底層現實都是C/C++,代碼生成步驟如下: 1、我們編寫的Objective-C,底層現實都是C/C++,代碼生成步驟如下: 2、在OC中的所有面向對象的實現,都是基於C/C++的數據結構實現的 3、將 ...
  • 瀏覽器輸入框自動填充解決辦法 emmmmm;今天處理公司後臺系統遇到的;登錄頁面瀏覽器保存賬號密碼後;瀏覽器會自動在其他頁面進行填充;解決如下圖: 瀏覽器會預設填充input type值為password的文本框;(填充對象為input[type=password]及前一個input框) 先設置in ...
  • rem適配 <meta name="viewport" content="width=device-width,user-scalable=no"/> <script> (function(){ var html=document.documentElement; var hWidth=html.g ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...