我现在碰到这样的问题,有三个域名a.com b.com c.com,当用户在a.com完成登录后,再访问b.com c.com也需要登录状态。三个域名用的是同一个用户系统,只是前端展现不一样。

2010-11-05 15:00:22

18 Answers

ucenter确实实现了代理认证的功能。不过想自己实现也是完全可行的。
首先在用户端要标示一个在线的状态,那么在用户端能够存储数据而且兼容性好的就只剩下cookie了,但是cookie默认是不跨域的,怎么办呢?幸好有jsonp这项技术。可以跨域传递数据。在cookie中存储一个唯一id值,也其他的关联数据。
然后在服务器器端的数据库中同样存储着一张数据表,可以根据这个cookie中的id查询登录时在数据库中写入的状态信息。
OK,跨域的思路解决。

2010-11-05 17:29:34
  1. 是否登录校验

www.t.com/user/islogin?jsonp={callback} => [
1. 首先去找 cookie里面是否存在 .t.com 域下的 令牌 tokenket
2. 不存在令牌
3. 展现登录视图
 

www.t.com/user/islogin?jsonp={callback} => [
1. 首先去找 cookie里面是否存在 .t.com 域下的 令牌 tokenket
2. 存在令牌但校验无效
3. 展现登录视图
 

www.t.com/user/islogin?jsonp={callback} => [
1. 首先去找 cookie里面是否存在 .t.com 域下的 令牌 tokenket
2. 存在令牌
3. 令牌有效 -> 通过
 

  1. 登录操作

www.t.com/user/logincheck?jsonp={callback} => [
1. 校验帐号信息
2. 正确/错误/异常  

  1. 正确 -> 生成令牌 -> 写入 .t.com 下的tokenket 中  
2010-11-05 18:13:24

完全的跨域登录这个问题在业界早就有完善的解决方案了啊,叫做OAuth (最新版本是2.0),包括了服务器端第三方登录、客户端Javascript第三方登录、客户端桌面或手机软件第三方登录、用户名密码的第三方登录(可选,不安全)等等完整的一套解决方案。新浪微博等第三方登录接口都是这么设计的,为什么没人提呢……其他方案基本上都是有比较严重的安全漏洞的

具体的架构可以参考官方文档,大致上是这样的结构:
(1) 需要第三方登录时:
比如从a.com使用t.com登录,在a.com生成一个这样的页面链接:
https://t.com/getcode?callback=http://a.com/callback&state=abce2324&appkey=29s0akfds3
后面的state里面存储token,防止CSRF攻击
appkey是大多数OAuth中都需要的,在访问时用来验证请求者的身份。获取code时使用明钥,获取authtoken时使用密钥,确保调用者身份。

a.com将这个链接展示给用户:“使用t.com登录”按钮,或者(在用户默许的条件下)自动重定向到这个页面
t.com通过callback地址验证这个页面的确来自于有授权的a.com,然后展示给用户:

a.com请求使用您的t.com账号登录
允许 拒绝
如果未登录,则同时显示输入用户名、密码的框

如果用户以前已经授权过并且当前已经登录,这个过程就可以跳过,直接从getcode页面重定向回callback,这样这个登录的过程对用户来说就不可见了。
如果用户允许的话,getcode会将页面重定向到callback:
http://a.com/callback?code=239dsafk3k&state=abce2324

state参数保持不变,这样callback可以校验这个参数判断这次请求的确来自自己的getcode请求,而不是一次恶意的CSRF攻击。如果没有这个参数,一个恶意网站可能通过嵌入的方法在用户不知觉的情况下改变当前登录的账号。这时候用户进行的操作就可能被攻击者获得。

code参数是一个临时的标示符,在几分钟内有效,callback页面在获取code之后,通过curl调用:
https://t.com/getauth?code=239dsafk3k&appkey=29s0akfds3&secretkey=2dskeislsedsa
这个页面会通过json或者xml的格式返回authtoken,callback页面就可以通过authtoken来获取用户信息、模拟用户操作等等。通常也允许直接在callback中返回authtoken,但不如code方式安全,因为authtoken会显式地出现在地址中,用户可能不小心将地址发给了别人从而导致authtoken泄露。

对Javascript登录来说方法是类似的,差别在于:
Javascript并不是重定向,而是打开一个新的窗口,显示getcode页面,并且要求直接返回authid,而且使用特殊的“Javascript登录”方法;
getcode页面完成的时候,通过window.parent.location.href="#a934jkdsfsa"的方法返回。重定向到一个锚地址不会刷新页面,但javascript可以通过获取这个锚地址来获得返回的authtoken。之后可以用jsonp的方法来调用跨域API。jsonp的API不可以直接提供登录、或者无参数验证登录状态的接口,否则会引起严重的安全问题。但是可以提供使用code换取token的接口。

对应用程序登录来说:
应用程序通过打开浏览器、或者显示内嵌的浏览器、或者显示链接给用户,展示:
https://t.com/getcode?appkey=dskel22324
这个页面在完成之后不进行callback,而是直接显示code:
您的code为:
dsal32lsdfsk
然后用户将这个code复制并填写到应用程序指定的地方,应用程序使用code调用getauth获得authtoken

用户名密码验证就不用多说了,直接调http://t.com/getauth?username=...&password=...

对你自己的应用来说可以用简化版本:
访问http://a.com/时,如果SESSION或Cookies里没有authtoken,显示登录按钮;登录到http://t.com/getcode,getcode验证callback地址,如果已经登录就直接跳转(跳过验证授权步骤),然后返回到callback;之后callback地址使用getauth获得token。之后还可以使用token来调用t.com上面的Service API。

2010-11-05 20:36:43

要看你各个网站是依靠那种方式来验证登录了,
session的话,可以通过memcache之类的nosql存储登录状态;
cookie的话,可以在a登录的同时,向b和c发起请求,模拟一次登录,取回登录之后的cookie信息,在a输出的时候,设置cookie,这样能保证b和c同时登录

2010-11-05 21:18:52

相当于有一个ucenter,提供一个服务器端xml_rpc的接口,b.com请求xml_rpc客户端检查用户是否通过,通过则解析这个cookie。里面加密了用户的各种信息。然后数据库检查这个用户存在与否,就可以显示其登陆状态了。这个是同一域名下登陆情况的处理。
如果是不同域名下的登陆状态,可以多返回一个表示是否有其它子站也登陆的情况,如果a.com登陆了,返回is_login:1,否则返回is_login:0.就可以判断是否有其它子站,这个用户是否登陆了。

2010-11-05 22:59:55

建议使用基于服务器的安全认证,由前台+数据库来管理,比如:定义SessionID,记录到cookie中,在filter中或许认证信息,然后由安全认证来进行校验是否合法,我使用具有Weblogic的安全认证,当然还有很多其他开源的

2010-11-06 01:02:53
您不能回答该问题或者回答已经关闭!

相关文章推荐

  • C#实例解析适配器设计模式

    将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够一起工作

  • C#开发高性能Log Help类设计开发

    项目中要在操作数据库的异常处理中加入写Log日志,对于商业上有要求,写log时对其它操作尽可能影响小,不能因为加入log导致耗时太多

  • C#中using指令的几种用法

    using + 命名空间名字,这样可以在程序中直接用命令空间中的类型,而不必指定类型的详细命名空间,类似于Java的import,这个功能也是最常用的,几乎每个cs的程序都会用到

  • C#协变和逆变

    “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型,“逆变”则是指能够使用派生程度更小的类型

  • C#运行时相互关系

    C#运行时相互关系,包括运行时类型、对象、线程栈和托管堆之间的相互关系,静态方法、实例方法和虚方法的区别等等

  • 使用托管C++粘合C#和C++代码(二)

    本文实现一下C++代码调用C#代码的过程。我构造一个简单并且直观的例子:通过C++ UI 触发C# UI.

  • C#基础概念之延迟加载

    延迟加载(lazy load)是Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作

  • 使用托管C++粘合C#和C++代码(一)

    C#在xml读写,数据库操纵,界面构造等很多方面性能卓越;C++的效率高,是底层开发的必备武器

  • C#中的索引器的简单理解和用法

    C#中的类成员可以是任意类型,包括数组和集合。当一个类包含了数组和集合成员时,索引器将大大简化对数组或集合成员的存取操作

  • C#开发中的反射机制

    反射的定义:审查元数据并收集关于它的类型信息的能力。元数据(编译以后的最基本数据单元)就是一大堆的表,当编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等

  • 深入C# 序列化(Serialize)、反序列化(Deserialize)

    C#中的序列化和反序列化,序列化是.NET运行时环境用来支持用户定义类型的流化的机制

  • Async和Await使异步编程更简单

    C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作