如下图所示,详解各步骤:
1、用户请求登录;
2、请求获取二维码。请求地址:https://qrlogin.taobao.com/qrcodelogin/generateQRCode4Login.do?from=alimama,from参数代表来源,本示例演示的是阿里妈妈,其他来源请自行摸索;
3、返回二维码地址与lgToken。执行第二步操作,淘宝网会返回这样的JSON:
{
success: true,
message: "null",
url: "//img.alicdn.com/tfscom/TB1Rb1yQpXXXXXTapXXwu0bFXXX.png",
lgToken: "0e7fdfec57971ab22759ef2a0e420afb",
adToken: "1877bc503d6d23555241d4df3b6d6fc7"
}
其中url就是登录二维码的地址,lgToken用于后续登录校验,其他响应参数请忽略;
4、渲染二维码,等待用户扫码。该步骤主要是将淘宝网返回的二维码可视化渲染到前台用户,可以采用网页展示,也可以本地应用程序方式把二维码的图片给呈现出来,等待用户的扫描操作;
5、根据lgToken,开始登录状态验证。在等待用户扫描操作的过程中,要同时开始用户登录状态的验证,该操作是异步执行的。
5.1 先校验二维码登录状态,二维码登录状态验证地址:https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do,
两个参数分别是:
defaulturl,其值写死为:http://login.taobao.com/member/taobaoke/login.htm?is_login=1
lgToken,其值为第2步返回的lgToken值。
循环请求校验地址,每次请求都会返回类似下面的json:
{"code":"10000","message":"login start state","success":true}
其中,code=10004表示二维码已过期;code=10006会返回url,表示用户扫码确认登录
5.2 当code=10006,获取url,带上返回的cookie请求该url。特别注意,淘宝网为进行不同站点的session同步,会存在多次302的跳转操作,所以,请不停的跳转直至该请求返回200
6、用户扫码并确认登录。用户扫码确认,会发送请求给淘宝。
7、淘宝网接到确认扫码,返回登录成功。
8、保存登录Cookie信息
9、提示用户登录成功
展示一部分Java的代码片段:
public void checkAndSetLoginStatus(String lgToken) { Thread thread = new Thread(new Runnable() { @Override public void run() { Map<String, String> params = newHashMap(); params.put("defaulturl", "http://login.taobao.com/member/taobaoke/login.htm?is_login=1 params.put("lgToken", lgToken); int retryTimes = 1; HttpResponse loginCheckResp =HttpUtil.post("https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do null); QRcodeLoginCheck loginCheck =JSON.parseObject(loginCheckResp.getResponse(), QRcodeLoginCheck.class); while (!loginCheck.isLoginSuccess()) { if(loginCheck.isExpire() || retryTimes++>30){ redisService.set(loginKey, QRCODE_EXPIRED+""); log.warn("Taobao login QRCode is expire or long time no scan."); return; } ThreadSleep.sleep(1500); loginCheckResp =HttpUtil.post("https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do null); loginCheck =JSON.parseObject(loginCheckResp.getResponse(), QRcodeLoginCheck.class); } HttpResponse httpResponse = HttpUtil.post(loginCheck.getUrl(), loginCheckResp.getCookieStore()); while(httpResponse != null && httpResponse.is302Direct()){ String location = httpResponse.getLocaltion(); httpResponse = HttpUtil.post(location, httpResponse.getCookieStore()); } byte[] data = new JavaSerializer().to(httpResponse.getCookieStore()); redisService.set(sessionKey, Base64.encodeBase64String(data)); } }); thread.setName("TB_Login_Thread"); thread.start(); }