日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

什么是單點登錄系統?用nodejs怎么實現?下面本篇文章給大家介紹一下使用node實現單點登錄系統的方法,希望對大家有所幫助!


什么是單點登錄系統?用nodejs怎么實現?


單點登錄SSO(Single Sign On),就是把2個及以上的業務系統中的登錄功能剝離出來,形成一個新的系統,做到一次登錄后在任意的業務系統中都無需登錄的效果。


一. 基礎知識

1.1 同源策略

源 = 協議 + 域名 +端口

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

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

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

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

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


1.2 會話機制

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

常用的會話跟蹤就是cookie和session,簡單的理解它們就是可以存放key,value的數據結構,區別在于cookie保存在客戶端,session保存在服務器端。

二. 單點登錄

1. 同父域SSO

同父域,如www.app1.aaa.com,www.app2.aaa.com這兩個服務器都是在.aaa.com的父域名。

默認情況下,兩個服務器下頁面之間的cookie是互相訪問不到的。

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

router.get('/createCookie', async (ctx, next) => {
  ctx.cookies.set('username', '123', {
    maxAge: 60 * 60 * 1000,
    httpOnly: false,
    path: '/',
    domain:'.a.com' //設置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'
  }
})


什么是單點登錄系統?用nodejs怎么實現?


2. 跨域SSO

當我們的域名為www.a.com,www.b.com時,無論怎樣設置domain都沒用了。

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

2.1 跨域寫cookie

2.1.1 利用< script />標簽跨域寫cookie(jsonp)

在http://www.a.com/index.js中直接向https://www.c.com:3000/sso直接發送網絡請求,是無法跨域寫入cookie的。

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

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

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

或者使用jquery jsonp的方式發起跨域請求,寫入cookie,這種方式的原理也是通過< script />標簽能夠跨域實現的。

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

這樣通過<script/>標簽就實現了往www.a.com中寫入了domain為www.c.com的跨域cookie.


什么是單點登錄系統?用nodejs怎么實現?


后端

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協議寫cookie
router.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) 發送,, 且不提供給客戶端 JavaScript (默認為 true).
    path: '/',
    sameSite: 'none', //限制第三方 Cookie
    secure: true //cookie是否僅通過 HTTPS 發送
  });
  ctx.body = 'create Cookie ok'
})

注意:

瀏覽器未寫入cookie報錯his set-cookie was blocked due to http-only

http-only:表示 cookie 是否僅通過 HTTP(S) 發送,, 且不提供給客戶端 JavaScript (默認為 true).

所以要將httpOnly設置為false.

瀏覽器未寫入cookie報錯this set-cookie was blocked due to user preference

這個真的坑,因為我是無痕模式打開的瀏覽器,但是chrome瀏覽器默認無痕模式下禁用第三方cookie,修改為允許所有cookie就行了.


什么是單點登錄系統?用nodejs怎么實現?


瀏覽器未寫入cookie報錯this set cookie was blocked because it has the SameSite attribute but Secure not set

需要設置sameSite和secure屬性

瀏覽器未寫入cookie報錯server error Error: Cannot send secure cookie over unencrypted connection

這個我覺得是koa框架寫cookie的限制吧,它只能支持https寫cookie…,于是我把www.c.com改為了https服務器.


2.1.2 p3p協議頭實現IE瀏覽器跨域

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

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響應頭
  ctx.body = 'create Cookie ok'
})

2.1.3 url參數實現跨域信息傳遞

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

這樣就實現了跨域信息的傳遞.與上面的方式不同,這種方法只是單純的http請求,適用于所有瀏覽器,但是缺點也很明顯,每次只能分享給一個服務器。


什么是單點登錄系統?用nodejs怎么實現?


2.2 跨域讀cookie

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

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

其實也是同樣的方法,在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)
})


什么是單點登錄系統?用nodejs怎么實現?


可以看到讀取到了存儲在www.a.com里面domain為www.c.com的cookie.


3. nodejs實現單點登錄系統實戰


什么是單點登錄系統?用nodejs怎么實現?


效果如圖所示:

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

跳轉到www.c.com:3000登錄頁面,登錄成功后跳轉www.a.com首頁

再次訪問www.a.com首頁,無需登錄直接跳轉

訪問www.b.com首頁,無需登錄直接跳轉

源碼: https://github.com/wantao666/sso-nodejs

詳細設計:


什么是單點登錄系統?用nodejs怎么實現?


分享到:
標簽:單點登錄系統 nodejs實現單點登錄
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定