第三方登录有很多,常见有新浪微博、QQ、微信、百度、支付宝等等,我们今天就来讲讲其中一个和其他登录有很大区别的微信登录,我们知道除了微信以外的其他第三方登录都支持账号密码输入的方式进行登录,但是微信登录并没有给我们提供这种方式,它只支持扫码登录,扫码登录在操作上给用户带来了极大的方便,我们甚至都不用知道我们的微信账号和密码只是简单的一扫就可以实现第三方登录,确实很方便;但是在使用场景上有很大的限制,下面我们就通过代码来进行分析。
要想接入微信登录首先要在微信开放平台https://open.weixin.qq.com/注册成为开发者并通过开发者资质认证后方可开发。
如图中所示,进入开放平台后可以选择移动应用和网站应用,这里我们以网站应用为例,当我们成功创建一个网站应用之后,我们会得到一个appid和secret,在接口调用中我们需要使用到这两个id;
第一步:请求CODE
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取当前完整路径
String requestUrl = request.getRequestURL().toString();
//获取当前路径中的方法
String requestUri = request.getRequestURI().toString();
//得到根路径
String rootPath = requestUrl.replaceAll(requestUri, "");
String backUri = rootPath+"/Authorize/callback.do";
backUri = URLEncoder.encode(backUri);
String url = "https://open.weixin.qq.com/connect/qrconnect?"+
"appid="+AuthUtil.APPID+
"&redirect_uri="+backUri+
"&response_type=code"+
"&scope=snsapi_login"+
"&state=123456#wechat_redirect";
System.out.println("url:"+url);
response.sendRedirect(url);
}
}
第三步:获取用户个人信息
public class CallbackServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String code = request.getParameter("code");
//通过授权后根据code获取access_token、openid
String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
AuthUtil.APPID,AuthUtil.APPSECRET,code);
JSONObject tempValue = AuthUtil.doGetStr(url);
String openid = tempValue.getString("openid");
String accessToken = tempValue.getString("access_token");
int index = -1;
if(openid != null && accessToken != null){
String infoUrl = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN", accessToken,openid);
JSONObject userInfo = AuthUtil.doGetStr(infoUrl);
System.out.println(userInfo);
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
当通过获取用户信息接口取到用户信息后我们就可以按照自己的业务自由发挥了,可以将微信用户的信息和第三方网站的账号进行绑定,之后我们再次扫码二维码的时候就可以以绑定的账号直接进行登录。
以上的实现方式主要是用于PC端的微信登录,因为在开始的时候我已经提到过微信登录只提供扫码登录,那如果是在手机端也要使用微信登录又该如何呢,这里我们以京东在微信浏览器中进行微信登录为例,如下图
我们可以看到,虽然在手机打开二维码无法去扫描它,但是微信浏览器提供了按住图片点击识别图片中的二维码依然可以进行登录,不过这种体验其实是打了折扣的,因为在手机端直接摆个二维码很多人都不知道要怎么做,所以微信的扫码登录只是比较适合在PC端进行登录时使用;如果想在手机端以更好的方式进行登录的话,就需要借助微信公众号再开发一个针对手机端的登录,另外要强调一下,这里所说的手机浏览器仅仅只是微信浏览器,其他手机浏览器都是不支持微信各种接口的。
公众号的登录代码更PC端比较类似,就不在这里贴代码了,下面主要说明一下,当既使用了微信开放平台又使用微信公众号同时开发微信登录、或者说在微信开放平台下有多个网站和移动应用想打通所以账号的时候,在开发中我们在获取用户信息的时候要区分openid和unionID
这里不得不谈到微信的用户隐私策略:每个接入微信的应用(公众号、APP)就像一个独立的商场,用户使用这些应用就像逛商场,商场用会员卡识别用户,类似的,我们根据商场名字为每个用户生成了一张专属会员卡(openid),每张会员卡只能在对应的商场才能够使用,你不能拿着沃尔玛的会员卡去华润万家积分。这是一种安全的授权方式,如果没有这个会员卡,直接暴露微信号,就相当于拿着身份证去逛商场,丢失一个会员卡号远比丢失身份证号要安全。
那么问题来了,都是万达集团,万达影城与万达商场希望做到会员卡通用。微信在这里做了一个打通机制,对于同一个企业,在用户属性里面加了一个企业属性(UnionID),方便同一个企业在不同的产品中识别到同一个用户。
这个机制伴随着微信联合登录已经在微信开放平台(open.weixin.qq.com)推出了。获得了开放平台认证的企业,可以绑定10个手机应用、10个网站、10个公众号,他们对应的用户信息也可以互联互通。
如果对上面的说明不是很明白的话,下面通过实例来说明
{
"subscribe": 1,
"openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
"nickname": "zapperbot",
"sex": 1,
"language": "zh_CN",
"city": "广东",
"province": "广州",
"country": "中国",
"headimgurl": "http://wx.qlogo.cn/mmopen/utpKYf69VAbCRDRlbUsPsdQN38DoibCkrU6SAMCSNx558eTaLVM8PyM6jlEGzOrH67hyZibIZPXu4BK1XNWzSXB3Cs4qg18/0",
"subscribe_time": 1375706487,
"unionid": "oTBn-jt2RQSHdBoJQYFSdnZo8BBQ"
}
{
"subscribe": 1,
"openid": "ouBMEj6WFnUFBIUKe83VD7s7dft9",
"nickname": "zapperbot",
"sex": 1,
"language": "zh_CN",
"city": "广东",
"province": "广州",
"country": "中国",
"headimgurl": "http://wx.qlogo.cn/mmopen/utpKYf69VAbCRDRlbUsPsdQN38DoibCkrU6SAMCSNx558eTaLVM8PyM6jlEGzOrH67hyZibIZPXu4BK1XNWzSXB3Cs4qg18/0",
"subscribe_time": 1375726425,
"unionid": "oTBn-jt2RQSHdBoJQYFSdnZo8BBQ"
}
上面有两条用户信息,分别是在同一开放平台下面的两个网站应用中获取的同一个微信用户的信息,我们可以看到两条信息除了openid不一样其他信息都是相同的,所以当我们有多个应用时要想账号统一需要使用unionid,以便于打通各个网站或应用之间的账号,如果只是单个应用使用openid也无妨,另外,如果是在微信公众号中想要获取unionid的话需要将微信公众号绑定到微信开放平台中。好了今天就先写到这里。