Android常用OAuth登陆与分享

2017-09-01  本文已影响0人  baolvlv

本文分两部分,第一部分介绍OAuth基础知识,第二部分展示一个Demo,使用百度OAuth SDK获取令牌信息与用户信息。

详细代码:github.com/Baolvlv/LearnAndroid/tree/master/OAuthDemo

一、OAuth基础知识

1.OAuth概述与运行流程

OAuth是关于授权(authorization)的开放的网络标准,用户允许第三方应用访问用户在某一网站上的私密资源,而不需将用户名与密码提供给第三方应用,通过OAuth访问可以限制第三方应用的范围和有效期。

2006年11月,OpenID不能满足twitter的委托授权

2007年4月,成立OAuth讨论小组

2007年11月,OAuth核心1.0最后的草案发布

2010年4月,OAuth1.0协议发布  RFC-5849

2012年12月,OAuth2.0协议发布 RFC-6749

OAuth 2.0不向下兼容OAuth 1.0

+--------+                               +---------------+

|        |--(A)- Authorization Request ->|   Resource    |

|        |                               |     Owner     |

|        |<-(B)-- Authorization Grant ---|               |

|        |                               +---------------+

|        |

|        |                               +---------------+

|        |--(C)-- Authorization Grant -->| Authorization |

| Client |                               |     Server    |

|第三方应用 |<-(D)----- Access Token ———|  授权服务器       |

|        |            (令牌)            +---------------+

|        |

|        |                               +---------------+

|        |--(E)----- Access Token ------>|    Resource   |

|        |                               |     Server    |

|        |<-(F)--- Protected Resource ---|               |

+--------+                               +———————+

2.OAuth授权模式

1.授权码模式(Authorization Code)

2.简化模式(implicit grant)

3.密码模式(resource owner password credentials)

4.客户端模式(client credentials)

授权码模式最完整严密,下图为授权码模式流程

+----------+

| Resource |

|   Owner  |

|          |

+----------+

^

|

(B)

+----|-----+          Client Identifier      +---------------+

|         -+----(A)-- & Redirection URI ---->|               |

|  User-   |                                 | Authorization |

|  Agent  -+----(B)-- User authenticates --->|     Server    |

|          |                                 |               |

用户代理   -+----(C)-- Authorization Code ---<|               |

+-|----|---+                                 +---------------+

|    |                                         ^      v

(A)  (C)                                        |      |

|    |                                         |      |

^    v                                         |      |

+---------+                                      |      |

|         |>---(D)-- Authorization Code ---------'      |

|  Client |          & Redirection URI                  |

|         |                                             |

|         |<---(E)----- Access Token -------------------'

+---------+       (w/ Optional Refresh Token)

Note: The lines illustrating steps (A), (B), and (C) are broken into

two parts as they pass through the user-agent.

Figure 3: Authorization Code Flow

Redirection URI———重定向URIOptional Refresh Token———刷新令牌

客户端发起两次请求,第一次以获得临时授权码作为结束,第二次以获得令牌作为结束

用户代理一般为浏览器

第一次请求参数:

第一次请求返回参数:


第二次请求参数:


请求方式:


第二次请求需要客户端的ID与密钥

现在普遍使用Https,当使用Https时,get和post请求安全性相同,get方式更加便捷。

使用http+Basic时,使用post方式更为安全,请求信息不可以在url中直接读取,post会将请求内容隐藏到请求实体中。

Content-Type:申请的表单类型

grant_type:请求实体

Http Basic Authentication:

访问一个特定的域名或url时,需要通过用户名和密码进行授权查看

发起请求时携带用户名和密码信息:

post方式和get方式:


代码实现:post方式:


第二次请求返回参数:


access_token:令牌,expires_in:令牌的有效时间段

refresh_token:刷新令牌,令牌实效后获取新的授权码

3.OAuth授权模式:简化模式,密码模式,客户端模式

简化模式流程:


没有后台服务器,或不能妥善保管第三方密钥情况下:

web-Hosted Client Resource:内嵌到浏览器中的客户端模块

User-Agent:用户代理,一般为浏览器

开始请求部分与授权码模式相同,返回值为重定向url和令牌,认证服务器将令牌放置在url的哈希值部分(#后面的部分)一般认为是未知信息,转发到服务端哈希值会被忽略掉。

web资源模块处理重定向url,返回给用户代理一个脚本用于解析,用户代理完成解析后,返回给客户端令牌信息。

通常会将web-Hosted Client Resource部分内嵌到Client,直接截取收到的信息,提取令牌信息简化流程

简化模式请求参数:


简化模式请求与返回值:


没有刷新令牌的原因:不能妥善保管第三方密钥,有刷新令牌降低安全性

密码模式请求流程:


用户需要将用户名与密码告诉客户端,但客户端不得存储密码

用户对客户端足够的信任,认证服务器没有其他的认证方式可以选择时采用。

密码模式请求参数:


密码模式请求具体内容:


密码模式请求返回值:


密码模式请求返回值与授权码模式返回值类似

客户端模式请求流程:

用户在客户端注册,客户端提出请求,授权不明显


客户端模式请求参数:


客户端模式请求具体内容:


客户端模式请求返回值:

客户端模式的返回值与其他几种认证类型类似:


4.OAuth更新令牌与相关问题:

更新令牌的方法:

1.重复一遍认证流程,用户手动输入用户名密码,发起请求认证

2.使用refreshtoken获取一个新的令牌,即刷新令牌操作

更新令牌参数:


更新令牌具体请求过程:


4.1授权码模式中请求参数state的作用:


当多个用户发起请求时,如果没有state参数,认证服务器只会返回临时授权码这一个参数,容易混淆。添加state参数可以将发起请求的的用户与获得的临时授权码一一对应。对应方式不可预期以提高安全性。

4.2为什么需要临时授权这一过程:

(1)redirect_url的安全性

redirect_url由第三方提供,是一个可访问的server表单地址。如果被截获,令牌会被截获

(2)redirect_url不如access token敏感,被截获不会泄漏用户的资源信息。

(3)如果没有临时授权码这一步,需要增加整个认证过程中的安全性

4.3 申请百度开发者账号以及百度OAuth

http://developer.baidu.com/wiki/index.php?title=docs/oauth

4.4获取百度令牌

http://developer.baidu.com/wiki/index.php?title=docs/oauth/authorization

4.5获取百度用户信息


二、android工程中获取百度令牌信息

http://developer.baidu.com/wiki/index.php?title=docs/oauth/showcase

下载安卓相关的sdk,解压后将其中的 jar包导入工程。

Project Structure->添加app的dependencies,添加百度相关的jar包

创建Baidu对象,调用authorize方法,第四个参数新建百度对话框监听器对象,实现其完成,异常,错误,取消四个方法.

//第一个参数为clientId,即API Key

finalBaidu baidu =newBaidu("PRheS6ajilCjg1muyFDGeCYz",this);

baidu.authorize(this, true, true, newBaiduDialog.BaiduDialogListener() {

@Override

public voidonComplete(Bundle bundle) {

//获取baidu对象中的AccessToken

refreshUI(baidu.getAccessToken());

}

@Override

public voidonBaiduException(BaiduException e) {

refreshUI("exception");

}

@Override

public voidonError(BaiduDialogError baiduDialogError) {

refreshUI("error");

}

@Override

public voidonCancel() {

refreshUI("cancel");

}

});

在主线程中,创建私有方法,用以刷新ui

private voidrefreshUI(finalString msg){

runOnUiThread(newRunnable() {

@Override

public voidrun() {

tvAccessToken.setText(msg);

}

内部类中只能调用外部类的final对象

三、android工程中获取百度个人信息

由于网络请求不能放在主线程中,所以通过以下两种方式实现:

1.在主线程中新建线程,使用百度提供的api,调用Baidu的对象的request方法返回json文本

启动线程

newThread(){

@Override

public voidrun() {

String url="https://openapi.baidu.com/rest/2.0/passport/users/getInfo";

try{

//使用baidu对象request时,第二个参数会自动将包含在对象中的access Token传入

finalString jsonText =mBaidu.request(url,null,"GET");

//返回对象为简单类(实体时)时,使用class型

finalUserEntity user =mGson.fromJson(jsonText,UserEntity.class);

//返回对象为泛型时,使用Type方式

finalUserEntity user =mGson.fromJson(jsonText,newTypeToken(){}.getType());

//在主线程中实现runnable接口,完成ui的更新

runOnUiThread(newRunnable() {

@Override

public voidrun() {

tvResult.setText(jsonText);

tvUser.setText(mGson.toJson(user));

}

});

}catch(IOException e) {

e.printStackTrace();

}catch(BaiduException e) {

e.printStackTrace();

}

super.run();

}

}.start();

其中通过使用Gson库,完成json文本到json实体的转换或json实体到json文本的转换

首先实体化Gson对象

mGson=newGson();

上一篇下一篇

猜你喜欢

热点阅读