(php) PHP单点登入的问题

我做了一个单点登录遇到一个问题是:比如有A、B、C三系统,当没有登入的时候会跳到S系统进行登入,登入成功会生成一个token,并把token传回来,同时会把token存到redis里面。但是B、C系统如何去获取那个token?

既然这么多人不认同我的简单的想法那我就改正一下吧:
单点登录:
一个简单的场景:当用户第一次访问应用系统的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--ticket;用户再访问别的应用的时候,就会将这个ticket带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行校验,检查ticket的合法性。如果通过校验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。

所以单点登录的原理也就是这样,下面说一下实现原理,当用户通过认证系统的时候,会把ticket保存在cookie中,这样,用户夹带cookie登录其他系统的时候就可以附带上这个cookie进行验证了;但是这样会出现一个缺陷,就是不支持跨域,如何使其支持跨域呢,除了楼下的高票回答保存在数据库中外,还有一种方法,jsonp,原理图如下:

验证方法如下:

1、 用户通过登录子系统进行用户登录;
2、 用户登录子系统记录了用户的登录状态、OpenId等信息;
3、 用户使用业务子系统;
4、 若用户未登录业务子系统则将用户跳转至用户登录子系统;
5、 用户子系统通过JSONP接口将用户OpenId传给业务子系统;
6、 业务子系统通过OpenId调用验证服务;
7、 验证服务返回认证信息、业务子系统构造用户登录凭证;(此时用户客户端已经与子业务系统的验证信息已经一一对应)
8、 将用户登录结果返回用户登录子系统,若成功登录则将用户跳转回业务子系统;
9、 将授权后的内容返回客户端;

总结:整个单点登录的机制决定了OpenId是会出现在客户端的,所以OpenId需要有过期机制,假如用户在一个终端登录的话可以选择在用户每次登录或者每次退出时刷新OpenId,而在多终端登录的情况下就会出现矛盾:当一个终端刷新了OpenId之后其他终端将无法正常授权。这个时候就要采用单用户多OpenId的解决方案了。每次用户通过用户名/密码登录时,产生一个OpenId保存在Redis里,并且设定过期时间,这样多个终端登录就会有多个OpenId与之对应,不再会存在一个OpenId失效所有终端验证都失效的情况。

参考文章
百度:单点登录
单点登录的实现原理

———————————————————分割线————————————————————
以下是我之前的回答,回答的简单没考虑全面请见谅~
拿到这个token之后,用curl或者header的方式把值分别发送到另外两个B、C系统的接口中,接口中GET或则POST接收发送过来的token参数,然后处理这个token值。比如把token值存入redis、session等

反对目前的最佳答案,举个例子,假如单点登录要负责100个系统的登录,每个系统有用户登录之后都要请求99遍吗?那还叫什么单点登录。

其他说直接从redis里读token的人,你们知道哪个用户去读哪个key嘛?

所谓单点登录,并不是用户登录了A就代表也能登录B和C,而是登录了S就可以登录A、B、C。

所以需要两个东西:

1.S系统本身的cookie/session,只要用户登录了S系统(不管是直接访问S还是因为要登录A而访问S),就生成该用户在S系统下的cookie/session,不需要做任何跨域之类的处理。
2.login ticket,用户从A系统过来,S系统判断用户是否登录了S系统,如果没登录则要求登录,登录之后或者本身已经是登录状态,则会生成一个唯一的ticket,将该用户以及ticket存入数据库,然后将ticket通过用户浏览器返回给A系统,及S系统让用户浏览器跳转到 http://AAA.com/login/callback?ticket=xxxxx。这个时候A系统拿到了ticket,在内部去请求S系统的校验接口,S系统拿这个ticket和数据库里的比对,找出对应用户的信息返回给A系统,A系统就知道要登录的用户是谁了。

建议题主去看一下CAS协议 https://apereo.github.io/cas/…

亲,你现在都存入redis了,B、C链接上redis然后直接从redis里面取不可以吗

有N多理由反对采纳的答案。
首先发放票据和验证票据的过程不对(这个系统通常还要做双机热备等防单点失效,或者分布式之类的)
如其他人所说,100个系统难道说推送100个?超时什么的怎么搞?
如果有一个系统登出了,其他系统应该也要登出?
如果被修改了权限,只允许登录A,不允许登录B,怎么搞?

不存在跨域问题的。

  1. 进入a系统的时候,跳转去s系统。

  2. s系统验证账号后,让浏览器带着票据(在url参数里)跳转回a系统。

  3. a系统这时候被传入了票据,系统内部用curl之类的方法去s系统验证票据还要带上自身系统的key等证明a系统的这点验证合法性,如果是授权票据(即便登录了s系统,也不代表可以登录a系统,具体由s系统判断发放的票据登录权限),那么就让进入,否则就接着跳转回s系统的登录界面。

楼主可以部署一下某java版开源单点登录系统,了解具体用法和流程。也可以搞下OAUTH2.0之类的授权系统。

推荐使用UCenter或者OpenCenter,都可以轻松实现单点登录

b,c提供个获取token的接口,登陆成功刷调下就行

可以考虑用cookie来存储、传递

主站在登陆完成后,在登录服务器跳转回来后的那个页面加上跨域代码,同时发送给从站(或者说其他站点)即可,代码如下

<script src=xxxx.com?token=aaaaaa>

这样在xxxx里面即可获取token,处理验证即可

楼主的意思应该是:3个系统,跨域不知道怎么保存sessionid吧。 可以考虑下 UCenter 或者 PHP利用P3P实现跨域。

一般token是经过一些加密算法+salt算出来的,B、C接收到token使用同样的加密算法验证就可以了。

token不是被传回B、C系统了吗?可以直接连redis,规范点就将token放到参数或Header上请求S系统的专门接口。

把token值存入Redis。

  1. 用户在S系统登录后,通过一定算法生成一个key值,然后把token或用户登录信息以key-value形式存入Redis共享;
    2.运用特定算法,将key值加密以cookie形式存储在客户端;

3.当访问A、B等系统时,直接检测此cookie值,然后逆运算得到key值,进而获取token,若不存在则跳转到S系统登录;

登录成功后。肯定要去其他的站点发送 。我这边某某用户已经登录了。记录一下登录状态

不跨域的情况下,可以考虑把token 存到cookies 中

不管怎么说,总要有一个用户中心用来保存用户的数据的S系统。
1 用户从A系统登录时,向S系统请求接口,按照某些规则生成一个token。保存在S系统服务器的数据库或者redis都可以。
2 A系统将这个token用cookie保存下来。这个同一个客户端可以获取该cookie了。
3 用户进入B系统,获得cookie的token值,请求S系统,验证token的正确性。正确则B系统登录。

直接cookie存储不就可以了

一般像ucenter,登录的同时,通过js对所有入口进行一次登录函数的访问,生成对应是session,cookies.
那要是不这么做,感觉单靠写入好像不行,因为不同站点的cookies,session是不同的,不发起http访问还真不行。

你的S级系统就相当于是auth中的授权服务器,对于ABC三个系统需要分别授权,用户访问A系统, A系统去S系统请求用户的授权,用户登录S系统后授权返回A ,用户在访问B系统 因为之前已经登录过S系统,所以直接就是用户授权的页面授权登录就可以了,不知道这样能不能解决你的问题

用康盛的UCenter怎么样?

发表评论

电子邮件地址不会被公开。 必填项已用*标注