一:介绍
第三方登录有QQ、微信、微博、支付宝等等,如果现在自己的项目中实现这些登录,即可以使用友盟的sdk,也可以一个一个接入,各有各的有点,这里不做赘述。
今天和大家分享的是,在项目中实现微信登录,虽然微信官网给出了接入文档,但是我在接入的过程中,遇到一些问题,在此做出总结以便大家参考。主要讲微信snsapi_base静默授权与snsapi_userinfo网页授权的实现。
二:准备工作
移动应用微信登录是基于OAuth2.0标准协议构建的微信OAuth2.0授权登录系统。
在进行微信OAuth2.0授权登录接入之前,需要完成一下工作才可以开始介接入:
- 在微信开放平台注册开发者帐号;
- 拥有一个已审核通过的移动应用;
- 并获得相应的AppID和AppSecret;
- 申请微信登录且通过审核。
三:授权流程
微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:
- 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
- 通过code参数加上AppID和AppSecret等,通过API换取access_token;
- 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。
获取access_token时序图:
四:静默授权与网页授权的实现
1. 静默授权与网页授权的区别
网页授权:1
req.scope = @"snsapi_userinfo";
静默授权:1
req.scope = @"snsapi_base";
snsapi_base与snsapi_userinfo属于微信网页授权获取用户信息的两种作用域:
snsapi_base只能获取access_token和openID
snsapi_userinfo可以获取更详细的用户资料,比如头像、昵称、性别等
2. 获取CODE
再登录按钮的点击事件中写入一下代码:
1 | //构造SendAuthReq结构体 |
在AppDelegate的didFinishLaunchingWithOptions方法中注册:
1 | [WXApi registerApp:@"wx1234567890"]; |
“wx1234567890”为appid,请更换为自己项目的appid
拉起微信打开授权登录页如下图:
点击确认登陆,授权后回调 WXApiDelegate1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22-(void)onResp:(BaseReq *)resp
{
/*
ErrCode ERR_OK = 0(用户同意)
ERR_AUTH_DENIED = -4(用户拒绝授权)
ERR_USER_CANCEL = -2(用户取消)
code 用户换取access_token的code,仅在ErrCode为0时有效
state 第三方程序发送时用来标识其请求的唯一性的标志,由第三方程序调用sendReq时传入,由微信终端回传,state字符串长度不能超过1K
lang 微信客户端当前语言
country 微信用户当前国家信息
*/
if ([resp isKindOfClass:[SendAuthResp class]]) //判断是否为授权请求,否则与微信支付等功能发生冲突
{
SendAuthResp *aresp = (SendAuthResp *)resp;
if (aresp.errCode== 0)
{
NSLog(@"code %@",aresp.code);
[[NSNotificationCenter defaultCenter] postNotificationName:@"wechatDidLoginNotification" object:self userInfo:@{@"code":aresp.code}];
}
}
}
使用通知,将aresp.code传递到登录页面
3. 通过code获取access_token
在登录页面通过通知,获取到code之后,请求以下链接获取access_token:
1 | https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code |
参数说明:
- appid:应用唯一标识,在微信开放平台提交应用审核通过后获得
- secret:应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
- code:填写第一步获取的code参数
- grant_type:填authorization_code
网络请求返回的参数格式如下:
1 | { |
参数说明:
- access_token:接口调用凭证
- expires_in:access_token接口调用凭证超时时间,单位(秒)
- refresh_token:用户刷新access_token
- openid:授权用户唯一标识
- scope:用户授权的作用域,使用逗号(,)分隔
- unionid:当且仅当该移动应用已获得该用户的userinfo授权时,才会出现该字段
注意:
1、Appsecret 是应用接口使用密钥,泄漏后将可能导致应用数据泄漏、应用的用户数据泄漏等高风险后果;存储在客户端,极有可能被恶意窃取(如反编译获取Appsecret);
2、access_token 为用户授权第三方应用发起接口调用的凭证(相当于用户登录态),存储在客户端,可能出现恶意获取access_token 后导致的用户数据泄漏、用户微信相关接口功能被恶意发起等行为;
3、refresh_token 为用户授权第三方应用的长效凭证,仅用于刷新access_token,但泄漏后相当于access_token 泄漏,风险同上。还有就是要注意网络授权网页授权access_token 与 普通access_token的区别:
1、网页授权的access_token在每次获取openID时一起更新,在接口调用频次限制中为“无上限”;
2、普通access_token一般限制为2000次/日,需要自己保存起来并定时更新。
到这里同时获得access_token和openid,静默授权与网页授权操作都是一样的。根据官网文档,网页授权还可以进一步操作,获取用户更多详细信息。
4. 获取用户个人信息(UnionID机制)
此接口用于获取用户个人信息,开发者可通过OpenID来获取用户基本信息,接口如下:
1 | https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID |
参数说明:
- access_token:调用凭证
- openid:普通用户的标识,对当前开发者帐号唯一
正确的Json返回结果:1
2
3
4
5
6
7
8
9
10
11
12
13
14{
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1",
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
5. 静默授权获取到用户详细资料
在第3步通过snsapi_base,同时获得access_token和openid,
把这里的access_token和openid用于下面接口中:
1 | https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN |
参数说明:
- access_token:调用凭证
- openid:普通用户的标识,对当前开发者帐号唯一
- lang:国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语,默认为zh-CN
Json返回结果和snsapi_userinfo下获取的用户详情一样。
但是这个方法的前提是同一个公众号内,用户关注了,如果是其他公众号,还是需要用户点击授权的。