最近在业务中碰到一种Web端的需求,底层用户数据是相同的,但是用户使用的系统A和系统B分别在不同的域名下,并且访问A、B系统的时候需要校验登录信息,当发现用户没登录时,将用户引导到A系统的登录页进行登录。对应的可能会有和B系统一样的C系统、D系统等(如下图)。
1、单域名登录
在只有一个域名的情况下,当用户访问需要登录的系统页面时,系统会自动引导用户到同域名的登录页,用户登录后,登录中心会将登录凭证(通常会使用Cookie、Session等手段,此处以Cookie为例)写入到 a.com 这个域名的根目录下,此时所有 a.com 下的页面都将共享该登录凭证保持登录态。
接着登录中心,会根据returnUrl返回到用户访问的页面,此时页面再次检验登录并验证通过,将该页面的内容返回给用户。
在上述过程中,登录态一产生即是共享的,登录中心不需要其他下发的处理。以下使用 PHP Laravel 框架为基础,简单展示相关代码:
1)a.com 登录中心
$returnUrl = urldecode($request["returnUrl"]); #登录成功后,写入有效期为1小时的Cookie Cookie::queue("userCookie", "张三",60,"/","a.com",true,true); return redirect($returnUrl);//回跳用户访问页
2)a.com 系统
#验证用户登录 $userCookie = Cookie::get("userCookie"); $returnUrl = urlencode($request->fullUrl());//当前访问页面的地址 if(empty($userCookie)){ return redirect("/login?returnUrl=".$returnUrl);//跳转到登录页 }
2、多域名登录
回到文章最初的场景,当用户访问B系统(b.com)时,在登录凭证失效的情况下,B系统会优先跳转到登录中心(a.com)下的登录状态检测页(后续称之为 jump 页)检验登录态,如果未登录则跳转到登录页,否则会携带当前的登录凭证和 returnUrl 跳转到 B系统的添加凭证页面(后续称之为 loginAdd 页)。
接着,B系统也有了登录凭证,回跳到 returnUrl,重新检验登录并返回用户访问的页面。
在上面的过程中,登录态在 a.com 产生后,除了在本站点共享外,还会向来源平台进行状态下发,以此来保持其他平台与登录中心登录状态的一致。状态下发的过程,其实就是将登陆中心的登录凭证 Cookie 通过跳转的方式同步给来源平台。这里我们需要保证B、C、D等系统对于登录的校验逻辑需要和登录中心的保持一致,否则就算登录凭证相同,登录校验也可能会失败的。
代码如下:
1)a.com 登录中心登录
$returnUrl = urldecode($request["returnUrl"]); #登录成功后,写入有效期为1小时的Cookie Cookie::queue("userCookie", "张三",60,"/","a.com",true,true); return redirect("/jump?returnUrl=".urlencode($returnUrl));//跳转到jump
2)a.com 登录中心 jump
$returnUrl = urldecode($request["returnUrl"]); //验证用户登录 $userCookie = Cookie::get("userCookie"); if(empty($userCookie)){ return redirect("/login?returnUrl=".urlencode($returnUrl));//跳转到登录页 } #用户已登录跳转到目标页面的login/add $targetHost = parse_url($returnUrl, PHP_URL_HOST); $targetAddUrl = "/login/add?returnUrl=".urlencode($returnUrl)."&userCookie=".urlencode($userCookie); if(strpos($targetHost, ".b.com")!== false){ $targetAddUrl = "https://b.com".$targetAddUrl; } return redirect($targetAddUrl);//回跳目标访问页面的添加登录凭证页
3)b.com 目标访问系统的loginAdd,写入Cookie
$returnUrl = urldecode($request["returnUrl"]);//目标访问页面 $userCookie = urldecode($request["userCookie"]);//登录凭证 //写入登录凭证的Cookie Cookie::queue("userCookie", $userCookie,60,"/","b.com",true,true); return redirect($returnUrl);//回跳目标访问页面的添加登录凭证页
当然,当 b.com 接收到参数后,应该有相关的参数有效性校验,此处代码不再展开,大家可以根据实际情况进行差异化处理。
最后,本文的内容是基于 Cookie 的相关特性进行的,关于Cookie的使用可以查看相关资料,本文不做具体的介绍。