?? ???(SSO) ????? ?????? nodejs? ???? ???? ??? ??????
Feb 24, 2023 pm 07:33 PMSingle Sign-On ????? ?????? nodejs? ???? ???? ??? ?????? ?? ???? Node? ???? Single Sign-On ???? ???? ??? ???????. ??? ?? ????.
Single Sign On SSO(Single Sign On)? ? ? ??? ???? ????? ??? ??? ???? ??? ???? ???? ? ?? ??? ??? ?? ???? ????? ???? ? ??? ?? ????. ????? ???.
1. ?? ??
1.1 ?? ?? ??
?? = ???? + ??? ?? + ??
http://www.a.com? ?? ?????:
- https: // www.a.com ?(?? ????)
- http://www.b.com ?(?? ??? ??)
- http://www.a.com:3000 ?(?? ??)
?? ?? ?? ?????? ??? ???? ? ????????? ???? ? ??? ?? ??? ???? ?? ????? ?????.
1.2 ?? ????
http ????? ?? ??? ???????(?????? ?? ???? ??? ? ??? ??? ??? ??? ?? ?????) ???? ?? ??? ???? ?? ?? ??? ???? ??? ?? ?????. [?? ?? ????: nodejs ??? ????]
????? ???? ?? ??? ??? ???? ??? ???? ??? ?????? ????? ????. ? ? ??? ?? ?? ?????.
2. ?? ???
1. ??? ?? ??? SSO
??? ?? ???(?: www.app1.aaa.com
, www) app2.aaa.com
? ?? ?? .aaa.com? ?? ???? ????. www.app1.aaa.com
,www.app2.aaa.com
這兩個(gè)服務(wù)器都是在.aaa.com的父域名。
默認(rèn)情況下,兩個(gè)服務(wù)器下頁(yè)面之間的cookie是互相訪問(wèn)不到的。
但是我們可以通過(guò)設(shè)置cookie的domain屬性為共通的父域名,使得兩個(gè)服務(wù)器下頁(yè)面之間的cookie可以相互訪問(wèn)到。
router.get('/createCookie',?async?(ctx,?next)?=>?{ ??ctx.cookies.set('username',?'123',?{ ????maxAge:?60?*?60?*?1000, ????httpOnly:?false, ????path:?'/', ????domain:'.a.com'?//設(shè)置domain為共通的父域名 ??}); ??ctx.body?=?"create?cookie?ok"})router.get('/getCookie',?async?(ctx,?next)?=>?{ ??let?username=ctx.cookies.get('username') ??if?(username){ ????ctx.body=username??}else{ ????ctx.body='no?cookie' ??}})
2. 跨域SSO
當(dāng)我們的域名為www.a.com
,www.b.com
時(shí),無(wú)論怎樣設(shè)置domain都沒(méi)用了。
那么就要想辦法將身份憑證(token)寫(xiě)入到所有域的cookie中。
2.1 跨域?qū)慶ookie
2.1.1 利用標(biāo)簽跨域?qū)慶ookie(jsonp)
在http://www.a.com/index.js中直接向https://www.c.com:3000/sso直接發(fā)送網(wǎng)絡(luò)請(qǐng)求,是無(wú)法跨域?qū)懭隿ookie的。
??<script> $.ajax({ url: 'https://www.c.com:3000/sso?key=username&value=123', method: 'get', }) </script>
但是我們可以通過(guò)標(biāo)簽發(fā)起跨域請(qǐng)求,寫(xiě)入cookie
<script></script>
或者使用jquery jsonp的方式發(fā)起跨域請(qǐng)求,寫(xiě)入cookie,這種方式的原理也是通過(guò)標(biāo)簽?zāi)軌蚩缬驅(qū)崿F(xiàn)的。
?$.ajax({ ??????url:?'https://www.c.com:3000/sso?key=username&value=123', ??????method:?'get', ??????dataType:'jsonp' ????})
這樣通過(guò)標(biāo)簽就實(shí)現(xiàn)了往www.a.com中寫(xiě)入了domain為www.c.com的跨域cookie.
后端
const?options?=?{ ??key:?fs.readFileSync(path.join(__dirname,?'./https/privatekey.pem')), ??cert:?fs.readFileSync(path.join(__dirname,?'./https/certificate.pem')), ??secureOptions:?'TLSv1_2_method'?//force?TLS?version?1.2}var?server?=?https.createServer(options,app.callback());??//只能使用https協(xié)議寫(xiě)cookierouter.get('/sso',?async?(ctx,?next)?=>?{ ??let?{ ????key,?value??}?=?ctx.request.query ??ctx.cookies.set(key,?value,?{ ????maxAge:?60?*?60?*?1000,?//有效時(shí)間,單位毫秒 ????httpOnly:?false,?//表示?cookie?是否僅通過(guò)?HTTP(S)?發(fā)送,,?且不提供給客戶端?JavaScript?(默認(rèn)為?true). ????path:?'/', ????sameSite:?'none',?//限制第三方?Cookie ????secure:?true?//cookie是否僅通過(guò)?HTTPS?發(fā)送 ??}); ??ctx.body?=?'create?Cookie?ok'})
注意:
瀏覽器未寫(xiě)入cookie報(bào)錯(cuò)
his set-cookie was blocked due to http-only
http-only:表示 cookie 是否僅通過(guò) HTTP(S) 發(fā)送,, 且不提供給客戶端 JavaScript (默認(rèn)為 true).
所以要將httpOnly設(shè)置為false.瀏覽器未寫(xiě)入cookie報(bào)錯(cuò)
this set-cookie was blocked due to user preference
這個(gè)真的坑,因?yàn)槲沂菬o(wú)痕模式打開(kāi)的瀏覽器,但是chrome瀏覽器默認(rèn)無(wú)痕模式下禁用第三方cookie,修改為允許所有cookie就行了.瀏覽器未寫(xiě)入cookie報(bào)錯(cuò)
this set cookie was blocked because it has the SameSite attribute but Secure not set
需要設(shè)置sameSite和secure屬性-
瀏覽器未寫(xiě)入cookie報(bào)錯(cuò)
??? ??? ??? ??? ?? ?? ??? ???? ???? ? ??? ??? ??? ?? ??? ?? ???? ? ????.server error Error: Cannot send secure cookie over unencrypted connection
????? ? ??? ??? ? ??? ?? ???? ? ????.
router.get('/sso',?async?(ctx,?next)?=>?{ ??let?{ ????key,?value??}?=?ctx.request.query ??ctx.cookies.set(key,?value,?{ ????maxAge:?60?*?60?*?1000,?//有效時(shí)間,單位毫秒 ????httpOnly:?false, ????path:?'/', ????sameSite:?'none', ????secure:?true ??}); ??ctx.set("P3P",?"CP='CURa?ADMa?DEVa?PSAo?PSDo?OUR?BUS?UNI?PUR?INT?DEM?STA?PRE?COM?NAV?OTC?NOI?DSP?COR'")?//p3p響應(yīng)頭 ??ctx.body?=?'create?Cookie?ok'})

2 . Cross-domain SSO
?? ??? ??? www.a.com
, www.b.com
?? ??? ???? ???? ??? ????. .
?? ?? ?? ???? ??? ID ?? ??(??)? ???? ??? ??? ???.
??2.1 ??? ??? ?? ????
????2.1.1 <script></script> ??? ???? ??? ??? ?? ??(jsonp)??????http://www.a.com /index .js?? https://www.c.com:3000/sso? ?? ???? ??? ??? ?? ??? ?? ??? ? ? ????. ??router.get('/createToken',?async?(ctx,?next)?=>?{ ??let?{?from?}?=?ctx.request.query??let?token?=?"123"; ??ctx.response.redirect(`${from}?token=${token}`)})????? <script></script> ??? ?? ??? ? ??? ???? ??? ????
router.get('/createCookie',?async?(ctx,?next)?=>?{ ??let?{?token?}?=?ctx.request.query ??ctx.cookies.set('token',?token,?{ ????maxAge:?60?*?60?*?1000,?//有效時(shí)間,單位毫秒 ????httpOnly:?false, ????path:?'/', ??}); ??ctx.body?=?'set?cookie?ok'})????? jquery jsonp? ???? ??? ? ??? ???? ??? ??? ? ????. ???? /> ??? ?? ???? ?? ??? ? ????. ??
<script></script>????? ?? <script></script> ??? ?? www.c.com ???? ??? ??? ??? www.a.com? ?????.??

router.get('/readCookie',?async?(ctx,?next)?=>?{ ??let?username?=?ctx.cookies.get('username') ??console.log('cookie',?username)})????:?? ??
- ????????? ??? ?? ??? ??? ??????
?? ?? ??? http ???? ?? ???????
?? http- only: ??? HTTP(S)? ???? ???? ????? JavaScript? ???? ??? ??? ?????(???? true).?? ??? httpOnly? false? ?????.????????????? ??? ???? ??? ??? ??????. code>? ?? ??? ??? ?? ???? ?? ???????.?? ????? ??? ??? ???? Chrome ????? ????? ??? ???? ?? ??? ??????? ?? ?? ?????. ?? ??? ?????.???????? ??????? ??? ?? ???? ??? ??? ??? SameSite ??? ??? ??? ???? ??? ??? ???????
?? sameSite ? ?? ??? ???? ???????????????? ??? ???? ??? ???????? ?? ??: ????? ?? ??? ?? ?? ??? ?? ? ????
?? ??? ?? ??? ?? Koa ?????? ?? ??? ? ????. www.c.com? https ??? ??????.?????????? 2.1.2 p3p ???? ??? IE ???? ??? ???? ?????. ????????? ??? jsonp ???? ?? ?????? ???? ????? IE ????? ??? ?? ? ???? ?? ?????? ??? ??? ? ????. ???? p3p ?? ??? ???? ????. ??rrreee????2.1.3 URL ????? ??? ? ?? ??? ???????????http://www.c.com:3000/createToken?from=http://www.a.com/createCookie??? ?????.www.c.com上生成token后將url重寫(xiě),帶上token,重定向到www.a.com
router.get('/createToken',?async?(ctx,?next)?=>?{ ??let?{?from?}?=?ctx.request.query??let?token?=?"123"; ??ctx.response.redirect(`${from}?token=${token}`)})
www.a.com上從url上獲取token,存入cookie
router.get('/createCookie',?async?(ctx,?next)?=>?{ ??let?{?token?}?=?ctx.request.query ??ctx.cookies.set('token',?token,?{ ????maxAge:?60?*?60?*?1000,?//有效時(shí)間,單位毫秒 ????httpOnly:?false, ????path:?'/', ??}); ??ctx.body?=?'set?cookie?ok'})
這樣就實(shí)現(xiàn)了跨域信息的傳遞.與上面的方式不同,這種方法只是單純的http請(qǐng)求,適用于所有瀏覽器,但是缺點(diǎn)也很明顯,每次只能分享給一個(gè)服務(wù)器。
2.2 跨域讀cookie
2.2.1 利用標(biāo)簽跨域讀cookie(jsonp)
之前2.1.1利用標(biāo)簽在www.a.com中寫(xiě)入了www.c.com的cookie(username,123),現(xiàn)在想要www.a.com請(qǐng)求的時(shí)候攜帶上www.c.com的cookie,也就是說(shuō)要跨域讀cookie.
其實(shí)也是同樣的方法,在www.a.com上利用跨域訪問(wèn)訪問(wèn)www.c.com,會(huì)自動(dòng)的帶上domain為www.c.com的cookie。www.a.com/index.js
<script></script>
www.c.com
router.get('/readCookie',?async?(ctx,?next)?=>?{ ??let?username?=?ctx.cookies.get('username') ??console.log('cookie',?username)})
可以看到讀取到了存儲(chǔ)在www.a.com里面domain為www.c.com的cookie.
3. nodejs實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)實(shí)戰(zhàn)
效果如圖所示:
第一次訪問(wèn)www.a.com首頁(yè)
跳轉(zhuǎn)到www.c.com:3000登錄頁(yè)面,登錄成功后跳轉(zhuǎn)www.a.com首頁(yè)
再次訪問(wèn)www.a.com首頁(yè),無(wú)需登錄直接跳轉(zhuǎn)
訪問(wèn)www.b.com首頁(yè),無(wú)需登錄直接跳轉(zhuǎn)
源碼: https://github.com/wantao666/sso-nodejs
詳細(xì)設(shè)計(jì):
更多node相關(guān)知識(shí),請(qǐng)?jiān)L問(wèn):nodejs 教程!
? ??? ?? ???(SSO) ????? ?????? nodejs? ???? ???? ??? ??????? ?? ?????. ??? ??? PHP ??? ????? ?? ?? ??? ?????!

? AI ??

Undress AI Tool
??? ???? ??

Undresser.AI Undress
???? ?? ??? ??? ?? AI ?? ?

AI Clothes Remover
???? ?? ???? ??? AI ?????.

Clothoff.io
AI ? ???

Video Face Swap
??? ??? AI ?? ?? ??? ???? ?? ???? ??? ?? ????!

?? ??

??? ??

???++7.3.1
???? ?? ?? ?? ???

SublimeText3 ??? ??
??? ??, ???? ?? ????.

???? 13.0.1 ???
??? PHP ?? ?? ??

???? CS6
??? ? ?? ??

SublimeText3 Mac ??
? ??? ?? ?? ?????(SublimeText3)

Node.js ?? ?????? npm? npm.cmd?? ? ?? npm ?? ??? ????. ???? ??? ????. ???? ????. npm? ?? ???? npm.cmd? ?? ? ?? ?????. Windows ???: npm.cmd? ?? ?????? ??? ? ???, npm? ?????? ??? ? ????. ???: npm.cmd? Windows ????? ???? npm? ??? ????? ??? ? ????. ?? ????: Windows ???? npm.cmd? ????, ?? ?? ??? npm? ?????.

Pinetwork ??? ?? ??? ?? ? ?? ???? ????? Pinetwork Ecosystem? ??? ?????. Pi ??, Pinetwork ???? ?? ??? ???? ?? ? ????? ?? ??? ?????. Pinetwork ?? ?? ??? ????? ?? ? ?, PI ??? ???? ?? ???? ???? ???? ???? ????? ???? ?? ????? ??? ????????. ?? Pinetwork? ???? Picoin? ???? ??????. ??? ??? ?????? PI ??, ?? ? ?? ??. Pinetwork ? ?????? Pinetwork ????? 2019 ?? ?????? ??? ? Cryptocurrency Pi Coin? ???? ????. ? ????? ?? ??? ??? ??? ??? ??? ?? ??????.

Node.js? ???, ???, ??? ??? ??, ??? ???, ?? ??? ?? ??? ????? ??? ?????? ??? ? ????.

?, Node.js? ????? ??? ??? ? ??? ?? ??? ???, ??? ???, ??? ? ??????. ???? ? ??? ?? ??, ?? ?? ? ??? ???? ?????.

Node.js?? ??? ?? ?? ??? ?????. ?? ??: ?? ?? ??: ????, ??, ?? ??? ?? ??: __dirname, __filename, __line, __column ??: undefine, null, NaN, Infinity, -Infinity

?, Node.js? ??? ?? ?????. ?? ? ???? ?? ??, ?????? ?? ??, API ?? ? ??? ??? ?????.

MySQL ??????? ????? ?? ??? ??? ???. mysql2 ????? ?????. mysql2.createConnection()? ???? ??? ??, ??, ??? ??, ???? ? ?????? ??? ??? ?? ??? ????. ??? ????? Connection.query()? ?????. ????? Connection.end()? ???? ??? ?????.

Node.js? ?? ???? ??? ?????. ???? ? ?? ?????? ??? ?? ?????? ??? ?????? ??? ??? ?????? ??? ?? ? ???? ?? ???????
