这是我参与更文挑战的第6天,活动详情查看: 更文挑战
书接上文,我们继续对上回说到的问题继续分析,本文目标针对url中的sec_uid参数进行分析。
1、sec_uid
思路及实现
调用接口是通过xhr异步调用的,那么一定会有前台js代码来生成或者通过其他接口来获取这个参数,那么我们可以在浏览器端先搜一下这个参数名称,看看都再哪里出现过,然后跟一下调用链,希望最终能找到源头。
首先,我们搜一下前端的代码,发现sec_uid只再一个名称为index.98ac6f5d.js文件中出现了几次,先挨个扫一眼,我们发现在1425和1474行的地方分别出现了以下2句代码:
url: '/web/api/v2/user/info/?sec_uid=' + config.sec_uid,
params.sec_uid = _utils2.default.getUrlParam(window.location.href, "sec_uid");
我们发现这个参数是从短链接跳转后的长连接里获取的,用这个参数调用了user/info接口,根据字面意思大概能知道这个接口是用户信息的接口
这里我们顺便看一下,怎么拿到这个长连接的url,这里用接口调试工具先试探看一下效果,我们可以看到,短链接是被302到具体地址了,那么我们后续可以通过HttpRequest来获取最终url以及携带的各项参数。
我们先来实现获取302地址的代码:
public static String get302Location(String requestUrl) {
String res = "";
HttpURLConnection httpUrlConn = null;
try {
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
httpUrlConn.setRequestProperty("Accept", "text/plain");
httpUrlConn.setRequestProperty("Content-Type", "application/json");
httpUrlConn.setRequestMethod("POST");
httpUrlConn.setInstanceFollowRedirects(false);//这里是重点,必须设置为false,时请求不进行重定向
String location=httpUrlConn.getHeaderField("Location");
httpUrlConn.disconnect();
return location;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
return res;
}
运行结果:
我们可以看到,这里已经成功拿到了302的目标地址,接下来,我们再写一个获取对应参数的方法。
public void getLocationParam(){
String url = "https://v.douyin.com/eCJaMPX";
String location = JwtHttpUtil.get302Location(url);
try {
URL urlStr = new URL(location);
String urlParam=urlStr.getQuery();
Map<String,String> params=new HashMap<String,String>();
for(String paramStr:urlParam.split("&")){
String paramName=paramStr.split("=")[0];
String paramVal=paramStr.split("=")[1];
params.put(paramName, paramVal);
}
String sec_uid="sec_uid的值="+params.get("sec_uid");
System.out.println(sec_uid);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
运行结果如下:
接下来,我们可以实现从首页来获取用户信息的代码,主体代码如下:
package com.lottery.job;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.jeecgframework.jwt.util.JwtHttpUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class DyTest implements Job{
@Override
public void execute(JobExecutionContext arg0) throws JobExecutionException {}
public String getLocationParam(String homeUrl){
String location = JwtHttpUtil.get302Location(homeUrl);
try {
URL urlStr = new URL(location);
String urlParam=urlStr.getQuery();
Map<String,String> params=new HashMap<String,String>();
for(String paramStr:urlParam.split("&")){
String paramName=paramStr.split("=")[0];
String paramVal=paramStr.split("=")[1];
params.put(paramName, paramVal);
}
String sec_uid=params.get("sec_uid");
System.out.println(sec_uid);
return sec_uid;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
}
}
/**
*
* @param homeUrl 首页地址
* @param url 接口地址
*/
public void getUserInfo(String homeUrl,String url){
String sec_uid=getLocationParam(homeUrl);
String apiUrl=url+"?sec_uid="+sec_uid;
System.out.println(apiUrl);
String jsonString = JwtHttpUtil.httpRequest(apiUrl, "POST", null);
System.out.println(jsonString);
}
public static void main(String[] args) throws JobExecutionException{
DyTest d=new DyTest();
d.getUserInfo("https://v.douyin.com/eCJaMPX/","https://www.iesdouyin.com/web/api/v2/user/info/");
}
}
运行结果如下:
这里出现了一些小问题,接口对请求进行了拦截,没有看到预期的效果,但是我在浏览器中直接访问,是有返回结果的
初步判断,这里可能是对请求头中的user-agent做了校验,由于时间问题,这个问题待下期更文进行再进行解决。
文末附上JwtHttpUtil的源码,大家有空也可以调试一下,看看具体是哪里的问题。
package org.jeecgframework.jwt.util;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.log4j.Logger;
import org.jeecgframework.core.util.LogUtil;
import com.alibaba.fastjson.JSONObject;
/**
* JWT 客户端
* @author qinfeng
*
*/
public class JwtHttpUtil {
private static Logger log = Logger.getLogger(JwtHttpUtil.class);
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr, String sign) {
JSONObject jsonObject = null;
StringBuffer buffer = new StringBuffer();
HttpURLConnection httpUrlConn = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
httpUrlConn.setRequestProperty("X-AUTH-TOKEN", sign);
httpUrlConn.setRequestProperty("Accept", "*/*");
httpUrlConn.setRequestProperty("Content-Type", "application/json");
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
log.debug(buffer.toString());
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
LogUtil.info("Weixin server connection timed out.");
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("https request error:{}" + e.getMessage());
} finally {
try {
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("http close error:{}" + e.getMessage());
}
}
return jsonObject;
}
/**
* 发起https请求并获取结果
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
*/
public static String httpRequest(String requestUrl, String requestMethod, String outputStr) {
String res = "";
StringBuffer buffer = new StringBuffer();
HttpURLConnection httpUrlConn = null;
try {
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// httpUrlConn.setRequestProperty("Accept", "text/plain");
// httpUrlConn.setRequestProperty("Content-Type", "application/json");
// 设置请求方式(GET/POST)
httpUrlConn.setRequestProperty("User-Agent","MSIE");
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
res = buffer.toString();
log.debug(res);
} catch (ConnectException ce) {
LogUtil.info("Weixin server connection timed out.");
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("https request error:{}" + e.getMessage());
} finally {
try {
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
org.jeecgframework.core.util.LogUtil.info("http close error:{}" + e.getMessage());
}
}
return res;
}
public static String get302Location(String requestUrl) {
String res = "";
HttpURLConnection httpUrlConn = null;
try {
URL url = new URL(requestUrl);
httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
httpUrlConn.setRequestProperty("Accept", "text/plain");
httpUrlConn.setRequestProperty("Content-Type", "application/json");
httpUrlConn.setRequestMethod("POST");
httpUrlConn.setInstanceFollowRedirects(false);//这里是重点,必须设置为false,时请求不进行重定向
// 当有数据需要提交时
String location=httpUrlConn.getHeaderField("Location");
httpUrlConn.disconnect();
return location;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
return res;
}
}
欲知后事如何,且听下回分解。