移动端(android)
1.在友盟对各平台封装的基础上再次封装,直接一个回调拿到第三方平台token,openid,unionid,nickname等信息.
这一个方法中包含了用户点击授权拿token,根据token拿个人信息两个步骤.
UmengUtil
//其他平台如loginByWeixin(this, new AuthCallback()
UmengUtil.loginBySina(this, new AuthCallback() {
@Override
public void onComplete(int var2, SinaInfo info) {
Log.e("dd",info.toString());
}
@Override
public void onError( int var2, Throwable var3) {
}
@Override
public void onCancel( int var2) {
}
});
2.然后,把必要的信息发送到服务端
服务端
拿到token,openid等关键信息,调用各平台的api进行信息核对校验,
如果通过,执行下一步:
根据第三方的openid/unionid去我们的数据库查阅,
如果没有账户,则生成新的账户.如果有账户,就不用生成.
最后,将账户个人信息取出,返回给客户端.
这样,就完成了登录操作.
信息校验的api:
校验的规则一般都是: 根据客户端传来的token去各平台拿openid,然后与客户端传来的openid比对,如果一致,就代表客户端数据没问题,校验无误.
sina
OAuth2/get_token_info
查询用户access_token的授权相关信息,包括授权时间,过期时间和scope权限。
URL:https://api.weibo.com/oauth2/get_token_info
HTTP请求方式:POST
请求参数
access_token:用户授权时生成的access_token。
返回数据
{ "uid": 1073880650, "appkey": 1352222456, "scope": null, "create_at": 1352267591, "expire_in": 157679471 }
微信
获取用户基本信息(包括UnionID机制)
注: 在微信账户体系中,unionid才是一个微信账户的唯一标识(而openid是跟公众号,服务号等发生关联产生的),所以微信的校验是通过token和openid来获取unionid,然后与客户端传来的unionid进行比对校验.
http请求方式: GET
https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
返回说明
正常情况下,微信会返回下述JSON数据包给公众号:
{ "subscribe": 1,
"openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M",
"nickname": "Band",
"sex": 1,
"language": "zh_CN",
"city": "广州",
"province": "广东",
"country": "中国",
"headimgurl": "[http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0](http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0)",
"subscribe_time": 1382694957,
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL",
"remark": "",
"groupid": 0}
获取用户OpenID_OAuth2.0
1 请求地址
PC网站:https://graph.qq.com/oauth2.0/me
WAP网站:https://graph.z.qq.com/moc2/me
2 请求方法:GET
3 请求参数:access_token
4 返回说明
PC网站接入时,获取到用户OpenID,返回包如下:
callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} );
注意解析openid时要将外层括号去掉才能拿到json.
永久登录的实现
问题
第三方授权和获取信息时,友盟工具会将相关信息在本地保存一份,以实现下次不用再吊起授权界面让用户再次点击.
但是,第三方token都是有过期时间的.超过了这个时间,授权界面是会被吊起的,这给用户看起来就好像莫名其妙掉线了,体验非常不好,那么,要怎么实现移动端第三方登录的永久登录呢?
一个解决方式
将第三方登录转变成账号密码登录:
在这台手机上第一次用第三方登录时,当然是吊起授权界面.
当服务端判定登录成功时,返回第三方账户体系的用户id(openid/unionid)或者内部账户体系的uid,和服务端生成的一个密码(UUID等算法ramdom出来,反正不用用户记)
客户端拿到这两个数据,加密后保存到本地,下次进入app时,直接用这两个来登录.
更进一步
为了避免每次都传输用户名密码(即使加了密,在网络暴露太多也不好),可以在登录成功后,服务端生成一个token和规定其有效期(设置长一点,十几天一个月之类的),并下发,
每次客户端拿本地token,判断有效期,在有效期内用token登录或者作为登录验证,过期就用用户名密码登录.
短时频繁登录,以及多台设备抢登的处理
session处理
验证用户名密码或者token通过后,如果同一个user的原session还存在:
先判断是否为同一个ip,如果不是,kill原session,创建新的session.
如果是原ip,就不必创建新的session.
多台设备抢登问题
两台手机相隔很短的事件先后登录同一个账户,如果移动端实现了对用户完全透明的过期重登机制,那么还是会出现看起来两台手机同时登录同一个账户,而对于服务端来说,就是不断地在创建session,销毁session.
怎么处理呢?
服务端的响应多增加一个错误码类别:
原先的:登录token过期一个code
增加的: 其他设备登录的一个code
客户端拿到第二个code时,可以不再做自动重新登录,而是像QQ一样弹出notification通知用户,让用户主动选择.