【成长之路】未知系统的开发挑战

260 阅读4分钟

最近在公司做一个项目,姑且先称作A,项目中需要去调用另一个系统B的接口。

但是系统B因为是买的第三方的产品,我们只是负责部署,对其中的源码细节完全不了解,想要获取这样的接口难度很大。刚接到这个任务的时候,我可谓是一头雾水,没有一点头绪。

不过,经过思考后,我大概想出了三个方案。

方案一:我们所需要的接口在页面上是能找到的,虽然系统B是一个很老的spring mvc项目,很多页面都不是前后端分离的,但是这个接口是可以单独调用的,因此可以尝试去想办法调用该接口。

方案二:虽然系统B的源码很难读,但是知道了接口,我们多少可以顺藤摸瓜,尝试去深入挖一下这个接口的逻辑,运气好的话,还能找到在代码中直接调用该接口的方式,减少开发成本。

方案三:虽然系统B的功能复杂,但是数据库我们是能访问的,只要能找到数据结构关系,我们自己就能通过读数据库的方式找到想要的数据。但是,要理清数据结构关系并不容易。

首先对方案一进行研究。

找到页面接口和所需参数,通过postman模拟对其进行访问,发现了有个必须的参数,那就是登录状态的session。

所以,很容易想到通过模拟登录的方式,先拿到session,再去访问我们所要的接口。使用python代码模拟如下:

  url = "xxx"
  session = requests.Session()
  session.headers.update({})
  r = session.get(url)
  payload = {"xxx": "xxx"}
  url2 = "xxx"
  r2 = session.post(url2, data=payload)
  print(r2.text)
  return Response({"data": "ok"})

虽然这种方法能够获得我们想要的结果,但是也造成了意想不到的问题。因为代码让用户重新登录后,会使已经登录的用户下线,原因是系统B的页面上会有一个轮询请求,一直在检测sesssion值是否改变。

因此,既然后端登录不行,那改用前端登录呢?这样即便session改变了,浏览器也会将session更新,而不至于使用户踢下线。

但是前端模拟登录,会面临跨域问题,通过调研跨域问题的解决方案,使用iframe技术先做一个尝试。

父页面:

<!DOCTYPE html>
<html>
<head>
	<title>A系统</title>
	<script type='text/javascript'>
		 window.addEventListener('message', function (event) {
		 	console.log('father page receive')
            var sessionid = event.data.sessionid;
            console.log(sessionid);
        });
	</script>
</head>
<body>
<iframe hidden="hidden" id="bkjk-pin" src="https://B系统域名/test.html"></iframe>
</body>
</html>

我们在B系统下面放了一个页面,在iframe里面尝试登录B系统,这样就解决了因域名不一致的登录问题。

<!DOCTYPE html>
<html>
<head>
	<title>B系统</title>
	<script type='text/javascript'>
		setTimeout(function () {
			var sessionid = getCookie('JSESSIONID')
			console.log("son page send")
			console.log(sessionid);
			window.parent.postMessage({sessionid: sessionid}, '*');
		}, 1000);
		

		function getCookie(name) {
		    var prefix = name + "="
		    var start = document.cookie.indexOf(prefix)
		 
		    if (start == -1) {
		        return null;
		    }
		 
		    var end = document.cookie.indexOf(";", start + prefix.length)
		    if (end == -1) {
		        end = document.cookie.length;
		    }
		 
		    var value = document.cookie.substring(start + prefix.length, end)
		    return value;
		}
	</script>
</head>
<body>
	hello world
	<iframe hidden="hidden" id="bkjk-pin" src="https://B系统的登录链接"></iframe>
</body>
</html>

此种方案通过在子页面中进行登录,更新完session后,通过postMessage的方式返回给父页面。实测可以拿到session,但是需要去修改tomcat的session-config为httponly为false,这就违反了安全性问题。

所以模拟登录的方案就被否了。

其实在研究这种方案的时候,我也只是抱着试一试的心态,因为我知道,就算这一次接口刚好能通过页面调用获取到,到后面有新的功能需求,万一没有现成的接口,还是需要一种更为长远的方式去解决这个问题。

然后开始研究方案二

因为B系统的源码太过难度,而且依赖众多,特别容易让人绕晕,读了一天,依然不能清晰的勾勒出各个类之间的业务关联,因此再度放弃。

最后只剩下方案三

这是最后一根救命稻草了,方案是要去理解系统B的数据结构存储。

目前手上的资源还有系统B的数据字典,但是几百张表,无益于大海捞针。

但是一旦找到我们想要的表,则会格外惊喜,并有了坚持下去的动力。

在经历了长达3天的煎熬后,我终于理清了想要的数据结构,那一天下班后走出公司大门,我辈岂是蓬蒿人。

总结了一些经验:

  1. 看页面返回接口的字段,推测相应的表
  2. 根据关键字去搜索,尤其要注意关联关系
  3. 通过在系统里的操作,观察表记录的变化,来定位我们最终的结果

理清了数据结构,剩下的一切都好做了,底层打通了,上层的一切定制皆是浮云。

这是我的第一篇记录自己思考问题过程的文章,因为我看过太多技术文章,只是给出结论,然而我觉得思考的过程也很重要,没有人能够一步登天,都是在汗水和泪水交织中一步一步过来的。

我会坚持分享我的技术总结,因为我想成为优秀的人,我也想帮助身边的人都成为优秀的人啊。