整合用户篇—Oauth2理解与构造简单的系统

news2023/12/5 6:56:48

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

        当你运营越来越多的项目,每个项目的业务都不一样,每个需要使用到这些业务的用户就需要注册方能进行使用。如果用户还需要使用其他项目的功能,就必须还得注册使用。造成反复注册,反复登录的不友好体验。

       此时很多人都会想着使用ucenter等方式来整合用户,将用户放到一个数据中心来管理。所有的项目都将使用这一个公共的数据中心来运行。ucenter和各个项目之间通信将采用隐式api的方式进行通信,所有的行为都在后端进行,好比你的淘宝账号可以在天猫登录一样。在这里,假设你也做了一个业务网站,你的网站用户需要一键分享到他的淘宝主页中、或者需要读取卖家的商品信息,那么总不能在你的网站让用户提供他的淘宝账号密码,这显得尤为的不专业和不安全。oauth2就刚好解决了这一问题,让用户使用淘宝的快捷登录进行授权后由淘宝提供的接口来返回用户相关信息,并将这一信息在自己数据库中生成对应的一份关联起来,这一切就变得比较安全,比较合理了。

        本文的主题是oauth2,oauth是一种协议,2是版本,即oauth2是一个协议标准,将多个项目整合起来,提供所需的接口通信,oauth2可以建立在ucenter上可以建立在单独业务上,总之他只是一种协议,具体关于该协议的介绍请直接浏览官网或者百科介绍。

        上文中有提到淘宝的快捷登录,那么对应就还有QQ快捷登录(QQ互联)、新浪快捷登录、google账号登录等。这样一来就可以使得原本来自QQ、来自google的用户无需在你的网站进行注册后,直接间接使用原先的媒体账号登录就可以在你的网站访问。用google举例,你的网站可以使用google账号快捷登录,并且可以获得google提供的一些接口服务,那么将这一关系中的google称为server端,你的网站称之为client端,下文将client称为应用。
        当前主要是说自己构造一个oauth2 server端,就是上文中所提到的QQ互联、微博等,可以给自己的其他应用或者开放给第三方应用来提供方便用户管理的一个系统。


上图是Oauth2运行流程,描述了四个角色之间交互的方式。摘自RFC 6749

(A):Client 向 Resoure Owner 请求授权。可以理解为用户发起请求。

(B):在Server端用户同意给予 Client 端授权,并返回至 Client 端告知。

(C):Client携带Authorization Grant 向Authorization Server请求获取Access Token。

(D):授权验证通过后,返回Access Token。

(E):Client携带Access Token向Resource获取相关资源,例如头像、昵称、相册等。

(F):Access Token 验证 通过后 Resource Server 所需获取资源。

 

了解了基本的流程后,来简单构造一下数据表。

/**
 * app 应用
 */
CREATE TABLE uc_app(
app_id int primary key auto_increment,
app_sign varchar(20) NOT NULL DEFAULT '' COMMENT '应用唯一ID',
app_secret varchar(60) NOT NULL DEFAULT '' COMMENT '通信密码',
app_name varchar(20) NOT NULL DEFAULT '' COMMENT '应用名称',
app_desc varchar(60) NOT NULL DEFAULT '' COMMENT '应用描述',
app_providers varchar(60) NOT NULL DEFAULT '' COMMENT '提供商',
app_url varchar(255) NOT NULL DEFAULT '' COMMENT '官方主页',
app_type tinyint NOT NULL DEFAULT '1' COMMENT '应用类型 1.官方应用 2.第三方应用',
app_status tinyint NOT NULL DEFAULT '1' COMMENT '应用状态 1.正常运行 2.停止运行 5.审核中',
allow_domain varchar(255) NOT NULL DEFAULT '' COMMENT '授权域名',
allow_ip varchar(100) NOT NULL DEFAULT '' COMMENT '允许IP',
release_time int(10) NOT NULL DEFAULT '0' COMMENT '发布时间',
expire_time int(10) NOT NULL DEFAULT '0' COMMENT '失效时间',
UNIQUE KEY (`app_sign`)
);

/**
 * user_key 用户授权code
 */
CREATE TABLE uc_user_key(
id int primary key auto_increment,
code_key varchar(60) NOT NULL DEFAULT '',
app_sign varchar(20) NOT NULL DEFAULT '' COMMENT '应用唯一ID',
user_id int NOT NULL DEFAULT '0' COMMENT '用户ID',
redirect_uri varchar(255) NOT NULL DEFAULT '' COMMENT '回调URI',
scope varchar(20) NOT NULL DEFAULT '' COMMENT '申请权限范围',
state varchar(20) NOT NULL DEFAULT '' COMMENT '客户端状态',
release_time int(10) NOT NULL DEFAULT '0' COMMENT '生成时间',
expire_time int(10) NOT NULL DEFAULT '0' COMMENT '失效时间',
status tinyint NOT NULL DEFAULT '0' COMMENT '状态:0.待验证 1.已验证 2.已过期',
UNIQUE KEY(`code_key`)
);

/**
 *	uc_user_token
 *	用户访问权限表
 */
CREATE TABLE uc_user_token(
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT NOT NULL DEFAULT '0' COMMENT '用户ID',
app_sign VARCHAR(20) NOT NULL DEFAULT '' COMMENT '应用唯一标识',
access_token VARCHAR(60) NOT NULL DEFAULT '' COMMENT '权限操作TOKEN',
scope VARCHAR(20) NOT NULL DEFAULT '' COMMENT '所申请权限',
release_time INT(10) NOT NULL DEFAULT '0' COMMENT '生效时间',
expire_time INT(10) NOT NULL DEFAULT '0' COMMENT '失效时间',
UNIQUE KEY(user_id, app_sign)
);

 

程序流程

1.第三方应用选择快速登录,跳转至Server端进行授权登录。

url:http://ucenter.example.com/authorize?response_type=code&client_id=f2292b656df429d4&state=xyz&
redirect_uri=http%3a%2f%2fclient.example.com%2fuser.php

如果是已经登录状态,则自动跳过登录过程,否则展现登录页面,引导用户进行登录。

2.用户登录完毕之后,生成一个相对用户相对client_id相对回调信息的记录到数据库,并将这条记录的唯一值code返回给应用。

url:http://client.example.com/user?code=Q8GlvX4lS3Fy3KBHpQro&state=xyz

3.用户携带上一步获取的code, 到服务端进行授权,获取通信口令。

参数是否必须含义
grant_type必须授权类型,此值固定为“authorization_code”
client_id必须第三方应用的app_sign。
client_secret必须第三方应用的app_secret。
code必须上一步返回的authorization code。
redirect_uri必须与上一步中的回调地址一致。
url:http://ucenter.example.com/token
Method:POST
Form Data
grant_type:authorization_code
code:Q8GlvX4lS3Fy3KBHpQro
redirect_uri:http://client.example.com/user.php

4.服务端校验code过后,颁发通信令牌 access_token 。

Response: 
{
    response: - {
        code: 200,
        msg: "success"
    },
    datas: - {
       "access_token":"kIJAkUd31F58nGpknvoW3L4r3S21koNd9Lk0rfcn",
       "token_type":"example",
       "expires_in":3600,//有效期
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",//可选项,存在表示下一次使用该令牌获取资源
    }
}

5.应用使用access_token 向服务端提供的接口来获取数据,例如获取当前登录用户信息。

url:http://ucenter.example.com/user/getInfo?access_token=kIJAkUd31F58nGpknvoW3L4r3S21koNd9Lk0rfcn

6.服务端验证授权之后,将所需数据返回给应用。

Response: 
{
    response: - {
        code: 200,
        msg: "success"
    },
    datas: - {
        user_id: 5,
        user_name: "ellermister",
        full_name: "E先生",
        headimg: "http://q.qlogo.cn/headimg_dl?bs=qq&dst_uin=11733685&spec=100",
        address: "北京市北四环西路58号理想国际大厦"
    }
}

 

7.更新通信令牌方式借用第3步的,参数 grant_type 更改为 refresh_token,去掉code、redirect_uri,返回结果中增加 refresh_token 项,之后再次获取资源将使用refresh_token作为新的令牌。

 

补充下自己所遇到的问题,在前端实现上,会将用户从C站点引导到S站点进行登录并授权,随后返回C站点。

此过程中比较合理也是常见的过程则是,在C站点上点击登录,弹窗S站点,登陆授权完毕后关闭S站点,C站点进行刷新即可登录成功。该问题涉及JS跨域刷新父窗口,解决方案如下。

