OAuth2是基于HTTP的认证API,一般与OAuth2搭配的API也是基于HTTP的REST风格API(比如新浪微博和github),很多人一定想过是否可以直接从浏览器端调用REST API。

我最近做了一些这方面的研究,因为OAuth2中有secret key的存在,所以纯粹的客户端是不行的,但是服务端仅仅参与认证过程,由浏览器去调用REST API则是完全可行的。

于是比如你想开发一个github应用,那么服务端只需要一个没有界面的Auth服务就可以了,大部分的工作可以让浏览器端完成,这个架构可以大大减轻服务器的压力,对于不熟悉后端语言的前端工程师来说,是个不错的选择。

首先传统的oauth过程是这样的:

首先由跳转到OAuth服务器的登录认证页面,进行登录或者授权(假如已经在别的地方登录,就只需要授权):

然后服务端通常会返回302跳转到一个带ticket参数的网址,这个网址一般是在OAuth服务器注册的地址,也有些OAuth允许客户端指定:

这样浏览器端拿到302后,会自动转到App服务器,因为请求的Query String里面带了ticket,App Server于是拿到了ticket。客户端对App Server的请求是非Https,这个ticket是不怕被截获的,因为ticket是一次性的,而且攻击者拿到了ticket没有secret key是没法去Oauth服务器骗取token的:

App Server再对Oauth Server发HTTP请求,带上Secret Key:

OAuth服务器会把access_token传给App Server:

原本如果只用服务端访问REST API,这个token保存在服务端就可以了,但是我们现在希望直接在浏览器端用XHR去访问REST API,所以我们必须把token传给浏览器端。

这时候问题出现了,对于大部分开发者而言,花钱买个证书走https是不现实的,而http请求中明文传递token是可能被截获的:

token中包含用户授权信息,只要黑客截获了token,就可以冒充用户身份去Oauth服务器为所欲为:

解决的办法是使用RSA在浏览器端生成一对RSA密钥,然后把公钥传给App Server(建议用cookie,非常方便),Server用公钥加密token后传回给客户端。

我使用的是斯坦福大学的RSA开源实现(这个真的是非常高质量的RSA实现,向斯坦福师生致敬)

http://www-cs-students.stanford.edu/~tjw/jsbn/

学者们的实现比较文艺,依赖关系稍微有些复杂,这里我把所有文件打了个包,方便大家下载:

/Files/winter-cn/RSA.rar

over,接下来在浏览器端去使用token吧。

github API 的一个开源实现,请看 https://github.com/wintercn/github.wind

 
 
好文要顶 关注我 收藏该文  

oauth 2的更多相关文章

  1. ASP.NET WebApi OWIN 实现 OAuth 2.0

    OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. OAuth 允许用户提供一个令牌, ...

  2. Vue.js——使用$.ajax和vue-resource实现OAuth的注册、登录、注销和API调用

    概述 上一篇我们介绍了如何使用vue resource处理HTTP请求,结合服务端的REST API,就能够很容易地构建一个增删查改应用.这个应用始终遗留了一个问题,Web App在访问REST AP ...

  3. 集成基于OAuth协议的单点登陆

    在之前的一篇文章中,我们已经介绍了如何为一个应用添加对CAS协议的支持,进而使得我们的应用可以与所有基于CAS协议的单点登陆服务通讯.但是现在的单点登陆服务实际上并不全是通过实现CAS协议来完成的.例 ...

  4. 简述 OAuth 2.0 的运作流程

    本文将以用户使用 github 登录网站留言为例,简述 OAuth 2.0 的运作流程. 假如我有一个网站,你是我网站上的访客,看了文章想留言表示「朕已阅」,留言时发现有这个网站的帐号才能够留言,此时 ...

  5. 自己开发实现OAuth做webapi认证

    看到园子里面有人写的OAuth,就想把自己实现的OAuth也分享一下,关于OAuth协议这里就不再赘述. 一.作为认证服务器,首先需要提供一个可以通过appid/appsecret来获取token这样 ...

  6. OAuth认证原理及HTTP下的密码安全传输

    很多人都会问这样一个问题,我们在登录的时候,密码会不会泄露?随便进一个网站,登录时抓包分析,可以看到自己的密码都是明文传输的,在如此复杂的web环境下,我们没有百分的把握保证信息在传输过程中不被截获, ...

  7. ASP.NET OAuth:解决refresh token无法刷新access token的问题

    最近同事用iOS App调用Open API时遇到一个问题:在access token过期后,用refresh token刷新access token时,服务器响应"invalid_gran ...

  8. ASP.NET OWIN OAuth:遇到的2个refresh token问题

    之前写过2篇关于refresh token的生成与持久化的博文:1)Web API与OAuth:既生access token,何生refresh token:2)ASP.NET OWIN OAuth: ...

  9. ASP.NET OWIN OAuth:refresh token的持久化

    在前一篇博文中,我们初步地了解了refresh token的用途——它是用于刷新access token的一种token,并且用简单的示例代码体验了一下获取refresh token并且用它刷新acc ...

  10. ASP.NET OAuth:access token的加密解密,client secret与refresh token的生成

    在 ASP.NET OWIN OAuth(Microsoft.Owin.Security.OAuth)中,access token 的默认加密方法是: 1) System.Security.Crypt ...

随机推荐

  1. HDU 5296 Annoying problem

    Annoying problem Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  2. oracle 存储过程 ,触发器练习

    /*以下代码是对emp表进行显示宽度设置 */col empno for 9999;col ename for a10;col job for a10;col mgr for 9999;col hir ...

  3. HTML5学习笔记3 内联SVG

    HTML5支持内联SVG 下面来介绍一下什么是SVG SVG可缩放矢量图形 可缩放矢量是基于可扩展标记语言(标准通用语言的子集),用于描述二维矢量图形的一种图形格式.它由万维网联盟制定,是一个开放标准 ...

  4. unity3d的GUILayout布局

    GUILayout默认采用线性布局,从上到下.可以参见<unity3d常用控件> 如果要实现横向布局,则需要添加如下代码: GUILayout.BeginHorizontal (); // ...

  5. centos 7 生成文件名乱码的问题如何解决?

    在应用脚本生成文件时,发现生成的文件名称出现乱码(似麻将一样).刚开始找来找去,以为是复制粘贴的原因,复制时复制了特殊字符导致的,结果修改源文件后发现生成的文件名还是乱码.后来在执行脚本时,提示&qu ...

  6. python-求直角三角形斜边

    设计一个求直角三角形斜边长的函数(两条直角边为参数,求最长边) 如果直角边边长分分别为3和4,那么返回的结果应该像这样: The right triangle third side's length ...

  7. pandas drop_duplicates

    函数 : DataFrame.drop_duplicates(subset=None, keep='first', inplace=False) 参数:这个drop_duplicate方法是对Data ...

  8. 用Jquery控制文本框只能输入数字和字母及jquery自定义方法$.fn

    封装成onlyNum(),onlyAlpha()和onlyNumAlpha()3个Jquery扩展方法,方便复用,由于里面一些JS代码涉及到了"禁用输入法,获取剪切板的内容",而& ...

  9. Java并发编程(一):并发与高并发等基础概念

    并发概念 同时拥有两个或者多个线程,如果程序在单核处理器上运行,多个线程将交替地换入或者换出内存,这些线程是同时存在的,每个线程都处于执行过程中的某个状态.如果运行在多核处理器上,程序中的每个线程都将 ...

  10. Yii2基础常用笔记

    表单验证规则写在model类里,例如: 通过表单输入的值给模型属性填充数据用模型对象的load方法. $model->load(Yii::$app->request->post())