OAuth 2.0 原理与流程详解

OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版。

本文例子为 在多个不同域名的网站下,使用同一套用户中心体系,点击登录跳转到已搭建 OAuth2.0 的服务端后,用户授权登录。

流程:

(A)用户访问客户端,后者将前者导向认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的”重定向URI”(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的”重定向URI”,向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access_token)和更新令牌(refresh_token)。
(F)客户端用 access_token 向认证服务器获取用户信息

步骤详解:

搭建 OAuth2.0 的服务端 简称 i.com

步骤A

用户在 a.com 网站上点击登录,网站带上参数跳转到 i.com
参数:

response_type:表示授权类型,必选项
client_id:表示客户端的ID,必选项
redirect_uri:表示重定向URI,可选项
scope:表示申请的权限范围,可选项
state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。

例如:

GET
http://i.com/authorize?response_type=login&client_id= {%client_id%} &redirect_uri=http%3A%2F%2Fa%2Ecom
HTTP/1.1
Host: a.com

步骤B

i.com 根据 client_id 去数据库 client 表查找是否存在 client_id,存在则根据cookie或者其它方式验证用户是否在 i.com 为登录状态。
有登录则出现授权界面让用户确认是否授权,没有则进入正常用户帐号密码登录流程,登录成功后则出现授权界面让用户确认是否授权。


步骤C

当用户确认授权后,i.com 根据 client_id 搜出来数据 $data,生成 $code$redirect_uri$expires,等信息并保存到 code 表中,code有效期为60秒内,
最后跳转回 client 表中根据 client_id 搜索出来的 $data['redirect_uri']

$code = md5($client_id.$user_id.date("YmdHis",time()));
$redirect_uri = $data['redirect_uri'].'?code='.$code;
$expires = time()+60;
//保存数据到 code 表中

...

$url = $redirect_uri.'&client_id='$client_id.'&referer_url='.$_GET['redirect_uri'];
header("Location:".$url);

步骤D

i.com 收到 $_GET['code']$_GET['client_id'] 后,

POST http://i.com/token HTTP/1.1
Host: a.com
code= {%code%} &client_id= {%client_id%} &client_secret= {%client_secret%}

步骤E

服务器 i.com 接收到 codeclient_idclient_secret 后,验证 code 表,验证通过后生成 $access_token$refresh_token$expires, 保存到 token 表中后,发送的HTTP回复到 a.com,包含以下参数:

$access_token  = md5($client_id.$user_id.date("YmdHis",time()));
$refresh_token = md5($client_id.$client_secret.date("Ymd",time()));
$expires = time()+3600; //access_token有效期为1小时
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

    {
        "access_token" : "example",
        "token_type" : "example",
        "expires_in" : 3600,
        "refresh_token" : "example"
    }

access_token:表示访问令牌,必选项。
token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。


步骤F

a.com 用收到的 access_tokeni.com 获取用户信息并在 a.com 下存cookie或其它方式进行登录。


附上数据表

CREATE TABLE `oauth_client` (  
  `id` bigint(20) NOT NULL auto_increment,  
  `client_id` varchar(32) NOT NULL,  
  `client_secret` varchar(32) NOT NULL,  
  `redirect_uri` varchar(200) NOT NULL,  
  `create_time` int(20) default NULL,  
  PRIMARY KEY  (`id`)  
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;  

CREATE TABLE `oauth_code` (  
  `id` bigint(20) NOT NULL auto_increment,  
  `client_id` varchar(32) NOT NULL,  
  `user_id` varchar(32) NOT NULL,  
  `code` varchar(40) NOT NULL,  
  `redirect_uri` varchar(200) NOT NULL,  
  `expires` int(11) NOT NULL,  
  `scope` varchar(250) default NULL,  
  PRIMARY KEY  (`id`)  
) ENGINE=MyISAM DEFAULT CHARSET=utf8;  

CREATE TABLE `oauth_token` (  
  `id` bigint(20) NOT NULL auto_increment,  
  `client_id` varchar(32) NOT NULL,  
  `user_id` varchar(32) NOT NULL,  
  `access_token` varchar(40) NOT NULL,  
  `refresh_token` varchar(40) NOT NULL,  
  `expires` int(11) NOT NULL,  
  `scope` varchar(200) default NULL,  
  PRIMARY KEY  (`id`)  
) ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

**(文章写的估计外人都看不懂了,没关系,我是写给我自己看的。。。请原谅~)
** 配合用户中心同步机制可实现多网站同步登录(详情请用力戳我),方可实现一次登录,多个域名网站同步登录。






你可能感兴趣的:(php)