关于单点登录,在一些特定条件下,有没有相对简洁而又有效的实现方式?

2013-08-06 22:54:43 +08:00
 revlis7
据我自己平时了解到的情况,关于单点登录,可以有若干种做法

自己遇到的情形一般是,公司已经有了一个站点A,后来又多了一个站点B,但是运行在不同的域名下(关键),需要用户访问A的同时,能够自动登录站点B(不需要用户有一个额外授权认证的过程)

如果你google的话,通常会搜到用CAS做单点登录,可是CAS首先需要JAVA环境,其次CAS的做法好像和Oauth类似(可能就是衍生出来的概念,自己没有实际用过CAS),感觉如果只是要让自己两个站点同时登录,搞一套CAS什么的未免有点小题大作,另外OpenID什么的也了解过,也有类似的疑问。

说说我以前自己的做法:

1、用户请求站点B
2、跳转至站点A判断用户登录状态
3、如果已经登录跳转回站点B,并带上加密过的用户信息
4、站点B解密信息,设置站点B的登录状态,完成登录

另外还了解到一种做法:

1、用户请求站点B
2、站点B的页面中,包含一段访问站点A某个API的请求
3、这个站点A的API返回的是站点A下的cookie信息,并转换成JS嵌入站点B的页面
4、B站点页面获取到站点A的cookie后,后面的也不用多说了吧

我想知道我提到的这几种实现,究竟各自有什么样的优势或者劣势,或者还有其它更好的实现方式?在目前这种情况下,是否有足够的理由去使用CAS、Oauth或OpenID等类似的方式?
3827 次点击
所在节点    问与答
10 条回复
revlis7
2013-08-07 11:52:29 +08:00
Any Ideas?
wingoo
2013-08-07 12:06:59 +08:00
可以看下oauth 的实现, 如果自己跳转搞的话, 建议不要带用户信息, 可以一个guid过去,一次失效, 判断是否登录
atan
2013-08-07 12:26:38 +08:00
如果是apache的话可以试试mod_auth_tkt
revlis7
2013-08-07 12:54:57 +08:00
@atan 貌似又多了个选择,回头了解一下

@wingoo Oauth当然可以做,但问题就是,虽然Oauth可以用来做站点登陆这件事,但是实际上Oauth本身解决的是信息授权这个问题,登录只是授权认证其中的一部分而已。而且Oauth登录一般都是与第三方站点合作才会使用,那如果两个站点本身都是自己的,何必还需要一个认证授权的过程。
revlis7
2013-08-07 12:57:03 +08:00
这些都是我自己的理解,如果有错误的地方,可以纠正我。
wingoo
2013-08-07 13:06:05 +08:00
@revlis7 oauth只能说是曲线实现统一登录, 但公开的方案好处是安全之类的都考虑到了, 自己做套方案的话, 不能保证想全了
denger
2013-08-07 13:11:42 +08:00
可以看看我之前写的这方面的文章:
http://denger.iteye.com/category/161641

个人对 cas 比较熟悉。同样是基于统一认证中心来规避 session/cookie 存储跨应或域的问题。使用也较为简单,虽然它的 认证中心是基于 Java 实现,但是对于客户端(应用程序) 来说,提供有各种语言实现。python /php 等~

oauth 之类的个人感觉它更适用于第三方网站的登录授权。
ksc010
2013-08-07 13:22:31 +08:00
我现在用的是第二种
atan
2013-08-07 13:46:29 +08:00
@revlis7 CAS相对太庞大了些, 感觉有些时候小项目背后拉了个大家伙, mod_auth_tkt相比轻巧很多, 而且部署和迁移都挺方便的
ivydom
2019-10-10 16:39:26 +08:00
最简洁的就是用 Authing,超简单就可以实现:

``` javascript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Authing 单点登录实现示例</title>
<style>
body {
font-family: Avenir,Helvetica,Arial,sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}

a {
color: #42b983;
cursor: pointer;
text-decoration: underline;
}
</style>
</head>
<body>
<div style="margin-bottom:22px">
<img data-v-1129b33e="" alt="Vue logo" height="200" src="https://cdn.authing.cn/authing-logo@2.png">
<h1>使用 Authing 五分钟实现单点登录</h1>
<h2>当前状态:<span id="status">检测中</span></h2>
<h3 id="track-session-tip" style="display:none">以下是你的 session 信息:</h3>
<pre style="text-align: left;" id="session"></pre>
</div>
<a id="btn-login">登录</a>
<a id="btn-logout">退出</a>
<p>
<a href="https://authing.cn/login" target="_blank">使用 Authing</a>
<a href="https://github.com/Authing/web-sso-sample" target="_blank" style="margin-left:11px">本示例代码</a>
<a href="https://docs.authing.cn/authing/quickstart/implement-sso-with-authing" target="_blank" style="margin-left:11px">开发文档</a>
</p>
<p>
<a href="https://github.com/Authing/oidc-window">在单窗口中打开登录页面的代码示例</a>
</p>
<script src="https://cdn.jsdelivr.net/npm/@authing/sso/dist/AuthingSSO.umd.min.js"></script>
<script src="https://cdn.authing.cn/js-beautify/1.7.5/beautify.min.js"></script>
<script>
const authing = new AuthingSSO({
appId: "5d70d0e991fdd597019df70d", // OIDC 应用的 ID
appType: "oidc", // SSO 类型为 OIDC 类型
appDomain: "sample-sso.authing.cn"
});

const callTrackSession = async function() {
const res = await authing.trackSession();
if (!res.session) {
status.innerHTML = '未登录';
logout.setAttribute('style', 'display:none');
}else {
status.innerHTML = `${res.userInfo.username || res.userInfo.email || res.userInfo.nickname} 你好,你已处于登录状态`;
login.setAttribute('style', 'display:none');
sessionTip.setAttribute('style', 'display: block');
sessionPre.innerHTML = js_beautify(JSON.stringify(res));
}
};

// 检查登录状态
callTrackSession()

const login = document.getElementById('btn-login');
const logout = document.getElementById('btn-logout');
const status = document.getElementById('status');
const sessionPre = document.getElementById('session');
const sessionTip = document.getElementById('track-session-tip');

login.onclick = function() {
authing.login();
};

logout.onclick = async function() {
let res = await authing.logout();
alert(JSON.stringify(res));
location.reload();
};
</script>
</body>
</html>
```
线上体验:sample.authing.cn

https://github.com/Authing/web-sso-sample/blob/master/index.html

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/78236

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX