1.简单介绍
2.通过sessionKey_tokenKey维持登录状态
1.javaweb中如何去维持登录状态
(1).登录后 信息放入 session中
(2).页面内验证session中是否有登录信息
(3).如果有,不需要再次登录
(4).如果没有,跳转登录页面
(5).如果登录后点击注销,删除session中登录信息,并清除页面缓存(必要的)
2.javaweb中哪些情况我们的session会过期
(1).过期-->很长时间没有去访问网站
(2).主动关闭-->用处注销
(3).切换浏览器
3.登陆,返回用户信息
4.相关疑问
(1).sessionKey/tokenKey哪里来?
a.登录成功之后,后台返回.
(2).sessionKey/tokenKey生成有什么规则?
a.后台返回的,按照一定规则生成的(比如可以随机数生成一个24位以上的字符串)
(3).登录成功返回的sessionkey/tokenKey存到哪里?
a.保存到sp中就可以了
(4).sessionkey/tokenKey使用场景
a.有些协议需要用到登录信息,就需要看登录状态,就需要用到sessionkey/tokenKey,比如`支付协议`;
(5).如何使用sessionkey/tokenKey?
a.需要登录状态,判断sp中是否有sessionkey/tokenKey?
1.有:那当前是已登录状态,就把个人信息和sessionkey/tokenKey上传到服务器;
2.没有:跳到登录界面,让用户登录
(6).谁去判断sessionkey/tokenKey是否过期?
a.任何协议把sessionkey/tokenKey传到服务器.服务器会判断sessionkey/tokenKey是否过期?
1.过期:告知客户端,登录状态已过期,需要重新登录
2.未过期:可以使用当前的登录信息,继续走逻辑;
(7).为什么判断是否过期需要后台做?
a.因为前端可以修改当前时间?
(8).sessionkey/tokenKey多久过期?
a.这个具体看公司
(9).后台如何去判断sessionkey/tokenKey是否过期?-->拓展
a.分配sessionkey/tokenKey的时候记录时间
b.判断是否存在对应的sessionKey:如果不存在,是不是直接就是无效.
c.某一时刻,用户判断sessionkey/tokenKey是否过期的时候,拿着当前时间和sessionkey/tokenKey分配时间做比较
1. 大于指定时间:过期
2. 没有大于指定时间:未过期
5.登陆理解
3.通过支付场景看sessionKey_token的使用
1.模拟登陆
public class MainActivity extends Activity {
private Button mLogin;
private SPUtil mSpUtil;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLogin = (Button) findViewById(R.id.login);
mSpUtil = new SPUtil(MainActivity.this);
mLogin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
// TODO
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(
"http://mobileif.maizuo.com/user/login?username=18682036558&password=96e79218965eb72c92a549dd5a330112&type=1&userType=1&appType=31&agentID=0-maizuo&loginType=1&clientID=31&channelID=31");
HttpResponse response = httpClient.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
System.out.println("result :" + result);
// 得到sessionKey保存到sp中
JSONObject jsonObject = new JSONObject(result);
String sessionKey = jsonObject.optString("sessionKey");
// 保存到sp中
mSpUtil.putString("sessionKey", sessionKey);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
});
findViewById(R.id.pay).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 这个地方需要使用sessionKey,对应的一般操作,首先判断是否存在
String spSessionKey = mSpUtil.getString("sessionKey", "");
if ("".equals(spSessionKey)) {
Toast.makeText(getApplicationContext(), "请先登录", 0).show();
return ;
}
//接着就是把对应的sessionKey和userid和payinfo上传给服务器
}
});
}
}
4.短信验证码登录流程理解
1.验证码登录/注册_简单流程
(1).提交手机号
(2).下发短信验证码
(3).提交验证码
2.验证码登录流程理解
5.sharesdk sms短信验证码sdk的使用
1.短信验证码sdk:http://sms.mob.com/#/sms
2.集成步骤
(1).注册成为开发者
(2).添加应用
(3).下载demo
* SMSSDK-->lib工程
* SMSSDKSample-->demo
(4).运行demo查看效果-->用模拟器会报错
(5).集成到自己的应用里面;
3.使用demo
(1)查看demo或文档
(2)*查看官网文档详细步骤*
(3)配置文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.sharesdksms_demo_8"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.itheima.sharesdksms_demo_8.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- share sdk sms -->
<activity
android:name="com.mob.tools.MobUIShell"
android:configChanges="keyboardHidden|orientation|screenSize"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:windowSoftInputMode="stateHidden|adjustResize" />
</application>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
(4)MainActivity.java
public class MainActivity extends Activity {
private static final String appkey = "79b7f8d5c24c";
private static final String appsecret = "da67d6b2ef1694ae35e057afbd712f90";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SMSSDK.initSDK(this, appkey, appsecret);
setContentView(R.layout.activity_main);
findViewById(R.id.btn1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 打开注册页面
RegisterPage registerPage = new RegisterPage();
registerPage.show(MainActivity.this);
registerPage.setRegisterCallback(new EventHandler() {
public void afterEvent(int event, int result, Object data) {
// 解析注册结果
if (result == SMSSDK.RESULT_COMPLETE) {
@SuppressWarnings("unchecked")
HashMap<String, Object> phoneMap = (HashMap<String, Object>) data;
String country = (String) phoneMap.get("country");
String phone = (String) phoneMap.get("phone");
//这里就是验证通过.接着就是继续我们自己的逻辑就可以了
// 提交用户信息
// registerUser(country, phone);
}
}
});
}
});
}
}
6.开发平台理解
7.qqlogin_webview方式写前分析
1.网址: `http://wiki.connect.qq.com/sdk%E4%B8%8B%E8%BD%BD`
2.集成步骤(移动应用接入流程)
(1).注册成为开发者,登录;
(2).点击申请加入,创建应用;-->会分配appId,appKey
* APP ID:1104072093
* APP KEY:PzMWIM4GYZvxGRjd
(3).完善信息;
(4).下载demo.运行看效果;
(5).集成开发;
* webview方式(老方式):授权的时候是跳到了一个webview上去授权
* sso方式:如果手机里面装了qq.那就是单点登录的形式.如果没有装qq,就是跳到webview这种老方式;
* sso:单点登录
3.第三方登录
(1)用qq号/微信号/微博号去登录自己的应用
(2)核心:**就是拿到我们accessToken;**
(3)实际开发第三方登录的协议:`http://xxx?token=>xxx&type=x`,token就是我们授权之后返回的accessToken,type是为了区分不同登录渠道;
4.第三方登录
8.qqlogin_webview方式1,2步
1.实际开发3大步(app做的事情,实际开发,我们能把我这里的几个步骤,就可以完成开发工作)
(1).发起授权请求,让用户授权
(2).处理授权结果.拿到accessToken
(3).调用`第三方登录协议(自己公司定义)`,传递accessToken到app的server,**后续逻辑交给server **
2.qq登陆Demo
(1)清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.qqlogin_webview_8"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.itheima.qqlogin_webview_8.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- qqlogin_webview -->
<activity
android:name="com.tencent.tauth.TAuthView"
android:configChanges="keyboardHidden|navigation|orientation"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- <data android:scheme="auth"/> -->
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
(2)添加jar包
(3)MainActivity.java
见下一步
9.qqlogin_webview方式第3步
1.MainActivity.java
public class MainActivity extends Activity {
private Button mBtnLoginQQ;
protected String mAppid = "1104072093"; // 这个是老师自己申请的appId
// private String scope = "all";// 授权范围
// private String scope =
// private String mAppid = Config.qqAppId;
private AuthReceiver receiver;
/**
所有权限
// "get_user_info,get_user_profile,
get_simple_userinfo,add_share,
add_topic,list_album,
upload_pic,add_album";//
*/
// 授权范围
private String scope = "get_simple_userinfo"; // 权限范围
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerIntentReceivers();
mBtnLoginQQ = (Button) findViewById(R.id.btn1);
mBtnLoginQQ.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 1.发起授权请求-->让用户授权
auth(mAppid, "_self");
}
});
}
/**
* 打开登录认证与授权页面
*
* @param String
* clientId 申请时分配的appid
* @param String
* target 打开登录页面的方式:“_slef”以webview方式打开; "_blank"以内置安装的浏览器方式打开
* @author John.Meng<arzen1013@gmail> QQ:3440895
* @date 2011-9-5
*/
private void auth(String clientId, String target) {
Intent intent = new Intent(MainActivity.this, com.tencent.tauth.TAuthView.class);
intent.putExtra(TAuthView.CLIENT_ID, clientId);
intent.putExtra(TAuthView.SCOPE, scope);
intent.putExtra(TAuthView.TARGET, target);
// intent.putExtra(TAuthView.CALLBACK, CALLBACK);
startActivity(intent);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (receiver != null) {
unregisterIntentReceivers();
}
}
private void registerIntentReceivers() {
receiver = new AuthReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(TAuthView.AUTH_BROADCAST);
registerReceiver(receiver, filter);
}
private void unregisterIntentReceivers() {
unregisterReceiver(receiver);
}
/**
* 广播的侦听,授权完成后的回调是以广播的形式将结果返回
*
* @author John.Meng<arzen1013@gmail> QQ:3440895
* @date 2011-9-5
*/
public class AuthReceiver extends BroadcastReceiver {
private static final String TAG = "AuthReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Bundle exts = intent.getExtras();
String raw = exts.getString("raw");
String access_token = exts.getString(TAuthView.ACCESS_TOKEN);
String expires_in = exts.getString(TAuthView.EXPIRES_IN);
String error_ret = exts.getString(TAuthView.ERROR_RET);
String error_des = exts.getString(TAuthView.ERROR_DES);
Log.i(TAG, String.format("raw: %s, access_token:%s, expires_in:%s", raw, access_token, expires_in));
if (access_token != null) {
// 2.关心授权结果-->拿到accessToken
System.out.println("access_token:" + access_token);
// 07-25 06:03:00.560: I/System.out(5222): access_token:9AE33CD54165A5E2891FA36938828985
// 3.请求自己server定义的第三方登录协议
// http://mobileif.maizuo.com/user/thridlogin?token=xxx&type=1
String token = access_token;
new ThirdPlatformLogin().execute(token);
}
if (error_ret != null) {
Toast.makeText(getApplicationContext(), "授权失败", 0).show();
}
}
}
class ThirdPlatformLogin extends AsyncTask<String, Void, Void> {
@Override
protected Void doInBackground(String... params) {
try {
// 3.请求自己server定义的第三方登录协议
String token = params[0];
DefaultHttpClient httpClient = new DefaultHttpClient();
String format = "http://mobileif.maizuo.com/user/thridlogin?token=%s&type=1";
String url = String.format(format, token);
// 写死String url = "http://mobileif.maizuo.com/user/thirdLogin?token=4212A9E640A52314D7C2C451EDC830FB&type=1&agentID=0-maizuo&sign=null&version=3.0&clientID=31&channelID=31";
System.out.println("url:" + url);
HttpGet get = new HttpGet(url);
HttpResponse response = httpClient.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
System.out.println("result:" + result);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
}
2. 分三步
10.后台收到accessToken做了些啥
1.server拿到accessToken做了啥(锦上添花的了解一下)
(1)静默注册新用户或者返回已有用户用户信息
2.使用accessToken拿到用户在`第三方平台的唯一ID`;
* 判断`第三方平台的唯一ID`是否存在我们的`用户信息表`中;
* 存在:(之前使用qq号登陆过自己的系统)返回当前用户的用户信息
* 不存在:(用户还没有使用过此qq登陆过我们的系统)
3.调用相关的接口,拿到nickname,邮箱,头像(需要什么拿取什么);
11.qq登录_sso的形式
1.sso(单点登录)方式:如果手机里面装了qq.那就是单点登录的形式.如果没有装qq,就是跳到webview这种老方式;
2.开发Demo-----查看官方demo或文档
(1)两个jar包
(2)配置文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.qqlogin_sso_8"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.itheima.qqlogin_sso_8.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- qqlogin_sso -->
<activity
android:name="com.tencent.tauth.AuthActivity"
android:launchMode="singleTask"
android:noHistory="true" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tencent222222" />
<!-- 100380359 100381104 222222 -->
</intent-filter>
</activity>
<activity
android:name="com.tencent.connect.common.AssistActivity"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
(3)MainActivity.java
public class MainActivity extends Activity {
private static final String mAppid = "1104072093";
private Button mBtnQQLoginSSO;
public static QQAuth mQQAuth;
private Tencent mTencent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mQQAuth = QQAuth.createInstance(mAppid, this);
mTencent = Tencent.createInstance(mAppid, MainActivity.this);
mBtnQQLoginSSO = (Button) findViewById(R.id.btn1);
mBtnQQLoginSSO.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO
onClickLogin();
}
});
}
private void onClickLogin() {
// 2.接受授权结果-->拿到accessToken
IUiListener listener = new IUiListener() {
@Override
public void onError(UiError arg0) {// 授权失败
// TODO
}
@Override
public void onComplete(Object obj) {// 授权完成
// TODO
JSONObject jsonObject = (JSONObject) obj;
// 2.处理授权结果.拿到accessToken
String access_token = jsonObject.optString("access_token");
Toast.makeText(getApplicationContext(), access_token, 0).show();
System.out.println("access_token:" + access_token);
}
@Override
public void onCancel() {// 授权取消
// TODO
}
};
// mQQAuth.login(this, "all", listener);
// 1.发起授权请求
// loginWithOEM这个方法可以使用测试账号,测试账号在后台配置
// mTencent.loginWithOEM(this, "all", listener, "10000144", "10000144", "xxxx");
mTencent.login(this, "all", listener);
}
}
12.微博开发平台_添加应用
1.注册成为开发者
2.创建应用:`微博创建应用流程稍微麻烦一点.需要重点讲一下`
(1)需要上传我们keystore的签名信息,使用签名工具获取,和微信支付类似;
-------------获取签名工具:gen_signatures_weibo_ok.apk
(2)授权回调页(高级配置):随便写一个就可以,`但是需要不可以访问`
3.运行demo,查看一下.
4.集成微博第三方登录.
(1).拷贝jar包,或者关联lib工程
(2).查看androidMinfest.xml
(3).寻找关键代码
13.微博登录1,2步(只做了前两步)
1.查看官方demo或文档
2.Demo
(1)添加相关的jar包或关联lib
(2)清单文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.itheima.weibo8"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.itheima.weibo8.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- weibo login -->
<!-- 授权认证 -->
<activity android:name=".WBAuthActivity" />
<activity android:name=".WBAuthCodeActivity" />
<activity android:name=".WBShareMainActivity" />
<!-- 必须注册在微博授权,分享微博时候用到 -->
<activity
android:name="com.sina.weibo.sdk.component.WeiboSdkBrowser"
android:configChanges="keyboardHidden|orientation"
android:exported="false"
android:windowSoftInputMode="adjustResize" >
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>
(3)拷贝lib中资源文件
(4)MainActivity.java
public class MainActivity extends Activity {
private static final String APP_KEY = "2406388335";
private static final String REDIRECT_URL = "http://billy.itheima.com";
public static final String SCOPE = "email,direct_messages_read,direct_messages_write,"
+ "friendships_groups_read,friendships_groups_write,statuses_to_me_read,"
+ "follow_app_official_microblog," + "invitation_write";
/** 注意:SsoHandler 仅当 SDK 支持 SSO 时有效 */
private SsoHandler mSsoHandler;
private AuthInfo mAuthInfo;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuthInfo = new AuthInfo(this, APP_KEY, REDIRECT_URL, SCOPE);
mSsoHandler = new SsoHandler(MainActivity.this, mAuthInfo);
findViewById(R.id.btn1).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mSsoHandler.authorize(new AuthListener());
}
});
}
/**
* 微博认证授权回调类。
* 1. SSO 授权时,需要在 {@link #onActivityResult} 中调用 {@link SsoHandler#authorizeCallBack} 后,
* 该回调才会被执行。
* 2. 非 SSO 授权时,当授权结束后,该回调就会被执行。
* 当授权成功后,请保存该 access_token、expires_in、uid 等信息到 SharedPreferences 中。
*/
class AuthListener implements WeiboAuthListener {
@Override
public void onComplete(Bundle values) {// 授权完成
// 从 Bundle 中解析 Token
Oauth2AccessToken mAccessToken = Oauth2AccessToken.parseAccessToken(values);
if (mAccessToken.isSessionValid()) {
String accessToken = mAccessToken.getToken();
Toast.makeText(getApplicationContext(), accessToken, 0).show();
} else {
// 以下几种情况,您会收到 Code:
// 1. 当您未在平台上注册的应用程序的包名与签名时;
// 2. 当您注册的应用程序包名与签名不正确时;
// 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。
/* String code = values.getString("code");
String message = getString(R.string.weibosdk_demo_toast_auth_failed);
if (!TextUtils.isEmpty(code)) {
message = message + "\nObtained the code: " + code;
}
Toast.makeText(WBAuthActivity.this, message, Toast.LENGTH_LONG).show();*/
}
}
@Override
public void onCancel() {// 授权取消
// Toast.makeText(WBAuthActivity.this, R.string.weibosdk_demo_toast_auth_canceled,
// Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(), "授权取消", 0).show();
}
@Override
public void onWeiboException(WeiboException e) {// 授权异常
Toast.makeText(getApplicationContext(), "授权异常", 0).show();
// Toast.makeText(WBAuthActivity.this, "Auth exception : " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
14.oauth2.0协议介绍
1.oauth2.0授权流程
(A)用户打开客户端以后,客户端要求用户给予授权。
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器(比如qq登录,那就是腾讯)申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
2.oauth2.0涉及的角色
(1) Third-party application:第三方应用程序,本文中又称"客户端"(client),即上一节例子中的"云冲印"。
(2)HTTP service:HTTP服务提供商,本文中简称"服务提供商",即上一节例子中的Google。
(3)Resource Owner:资源所有者,本文中又称"用户"(user)。
(4)User Agent:用户代理,本文中就是指浏览器。
(5)Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。
(6)Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。