//C站点弹出JS
window.open('http://ucenter.example.com/authorize?response_type=code&
client_id=f2292b656df429d4&state=xyz&redirect_uri=http%3A%2F%2Fclient%2Eexample%2Ecom%2Fuser.php',
'弹出层页面','top=100,left=400,width=800,height=600,toolbar=no,menubar=no,scrollbars=yes,
resizable=yes,location=no,status=no');

//S站点授权登录后,执行JS
url = 'http://client.example.com/user.php?code=xxxx&state=xyz';//回调URL
try{  
        window.parent.opener.location.reload();  
        window.parent.close();  
}catch(e){
        window.parent.opener.location = url;  
        window.parent.opener = null;  
        window.parent.close();  
}

 

从登录到授权到获取资源基本流程也即是如此,期间的access_token 是针对用户的,当然也可以是针对全局的,类似于微信的做法。根据实际项目情况,做法不可能一成不变,本文只是提供了一个基本的流程,让初次了解的人能够快速的了解这个授权过程。

本文仅供参考理解,如有错误,请指正!

 

延伸阅读:

The OAuth 2.0 Authorization Framework  https://tools.ietf.org/html/rfc6749

理解OAuth 2.0  http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

OAuth 2 开发人员指南  http://www.oschina.net/translate/oauth-2-developers-guide

 

转载于:https://my.oschina.net/u/2366984/blog/749858

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://nwjs.net/news/300115.html

如若内容造成侵权/违法违规/事实不符,请联系七分地网进行投诉反馈,一经查实,立即删除!

相关文章

s7edge出现android停止,三星S7 Edge升级安卓7.0出现了这个问题!

三星从1月开始陆续为Galaxy S7、S7 Edge推送了Android 7.0(Nougat)系统更新,升级后的功能增加和提升不少,不过新系统也并不是十全十美,有用户反馈升级后的手机续航时间明显减少。对此,国外媒体进行了针对性测试,使用搭…

mac下完全卸载postgresql的方法

2019独角兽企业重金招聘Python工程师标准>>> 这里针对的是 9.3 版本。如是其他版下面的仅供参考。 1、如果是postgresql.app的形式,这个简单,跟其他app一样,删除app即可。 2、如果是使用installer图形界面方式安装的。则需要打开…

服务依赖性

转载于:https://www.cnblogs.com/coland/p/5500671.html

手动配置Hibernate的方法

2019独角兽企业重金招聘Python工程师标准>>> 前言:一直习惯用MyEclipse自动生成Hibernate,但是对手动配置一直不甚了解,都不好意思说自己是搞java的。所以赶紧复习了一下手动配置,并记录在此,以便常回来看看…

页面回顶

web开发中经常有页面回顶的需求&#xff0c;近期使用&#xff0c;代码较简单&#xff0c;但是很实用&#xff01; html: <a id"goTop" class"go-top" href"#header"><span class"go-top-inner"></span> </a> …

线刷一加5t android 9,一加5/5T 氢OS 9.0稳定四版 侧边工具 通知特效 Magisk 极速流畅 简约实用-刷机之家...

详情一加5/5T刷机包是小编推荐给大家使用的一款线刷包软件&#xff0c;功能丰富&#xff0c;一加5/5T 氢OS 9.0稳定四版 侧边工具 通知特效 Magisk 极速流畅 简约实用 是一加5/5T手机刷机的小帮手&#xff0c;有需要的朋友们不要错过!!刷机需知<<<<•一加手机的刷机…

mysql “group by ”与order by的研究--分类中最新的内容

这两天让一个数据查询难了。主要是对group by 理解的不够深入。才出现这样的情况这种需求&#xff0c;我想很多人都遇到过。下面是我模拟我的内容表我现在需要取出每个分类中最新的内容 select * from test group by category_id order by date结果如下明显。这不是我想要的数据…

python3 字符串格式化

字符串的格式化方法分为两种&#xff0c;分别为占位符(%)和format方式。占位符方式在Python2.x中用的比较广泛&#xff0c;随着Python3.x的使用越来越广&#xff0c;format方式使用的更加广泛。 一 占位符(%) %d 实例(Python3.0)&#xff1a; age 29 print("my age is …

SAX解析XML文件

就目前来说&#xff0c;有三种方式可以解析XML文件&#xff1a;DOM、SAX、StAX。DOM将整个XML文件加载到内存中&#xff0c;并构建出节点树&#xff1b;应用程序可以通过遍历节点树的方式来解析XML文件中的各个节点、属性等信息&#xff1b;这种方式便于对XML节点的添加修改等&…

用 namspace 隔离 DHCP 服务 - 每天5分钟玩转 OpenStack(90)

Neutron 通过 dnsmasq 提供 DHCP 服务&#xff0c;而 dnsmasq 如何独立的为每个 network 服务呢&#xff1f; 答案是通过 Linux Network Namespace 隔离&#xff0c;本节将详细讨论。 在二层网络上&#xff0c;VLAN 可以将一个物理交换机分割成几个独立的虚拟交换机。 类似地&a…

linux内存管理基本概念

1. Linux物理内存三级架构 对于内存管理&#xff0c;Linux采用了与具体体系架构不相关的设计模型&#xff0c;实现了良好的可伸缩性。它主要由内存节点node、内存区域zone和物理页框page三级架构组成。 • 内存节点node 内存节点node是计算机系统中对物理内存的一种描述方法&am…

华为鸿蒙10月17日,华为宣布10月17日重磅新机:鸿蒙系统+全球首发屏下摄像头...

今年华为手机太多大招&#xff0c;Mate30系列旗舰才开售不久&#xff0c;最近又曝光了一款顶级旗舰机&#xff0c;从曝光的真机渲染图来看&#xff0c;这款神秘机型将于10月17日在法国发布&#xff0c;手机渲染图四周超窄边框设计&#xff0c;值得注意的是手机右上角反光条纹&a…

linux 内存管理 page fault带来的性能问题

Linux进程如何访问内存 Linux下&#xff0c;进程并不是直接访问物理内存&#xff0c;而是通过内存管理单元(MMU)来访问内存资源。 原因后面会讲到。 为什么需要虚拟内存地址空间 假设某个进程需要4MB的空间&#xff0c;内存假设是1MB的&#xff0c;如果进程直接使用物理地址…

Linux 自动重启进程

Js代码 #!/bin/sh echo "Current DIR is " $PWD # ignore signal hup int quit tstp trap "" 1 2 3 24 start_server() { ulimit -c unlimited # export LD_LIBRARY_PATHpwd/deps/capn/libs:$LD_LIBRARY_PATH # rm -f *.pid # nohu…

Lucene学习笔记:Field.Store.* 域存储选项

2019独角兽企业重金招聘Python工程师标准>>> Store.YES&#xff1a; 指定存储域值。该情况下&#xff0c;原始的字符串值全部都被保存在索引中&#xff0c;并可以由IndexReader类恢复。该选项对于需要展示搜索结果的一些域很有用(如URL、标题或数据库主键)。如果索引…

第四次作业 孙保平034 李路平029

用C编写一个学生成绩管理系统 1、可以实现以下功能&#xff1a; cout<<"〓〓〓〓〓〓〓〓〓★ ☆ 1.增加学生成绩 ☆ ★〓〓〓〓〓〓〓〓〓"<<endl; 2、用链表存储信息 * 程序头部的注释结束 3、约定的规范&#xff1a; 1界面设计简介&#xff0c;人性化…

linux sar命令 性能监控

目录 1. CPU资源监控 2. inode、文件和其他内核表监控 3. 内存和交换空间监控 4. 内存分页监控 5. I/O和传送速率监控 6. 进程队列长度和平均负载状态监控 7. 系统交换活动信息监控 8.统计网络信息 9. 设备使用情况监控 10.常用命令汇总 sar命令常用格式 sar [optio…

android绘制高亮区域,实现高亮某行的RecyclerView效果

最终效果全部代码&#xff1a;github方式有二组合控件&#xff0c;RecyclerView View自定义RecyclerView1中只需要控制View&#xff0c;但是不好封装。2中需要重写RecyclerView中一些东西&#xff0c;最终就是一个CustomRecyclerView。所以采用的是第二种方法。代码100来行。主…

Android App监听软键盘按键的三种方式

前言: 我们在android手机上面有时候会遇到监听手机软键盘按键的时候&#xff0c;例如&#xff1a;我们在浏览器输入url完毕后可以点击软键盘右下角的“GO”按键加载url页面&#xff1b;在点击搜索框的时候&#xff0c;点击右下角的search符号键可以进行搜索&#xff1b;或者在全…

常用元素位置与大小总结

偏移量 offsetHeight: 元素在垂直方向占据的空间大小 > 内容高度 上下padding 上下boderoffsetWidth: 元素在水平方向占据的空间大小 > 内容宽度 左右padding 左右boderoffsetTop: 元素外边框距离offsetParent的上内边框的距离offsetLeft: 元素外边框距离offsetParen…