OAuth 介绍
介绍
OAuth 是一个关于授权(authorization)的开放网络标准。
引例
豪车一般配备两种钥匙:主钥匙和泊车钥匙。当你到酒店后,只需要将泊车钥匙交给服务生,停车的事情就由服务生去处理。与主钥匙相比,这种泊车钥匙的使用功能是受限制的:它只能启动发动机并让车行驶一段有限的距离,可以锁车,但无法打开后备箱,无法使用车内其他设备。这里就体现了一种简单的“开放授权”思想:通过一把泊车钥匙,车主便能将汽车的部分使用功能(如启动发动机、行驶一段有限的距离)授权给服务生。从而避免自己找停车位而耽误很多时间。
示例2,来自参考资料第一篇
有一个”云冲印”的网站,可以将用户储存在Google的照片,冲印出来。用户为了使用该服务,必须让”云冲印”读取自己储存在Google上的照片。问题是只有得到用户的授权,Google才会同意”云冲印”读取这些照片。那么,”云冲印”怎样获得用户的授权呢?传统方法是,用户将自己的Google用户名和密码,告诉”云冲印”,后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。
- “云冲印”为了后续的服务,会保存用户的密码,这样很不安全。
- Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。
- “云冲印”拥有了获取用户储存在Google所有资料的权力,用户没法限制”云冲印”获得授权的范围和有效期。
- 用户只有修改密码,才能收回赋予”云冲印”的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。
- 要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。
OAuth就是为了解决上面这些问题而诞生的。
把密码换成令牌(access_token),避免了问题1。凭令牌来访问用户的照片,也可以给令牌不同的权限,解决了问题3的范围问题。令牌可以设定有效时间,解决了问题3的有效期。令牌可以主动使之无效,解决了问题4,不用改用户密码。因为第三方应用只是存的令牌,没有密码,问题5也是不存的。
当然这都是个简单的模型,实际情况比这复杂。
RFC就定义了这个规范。
OAuth 2.0 协议
协议的参与者
- RO (resource owner): 资源所有者,对资源具有授权能力的人。
- RS (resource server): 资源服务器,它存储资源,并处理对资源的访问请求。
- Client: 第三方应用,它获得RO的授权后便可以去访问RO的资源。
- AS (authorization server): 授权服务器,它认证RO的身份,为RO提供授权审批流程,并最终颁发授权令牌(Access Token)。为了便于协议的描述,这里只是在逻辑上把AS与RS区分开来;在物理上,AS与RS的功能可以由同一个服务器来提供服务。
授权类型
OAuth为了支持这些不同类型的第三方应用,提出了多种授权类型
- 如授权码 (Authorization Code Grant)
- 隐式授权 (Implicit Grant)
- RO凭证授权 (Resource Owner Password Credentials Grant)
- Client凭证授权 (Client Credentials Grant)。
流程图
- (A)用户打开客户端以后,客户端要求用户给予授权。
- (B)用户同意给予客户端授权。
- (C)客户端使用上一步获得的授权,向认证服务器申请令牌。
- (D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
- (E)客户端使用令牌,向资源服务器申请获取资源。
- (F)资源服务器确认令牌无误,同意向客户端开放资源。
使用Google认证登录OAuth的示例
Client是自己的网站
RO 就是google账号
AS与RS就是google的登录服务器
操作步骤
0x01 开始之前
去创建一个 client ID,在https://developers.google.com/identity/sign-in/web/devconsole-project
0x02 引入google平台库
1 |
|
0x03 指定应用的ClientID
1 |
|
0x04 增加一个Google登录的按钮
1 |
|
0x05 获取授权用户概要信息
1 |
|
登出
1 |
|
效果
在页面上会有一个登录按钮
点击之后,会弹出一个登录页面。
提示在第三方应用上登录(图上是fortest)。
登录成功之后,就通过js,把授权用户概要信息打印出来。
当然,这个oauth的过程都是封装到js代码中。
后端程序获取
需要前台把这个token传到后端
关键代码如下
1 |
|
当然要引用google oauth库
1 |
|
参考
相关扩展及走的弯路
这里记录的是在查看google oauth各功能时走的岔道。
0x01 Identity Toolkit for Websites
先是使用的这个组件,Quick-start App for Java
各种配置,生成了一个oauth的clienid,还生了个服务账号的密钥。
样例代码很简单也有效,但没有报错,也没有继续,也不输出期望的信息。可能哪里没有配置对。
这个组件集成了yahoo,G+,facebook,paypal,mircrosof的第三方登录。ios,andorid,web的库完善。
0x02 google 官方示例
https://github.com/google/google-oauth-java-client.git
java 官方示例,先不能跑起来,因为LocalServerReceiver的实现端口总是变。
0x03 spring-boot 写的OAuth样例
Google OAuth 2.0 Sample Application
部署到服务器上,可以验证成功。但没有输出用户信息,也不能退出。也算是失败。容错上也不好。
在本地运行会超时错误。因为是spring-boot内部也是不好设置代理。
0x04 oauth2-cmdline-sample
https://github.com/google/google-api-java-client-samples.git
官方示例其中的oauth2-cmdline-sample,配置好密钥后,不是跑不起来。
查到LocalServerReceiver的实现端口总是变,而凭据的授权要指定url不能这样变,不然就出现redirect_uri_mismatch
错误。自己写的一个端口的实现类之后呢,又一直在authorize
方法止住。发现卡在TokenResponse response = flow.newTokenRequest(code).setRedirectUri(redirectUri).execute();
这个方法,无法访问服务google资源服务器的原因。然后修改了HttpTransport的默认对像HttpTransport newhttpTransport = new NetHttpTransport.Builder().setProxy(proxy).build();
。又卡在了tokenInfo的Tokeninfo tokeninfo = oauth2.tokeninfo().setAccessToken(accessToken).execute();
猜测也是网络问题,也没法重设httptransport。要本地电脑挂vpn,就没继续下去。
这个示例代码算是完整了用代码方式讲述google oauth的一般流程。