溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)

發(fā)布時間:2022-10-28 10:46:26 來源:億速云 閱讀:157 作者:iii 欄目:web開發(fā)

今天小編給大家分享一下node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

一. 基礎(chǔ)知識

1.1 同源策略

源 = 協(xié)議 + 域名 +端口

以http://www.a.com為例:

  • https://www.a.com ?(協(xié)議不同)

  • http://www.b.com ?(域名不同)

  • http://www.a.com:3000 ?(端口不同)

同源策略是瀏覽器的行為,它通過確保應(yīng)用下的資源只能被本應(yīng)用訪問,來保證安全。

1.2 會話機(jī)制

由于http協(xié)議是無狀態(tài)協(xié)議(客戶端和服務(wù)器端數(shù)據(jù)交換完畢,會關(guān)閉連接,下次請求重新建立連接),但我們需要做記住密碼等功能時,很明顯需要將會話記錄下來。

常用的會話跟蹤就是cookie和session,簡單的理解它們就是可以存放key,value的數(shù)據(jù)結(jié)構(gòu),區(qū)別在于cookie保存在客戶端,session保存在服務(wù)器端。

二. 單點(diǎn)登錄

1. 同父域SSO

同父域,如www.app1.aaa.com,www.app2.aaa.com這兩個服務(wù)器都是在.aaa.com的父域名。
默認(rèn)情況下,兩個服務(wù)器下頁面之間的cookie是互相訪問不到的。

但是我們可以通過設(shè)置cookie的domain屬性為共通的父域名,使得兩個服務(wù)器下頁面之間的cookie可以相互訪問到。

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'
  }})

node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)

2. 跨域SSO

當(dāng)我們的域名為www.a.com,www.b.com時,無論怎樣設(shè)置domain都沒用了。

那么就要想辦法將身份憑證(token)寫入到所有域的cookie中。

2.1 跨域?qū)慶ookie
2.1.1 利用< script />標(biāo)簽跨域?qū)慶ookie(jsonp)

在http://www.a.com/index.js中直接向https://www.c.com:3000/sso直接發(fā)送網(wǎng)絡(luò)請求,是無法跨域?qū)懭隿ookie的。

  <script>
    $.ajax({
      url: 'https://www.c.com:3000/sso?key=username&value=123',
      method: 'get',
    })
  </script>

但是我們可以通過< script />標(biāo)簽發(fā)起跨域請求,寫入cookie

<script src="https://www.c.com:3000/sso?key=username&value=123"></script>

或者使用jquery jsonp的方式發(fā)起跨域請求,寫入cookie,這種方式的原理也是通過< script />標(biāo)簽?zāi)軌蚩缬驅(qū)崿F(xiàn)的。

 $.ajax({
      url: 'https://www.c.com:3000/sso?key=username&value=123',
      method: 'get',
      dataType:'jsonp'
    })

這樣通過< script />標(biāo)簽就實(shí)現(xiàn)了往www.a.com中寫入了domain為www.c.com的跨域cookie.
node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)
后端

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é)議寫cookierouter.get('/sso', async (ctx, next) => {
  let {
    key, value  } = ctx.request.query
  ctx.cookies.set(key, value, {
    maxAge: 60 * 60 * 1000, //有效時間,單位毫秒
    httpOnly: false, //表示 cookie 是否僅通過 HTTP(S) 發(fā)送,, 且不提供給客戶端 JavaScript (默認(rèn)為 true).
    path: '/',
    sameSite: 'none', //限制第三方 Cookie
    secure: true //cookie是否僅通過 HTTPS 發(fā)送
  });
  ctx.body = 'create Cookie ok'})

注意:

  • 瀏覽器未寫入cookie報(bào)錯his set-cookie was blocked due to http-only
    http-only:表示 cookie 是否僅通過 HTTP(S) 發(fā)送,, 且不提供給客戶端 JavaScript (默認(rèn)為 true).
    所以要將httpOnly設(shè)置為false.

  • 瀏覽器未寫入cookie報(bào)錯this set-cookie was blocked due to user preference
    這個真的坑,因?yàn)槲沂菬o痕模式打開的瀏覽器,但是chrome瀏覽器默認(rèn)無痕模式下禁用第三方cookie,修改為允許所有cookie就行了.
    node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)

  • 瀏覽器未寫入cookie報(bào)錯this set cookie was blocked because it has the SameSite attribute but Secure not set
    需要設(shè)置sameSite和secure屬性

  • 瀏覽器未寫入cookie報(bào)錯server error Error: Cannot send secure cookie over unencrypted connection
    這個我覺得是koa框架寫cookie的限制吧,它只能支持https寫cookie…,于是我把www.c.com改為了https服務(wù)器.

2.1.2 p3p協(xié)議頭實(shí)現(xiàn)IE瀏覽器跨域

上面說的jsonp的方式在chrome瀏覽器中完美運(yùn)行,但是IE瀏覽器對于cookie更加嚴(yán)格,只用上面方式無法寫入cookie,解決辦法就是加上p3p的響應(yīng)頭。

router.get('/sso', async (ctx, next) => {
  let {
    key, value  } = ctx.request.query
  ctx.cookies.set(key, value, {
    maxAge: 60 * 60 * 1000, //有效時間,單位毫秒
    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.1.3 url參數(shù)實(shí)現(xiàn)跨域信息傳遞

訪問http://www.c.com:3000/createToken?from=http://www.a.com/createCookie

www.c.com上生成token后將url重寫,帶上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, //有效時間,單位毫秒
    httpOnly: false,
    path: '/',
  });
  ctx.body = 'set cookie ok'})

這樣就實(shí)現(xiàn)了跨域信息的傳遞.與上面的方式不同,這種方法只是單純的http請求,適用于所有瀏覽器,但是缺點(diǎn)也很明顯,每次只能分享給一個服務(wù)器。
node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)

2.2 跨域讀cookie
2.2.1 利用< script />標(biāo)簽跨域讀cookie(jsonp)

之前2.1.1利用< script />標(biāo)簽在www.a.com中寫入了www.c.com的cookie(username,123),現(xiàn)在想要www.a.com請求的時候攜帶上www.c.com的cookie,也就是說要跨域讀cookie.

其實(shí)也是同樣的方法,在www.a.com上利用< script />跨域訪問訪問www.c.com,會自動的帶上domain為www.c.com的cookie。
www.a.com/index.js

<script src="https://www.c.com:3000/readCookie"></script>

www.c.com

router.get('/readCookie', async (ctx, next) => {
  let username = ctx.cookies.get('username')
  console.log('cookie', username)})

node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)
可以看到讀取到了存儲在www.a.com里面domain為www.c.com的cookie.

3. nodejs實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)實(shí)戰(zhàn)

node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)
效果如圖所示:

  • 第一次訪問www.a.com首頁

  • 跳轉(zhuǎn)到www.c.com:3000登錄頁面,登錄成功后跳轉(zhuǎn)www.a.com首頁

  • 再次訪問www.a.com首頁,無需登錄直接跳轉(zhuǎn)

  • 訪問www.b.com首頁,無需登錄直接跳轉(zhuǎn)

詳細(xì)設(shè)計(jì):
node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)

以上就是“node如何實(shí)現(xiàn)單點(diǎn)登錄系統(tǒng)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI