先阅读C#之反编译之路(一)可以增加文章连续性
阅读C#之反编译之路(一)
如何快速定位代码位置
用一个小小的例子举例,用户反馈新能源车牌号无法录入,燃油车牌正常,查看日志报如下错误
拿到关键字车牌号长度错误直接反编译代码
打开dnSpy.exe→加载项目→Ctrl+F打开搜索框→输入关键字
由于是逐个文件进行反编译的,所有它并不能全局搜索,所以右上角是红色,这时候我们从资源文件开始,按键盘的向下键逐个文件向下查找(特别是完全不了解项目结构,非自己维护的代码等,不错过任何一个文件)
查找到关键字后,红色会变为黑色
很明显,最初的车牌号都为7位,并没有新能源车辆(新能源车牌号长度为8位),所以开发者添加了7位数的长度限制,我们只需要去掉该代码即可
右击→编辑方法→删掉圈中部分→编译→文件→全部保存,重新启动发现问题已经解决
修改接口调用
老系统用户登录后,要调用第三方系统接口,通过接口的返回值,判断是否能够登录系统,以及弹框提示等
通过对项目结构的分析,找到了登录方法
右键→编辑方法,添加如下的http post请求代码
//新接口请求
var request = (HttpWebRequest)WebRequest.Create("http://localhost:5184/getAuth");
request.Method = "POST";
request.ContentType = "application/json;charset=UTF-8";//ContentType
byte[] byteData = Encoding.UTF8.GetBytes(jsonParam);
int length = byteData.Length;
request.ContentLength = length;
Stream writer = request.GetRequestStream();
writer.Write(byteData, 0, length);
writer.Close();
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding("utf-8")).ReadToEnd();
这个时候代码会大量报错,因为我们并没有添加引用,你可以从其他项目(自己不报错的项目F12进去就能看到)或网上找到相关的代码命名空间(下图1),如果项目没有用到的依赖,则手动添加依赖,再引用,如下图(下图2)
添加如下引用之后,代码已经能够正常运行,并且我们打上了日志,还从日志文件中拿到了返回值
using System.IO;
using System.Net;
using System.Text;
using Newtonsoft.Json;
接下来我们要通过返回值来判断是否终止用户操作,只有当isAuth为true时,用户能直接登录,否则,如果message有信息,则弹框提示用户
这里我们直接使用JObject来接收值,省去添加返回值类的操作
if(string.IsNullOrEmpty(responseString)){
JObject jobj = JObject.Parse(responseString);
if (jobj.HasValues) {
if ((int)jobj["code"] == 200 && jobj["data"] != null && jobj["data"]["isAuth"] != null && (bool)jobj["data"]["isAuth"] == true) {
//鉴权通过
this.SystemInit(loginResponse, loginRequest.Password, jumpTo);
} else if ((int)jobj["code"] != 200 && jobj["msg"]!=null&&!string.IsNullOrEmpty(jobj["msg"].ToString())) {
//弹框提醒
Growl.WarningGlobal(jobj["msg"].ToString());
}
}
}else{
Growl.InfoGlobal("调用第三方鉴权接口失败!");
}
添加引用
using Newtonsoft.Json.Linq;
最终代码如下
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Text;
using Cloud.Data.IService;
using Cloud.Data.Model;
using Cloud.Helper;
using Cloud.Wpf.Common;
using Cloud.Wpf.Model;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using HandyControl.Controls;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Cloud.Wpf.ViewModel
{
// Token: 0x02000025 RID: 37
public partial class LoginViewModel : GalaSoft.MvvmLight.ViewModelBase
{
// Token: 0x06000118 RID: 280
public void Login(Cloud.Data.Model.LoginRequest loginRequest, string jumpTo = null)
{
this.dialogService.Waiting("登录中", true, "");
Cloud.Data.Model.LoginResponse loginResponse = this.userService.Login(loginRequest).Check<Cloud.Data.Model.LoginResponse>();
this.dialogService.WaitingClose();
if (loginResponse != null)
{
string jsonParam = JsonConvert.SerializeObject(new
{
userId = loginRequest.StationCode,//设备代码
loginName = loginRequest.UserName//登录id
});
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:5184/getAuth");
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/json;charset=UTF-8";
byte[] byteData = Encoding.UTF8.GetBytes(jsonParam);
int length = byteData.Length;
httpWebRequest.ContentLength = (long)length;
Stream requestStream = httpWebRequest.GetRequestStream();
requestStream.Write(byteData, 0, length);
requestStream.Close();
string responseString = new StreamReader(((HttpWebResponse)httpWebRequest.GetResponse()).GetResponseStream(), Encoding.GetEncoding("utf-8")).ReadToEnd();
Log.Info("第三方接口返回值:" + responseString);
if(!string.IsNullOrEmpty(responseString)){
JObject jobj = JObject.Parse(responseString);
if (jobj.HasValues) {
if ((int)jobj["code"] == 200 && jobj["data"] != null && jobj["data"]["isAuth"] != null && (bool)jobj["data"]["isAuth"] == true) {
//鉴权通过
this.SystemInit(loginResponse, loginRequest.Password, jumpTo);
} else if ((int)jobj["code"] != 200 && jobj["msg"]!=null&&!string.IsNullOrEmpty(jobj["msg"].ToString())) {
//弹框提醒
Growl.FatalGlobal(jobj["msg"].ToString());
}
}
}else{
Growl.WarningGlobal("调用第三方鉴权接口失败!");
}
}
}
}
}
保存,再次启动程序,用户已经不能正常登录系统
接口返回值如下