登录流程
1.微信小程序端 通过 wx.login 拿到 需要post的 code.
2. 一般情况下,通过getUserProfile可以拿到userInfo,拿到的userInfo是可视的,不需要解密就能post到后台的。
3.但有时候需要通过getPhoneNumber 拿用户手机号 和iv值,拿到的手机号它是被加密了的手机号(encryptedData),这时候就需要把拿到的encryptedData 连同code 和iv 一起post到后台,由后台进行解密。
4. 前端要 先进行wx.login 之后再进行getUserProfile 和 getPhoneNumber 操作 因为 wx.login 会刷新会话秘钥session_key ,如果wx.login 最后执行了 那么等于后台用新的session_key 去解旧的加密字段,很显然不行的, 就像前朝的尚方宝剑斩不了现在的官员。
5.个人号没有获取用户手机号的权限,所以必须是服务号小程序才可以,所以个人号小程序 不要做无谓的挣扎
后台控制器代码如下
不管你那边是怎么写的,重要的是拿到前端post的数据encryptedData,code 和iv
[ApiController]
[Route("/api/public/v1/users/")]
public class UserController : Controller
{
private readonly ILogger<UserController> _logger;
public UserController(ILogger<UserController> logger) {
_logger = logger;
}
[Route("wxlogin")]
[HttpPost]
public async Task<IActionResult> wxlogin(string encryptedData,string code,string iv) {
string Appid = appConf.Instance.APPID;
string Secret =appConf.Instance.SecretKey; 你的SecretKey
string grant_type = "authorization_code";
string re = await this.GetJsonStr();
string url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + Appid + "&secret=" + Secret + "&js_code=" + code + "&grant_type=" + grant_type;
try
{
string res = RESTClient.Get(url);
var jsonlist = LitJson.JsonMapper.ToObject(res);
string open_id = (string)jsonlist["openid"];
string session_key = (string)jsonlist["session_key"];
if (!string.IsNullOrWhiteSpace(open_id)&& !string.IsNullOrWhiteSpace(session_key))
{
var result1 = WXToolKit.DecodeEncryptedData(session_key, encryptedData, iv); 代码走到这就行了,可以打印解密以后的result1 json字符串,查看解密结果是否正确。 没必要往下继续进行了,再往下也就是反序列化一下,拿到手机号码,多的不说了,自行发挥,咱们主要说解密的过程 解密代码都在下面的WXToolKit.cs工具类中
}
return JSONRES.success("");
}
catch (Exception e)
{
_logger.LogInformation(e.ToString());
return "404";
}
}
}
主要代码 WXToolKit.cs
public class WXToolKit
{
public static string DecodeEncryptedData(string sessionKey, string encryptedData, string iv)
var aesKey = Convert.FromBase64String(sessionKey);
var aesIV = Convert.FromBase64String(iv);
var result = AES_Decrypt(encryptedData, aesIV, aesKey);
var resultStr = Encoding.UTF8.GetString(result);
return resultStr;
}
private static byte[] decode2(byte[] decrypted)
{
int pad = (int)decrypted[decrypted.Length - 1];
if (pad < 1 || pad > 32)
{
pad = 0;
}
byte[] res = new byte[decrypted.Length - pad];
Array.Copy(decrypted, 0, res, 0, decrypted.Length - pad);
return res;
}
private static byte[] AES_Decrypt(String Input, byte[] Iv, byte[] Key)
{
#if NET45
RijndaelManaged aes = new RijndaelManaged();
#else
SymmetricAlgorithm aes = Aes.Create();
#endif
aes.KeySize = 128;
aes.BlockSize = 128;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
aes.Key = Key;
aes.IV = Iv;
var decrypt = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] xBuff = null;
try
{
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write))
{
byte[] xXml = Convert.FromBase64String(Input);
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
Array.Copy(xXml, msg, xXml.Length);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = decode2(ms.ToArray());
}
}
catch (System.Security.Cryptography.CryptographicException)
{
using (var ms = new MemoryStream())
{
var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write);
{
byte[] xXml = Convert.FromBase64String(Input);
byte[] msg = new byte[xXml.Length + 32 - xXml.Length % 32];
Array.Copy(xXml, msg, xXml.Length);
cs.Write(xXml, 0, xXml.Length);
}
xBuff = decode2(ms.ToArray());
}
}
return xBuff;
}
}
不重要代码 RESTClient.cs
public class RESTClient
{
public static string Get(string url) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader readStream = new StreamReader(response.GetResponseStream(), encoding:Encoding.UTF8))
{
return readStream.ReadToEnd();
}
}
public static string Post(string url,string data) {
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
using (StreamWriter streamWriter= new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(data);
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (StreamReader readStream = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return readStream.ReadToEnd();
}
}
}
|