当使用 .NET Core 来实现微信小程序授权登录功能时,我们需要遵循微信小程序的开发文档,并结合后端服务进行开发。
1. 微信小程序授权登录流程
- 微信小程序是通过调用
wx.login
获取code
。 - 小程序将
code
发送到后端服务器。 - 后端服务器使用
code
向微信服务器发起请求,获取session_key
和openid
。 - 后端服务器将
session_key
和openid
与用户信息关联,并生成自定义的登录凭证(如 JWT)。 - 后端服务器将登录凭证返回给小程序。
- 小程序保存登录凭证,并在后续请求中携带该凭证,以便后端验证用户身份。
2. 小程序端实现
wx.login({
success: function (res) {
if (res.code) {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
wx.request({
url: '你的后端接口地址', // 例如:https://yourserver.com/api/auth/login
data: {
code: res.code
},
method: 'POST',
success: function (res) {
// 保存登录凭证到本地
wx.setStorageSync('session_key', res.data.session_key); // 注意:这里通常不保存session_key,而是保存JWT等自定义凭证
// 后续可以使用这个凭证来进行用户鉴权等操作
}
})
} else {
console.log('获取用户登录态失败!' + res.errMsg)
}
}
})
3. 后端(.NET Core)实现
3.1 创建后端接口接收 code
创建一个 .NET Core Web API 项目,并添加一个接收 code
的接口。
DecodeOpenIdAndSessionKey辅助方法,根据前端传过来的Code来调用微信服务器获取 openid 和 session_key 注意 后端需要配置正确的AppId和AppSecret 同时对应的小程序的AppId也需要和后端保持一致,否则调用会获取失败
/// <summary>
/// 微信授权-获取手机号
/// </summary>
/// <param name="loginInfo">code(登录凭证必传)encryptedData(加密数据必传)iv(向量必传)</param>
/// <returns></returns>
[HttpPost("/api/Registration/WxAuthorized")]
public async Task<AjaxResult> WxAuthorized(wxAuthorizedLoginResult loginInfo)
{
AjaxResult AjaxResult = new AjaxResult();
try
{
if (string.IsNullOrEmpty(loginInfo.code))
{
AjaxResult.StatusCode = 300;
AjaxResult.Message = "code不允许为空";
AjaxResult.Result = false;
return AjaxResult;
}
if (string.IsNullOrEmpty(loginInfo.encryptedData))
{
AjaxResult.StatusCode = 300;
AjaxResult.Message = "encryptedData不允许为空";
AjaxResult.Result = false;
return AjaxResult;
}
if (string.IsNullOrEmpty(loginInfo.iv))
{
AjaxResult.StatusCode = 300;
AjaxResult.Message = "iv不允许为空";
AjaxResult.Result = false;
return AjaxResult;
}
WxAccessTokenResult wxRes = WeChatAppDecrypt.DecodeOpenIdAndSessionKey(loginInfo, _configuration.GetSection("AppId").Value, _configuration.GetSection("AppSecret").Value);
if (wxRes.session_key != null)
{
//这里省略
}
else
{
AjaxResult.StatusCode = 500;
AjaxResult.Message = "解密用户信息失败";
AjaxResult.Result = false;
}
}
catch (Exception ex)
{
new Exception("请求地址:/LoginApi/WxAuthorized,错误内容:", ex);
}
return AjaxResult;
}
DecodeOpenIdAndSessionKey里面的具体方法代码参考
#region 获取OpenId和SessionKey的Json数据包
/// <summary>
/// 获取OpenId和SessionKey的Json数据包
/// </summary>
/// <param name="code">客户端发来的code</param>
/// <param name="appid"></param>
/// <param name="appsecret"></param>
/// <returns>Json数据包</returns>
public static string GetOpenIdAndSessionKeyString(string code,string appid,string appsecret)
{
string temp = string.Empty;
temp = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + appsecret + "&js_code=" + code + "&grant_type=authorization_code";
return GetResponse(temp);
}
#endregion
#region 反序列化包含OpenId和SessionKey的Json数据包
/// <summary>
/// 反序列化包含OpenId和SessionKey的Json数据包
/// </summary>
/// <param name="loginInfo"></param>
/// <param name="appid"></param>
/// <param name="appsecret"></param>
/// <returns>包含OpenId和SessionKey的类</returns>
public static WxAccessTokenResult DecodeOpenIdAndSessionKey(wxAuthorizedLoginResult loginInfo, string appid, string appsecret)
{
WxAccessTokenResult oiask = JsonConvert.DeserializeObject<WxAccessTokenResult>(GetOpenIdAndSessionKeyString(loginInfo.code, appid, appsecret));
if (oiask == null)
{
return null;
}
return oiask;
}
#endregion
辅助方法,用于生成 JWT 凭证(这里只是一个示例,具体实现需要根据你的 JWT 库进行)
/// <summary>
/// 生成JwtToken
/// </summary>
/// <param name="payload"></param>
/// <param name="Secret"></param>
/// <returns></returns>
public static string SetJwtEncode(Dictionary<string, object> payload,string Secret)
{
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(payload, Secret);
return token;
}
以上是具体的一些流程和代码参照 具体还有更多实用的说明可以在微信开发文档中自行学习
4. 安全性考虑
- 建议不要在前端(小程序)保存
session_key!
它应该只在后端使用!! - 使用 HTTPS 来保证前后端通信的安全性。
- 对敏感操作进行权限验证,确保只有合法用户才能执行。
5.常见的一些问题
5.1 微信小程序报40029
本人目前遇到这个问题出错的情况只有两个:
1.项目Appid和当前小程序不对应 需要认真检查一下 code 不存在或 AppId ,AppSecret 不一致
2.前端传的Code不对 就会不匹配
5.2 关于Code 前端传的Code只能用一次,用完就失效 也就是你每进行一次授权 Code就会失效 下次调的时候还是需要新的code 这个开发在进行功能测试的时候需要知道