单点登陆实战,重新认识session

前言:

首先介绍下项目背景,我经手的项目呢,是一个音乐网站,看上去是一个网站,实际上是三个项目,首先是一个基于onethink开发的音乐分享平台,第二个是基于客客族的一个众包类型的平台,第三个是基于ecshop的商城。三个项目的分别使用三个二级域名。各自代码数据库独立。我接到的需求的就是,让用户只需一个账号就能在三个网站中都能使用。就是用上去像一个网站就对了。

当时想了很多种思路,我觉得主要的难点在于,网站已经是一个线上运营的项目了,已经有一定的用户。各个项目数据表的设计也不相同,对用户密码的加密方式也不同。更厉害的是其中有个项目的用户表是一张大表,里面有很多字段,记录着用户的各种信息。

步骤:

解决分两步走,无论用什么方法解决,必须实现的功能就两个,那就是:

  1. 单点注册
  2. 单点登陆

1.单点注册

首先,我们抛开老用户不管,首先新用户,一来注册。肯定只需一个地方注册就不用在别的地方注册了。那么我的思路是关闭二三站的注册,将全部的注册引导至第一站来注册。当第一站的代码执行到注册成功,写入数据表的步骤时,我添加两个curl带上用户的注册信息,访问我在二三站写好了的注册接口

 //注册成功
//注册成功要调用一个大注册方法
$bigData['username'] = $username;
$bigData['password'] = $password;
$bigData['email'] = $email;
//加入token,提高安全性
$bigData['token']=md5('xxxxxxxx');
$taskUrl = 'http://task.56sing.com?xxxxxxxxxx.php';
$shopUrl = 'http://shop.56sing.com/xxxxxxxxx.php';
//封装的curl方法,传入url和数据
$this->bigRegister($taskUrl, $bigData);
$this->bigRegister($shopUrl, $bigData);

由于curl是模拟浏览器访问url,所以也不存在跨域的问题,前端的控制台,也没办法捕获这次调用。我自我感觉还是比较安全的

2站和3站的接口接收到传来的数据,直接调用自己的注册方法就可完成注册了。这样一以来,用户就可以使用童颜的账号密码登陆三个站点了。

当时感觉还行啊,感觉这个思路走的通,所以我就打算继续用curl传账号密码,完成单点登陆。当代码写好了后,发现傻逼了。于是我冷静下来重新思考了的网站的登陆原理。

我开始回忆起来最初学习登录的思路,如下图

初学登陆

乍一看好像也没什么大问题,我通过curl将账号密码传入接口,接口收到账号密码后调用登陆方法,验证通过的话就写入session。没毛病啊?
这时候,我又有一个疑问了,当我把账号密码传入接口,通过验证完成登陆时,我的浏览器并没有访问2,3站的页面。那么当我去访问它的页面时。网站怎么知道我是我呢?(这个问题给了我灵感)

最后我将注意力集中到了session身上。我回忆起来,其实每个session在生成的时候,都会一个session_id存入cookie里。

  • 这个session_id就像是数组的键一样,有一个对应的值,这个值就存在服务器的内存中
那么登陆的原理就是:

我们结合http协议来看这个问题,
当我们向服务器发起请求,并带上账号密码,服务器接收到了账号密码,并验证。如果通过,就把登陆状态的值记录在session中,然后返回一个登陆成功的页面或者一个json。就在返回的时候携带了session_id 存入用户的浏览器中。这样,这个session登陆信息就只有刚刚登录的那个人的浏览器才能访问,就知道是谁登录,谁没登录了。

那么弄清了原理之后我们就想了一个思路(是一个二逼思路)


二逼思路

好了大家看一看就行了哈。我就不介绍了。

经过一番思考后,和网上查资料,我发现了一个问题,curl只是一个模拟浏览器访问一个url。并没有真正的浏览器存在。那么也就没存cookie的说法。那么我又将目光移向了ajax跨域请求
下面是行的通的思路(敲黑板,划重点)

可行的思路.png

看到这里,细心的朋友肯定发现了,我说这么多,还是没有说怎么搞定cookie的session_id嘛
下面介绍如何共享session_id的,我们从两个方面来说

1. 浏览器端(客户端)

当我发送加密账号密码时,我会带上当前浏览器中储存的cookie

   $.ajax({
        //登录接口的url
        url:data.loginData.task.url,
        type: 'POST',
        //异步请求
        async:true,
        //通过设置 withCredentials: true ,发送Ajax时,Request header中便会带上 Cookie 信息
        xhrFields:{
        withCredentials:true
        },
       //账号密码
       data:{
        'sing56':data.loginData.task.sing56,
        'sing':data.loginData.task.sing
       },
      success:function (response) {

       },
      error:function (reason) {
        console.dir(reason);
       }
   });
2. 服务器端

首先我们要解决允许跨域请求,大家都是知道的,随后能就要允许携带cookie了

//获取请求来源地址
$origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
//设置允许请求的数组
$arrAllow=['http://www.56sing.com','http://shop.56sing.com'];
//判断是否在允许请求数组中
if (in_array($origin,$arrAllow)) {
    //允许请求
    header('Access-Control-Allow-Origin:'.$origin);
}
//允许请求的方式为post
header('Access-Control-Allow-Methods:POST');
//允许携带cookie
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Headers:x-requested-with,content-type');

对应客户端的 xhrFields.withCredentials: true 参数
服务器端通过在响应 header 中设置 Access-Control-Allow-Credentials = true 来运行客户端携带证书式访问。通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie。
这里需要注意的是:
服务器端 Access-Control-Allow-Credentials = true时,参数Access-Control-Allow-Origin 的值不能为 '*'

那么这样做的效果就是
当我在第一站登录,调用2站的登陆接口时会传递一个session_id

image.png

当我进入第二站时,账号已经自动登陆,并且当前cookie中存储的session_id,正是我们传递过来的那一个

image.png

好了,本次单点登陆实战的介绍了就写到这里了,如果有什么地方不对,希望大神指正.谢谢。
参考三位大神的博客,在这感谢了:
kangjianrong
sueris
guodengh

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容