Open tiodot opened 7 years ago
在单点登录的三种实现方式中,介绍了三种的单点登录实现方式:
文章讲的思路很清楚,就差使用代码实现,因而先实现以Cookie作为凭证媒介这种方式,这里使用node+koa2实现。Cookie相关的知识可以参考 #21。
以Cookie作为凭证媒介
以Cookie作为凭证媒介的思路为: 来源:单点登录的三种实现方式
这里的父应用就是需要实现的单点登录系统,而子应用就是实际的业务系统之类。 要实现单点登录系统,至少需要:
提供登录页面,输入帐号密码,然后通过ajax请求验证帐号密码的正确性。如果正确则返回需要跳转的地址,并注入相关cookie,后端实现为:
router.post('/login', async (ctx) => { const data = ctx.request.body; if (!isValid(data)) { // 验证帐号密码是否正确 return ctx.body = {code: 1, msg: '帐号或者密码不正确'}; } // 对用户名进行加密作为登录凭证。 ctx.cookies.set('token', cryptoCookie.encrypt(data.name), { domain: 'local.com' // 设置域名为顶级域名 }); ctx.body = {code: 0, msg: '登录成功', url: '/detail'} // 验证成功返回需要跳转的url });
前端请求验证帐号密码是否正确:
window.fetch('/login', { method: 'post', headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, credentials: 'same-origin', // 需要设置,否则设置不上cookie body: data }).then(res => res.json()).then(res => { if (res.code !== 0) { $error.innerHTML = res.msg; } else { window.location.href = res.url; } })
因为登录凭证是通过cookie中的token字段来标识的,所以退出只需要清空一下相关cookie就行:
router.get('/logout', async (ctx) => { ctx.cookies.set('token', '', { domain: 'local.com', expires: new Date('1970-1-1') // 设置过期时间,由于该时间小于当前时间,浏览器会自动清除该cookie }); await ctx.redirect('/login'); });
因为登录凭证都是通过cookie中的token存储的。所以需要取出token中的存储的信息,解密成用户民,然后判断用户民是否存在。
router.get('/validate', async (ctx) => { const token = ctx.cookies.get('token'); const name = cryptoCookie.decrypt(token); if (isExist(name)) { ctx.body = { code: 0, msg: 'success', name: name } } else { ctx.body = { code: 1, msg: 'error' } } });
在子应用中,为了简单,每次请求都向登录系统发请求验证是否已经登录,如果没有登录则重定向到父应用的登录页面进行登录:
app.use(async (ctx, next) => { const cookie = ctx.cookies.get('token'); if (!cookie) { ctx.state.isLogin = false; } else { await new Promise((resolve, reject) => { http.request({ host: 'local.com', port: 3000, path: '/validate', method: 'get', headers: { 'Cookie': ctx.request.headers.cookie } }, (res) => { res.setEncoding('utf8'); let data; res.on('data', (chunk) => { data = JSON.parse(chunk); }); res.on('end', () => { resolve(data); }); }).end(); }).then((res) => { if (res.code !== 0) { ctx.state.isLogin = false; } else { ctx.state.isLogin = true; ctx.state.name = res.name; } }); } await next(); });
这里有个遗留问题,每次请求验证Cookie是否可以做些优化,如果第一次验证成功,则隔一段时间再去验证cookie,以减少请求次数。
在单点登录的三种实现方式中,介绍了三种的单点登录实现方式:
文章讲的思路很清楚,就差使用代码实现,因而先实现
以Cookie作为凭证媒介
这种方式,这里使用node+koa2实现。Cookie相关的知识可以参考 #21。以Cookie作为凭证媒介
的思路为: 来源:单点登录的三种实现方式这里的父应用就是需要实现的单点登录系统,而子应用就是实际的业务系统之类。 要实现单点登录系统,至少需要:
1. 登录功能
提供登录页面,输入帐号密码,然后通过ajax请求验证帐号密码的正确性。如果正确则返回需要跳转的地址,并注入相关cookie,后端实现为:
前端请求验证帐号密码是否正确:
2. 退出功能
因为登录凭证是通过cookie中的token字段来标识的,所以退出只需要清空一下相关cookie就行:
3. 提供验证Cookie的接口
因为登录凭证都是通过cookie中的token存储的。所以需要取出token中的存储的信息,解密成用户民,然后判断用户民是否存在。
在子应用中使用
在子应用中,为了简单,每次请求都向登录系统发请求验证是否已经登录,如果没有登录则重定向到父应用的登录页面进行登录:
这里有个遗留问题,每次请求验证Cookie是否可以做些优化,如果第一次验证成功,则隔一段时间再去验证cookie,以减少请求次数。
参考