微信小程序认证在.netcore9.0上的流程
一、整体流程
- 小游戏端:获取用户临时登录凭证
code - 小游戏端:将
code发送至 .NET Core WebAPI - WebAPI:用
code向微信服务器换取openid/session_key - WebAPI:创建/更新用户信息,生成 JWT Token
- 小游戏端:存储 Token 并用于后续授权请求
sequenceDiagram
微信小游戏->>+微信服务器: wx.login() 获取 code
微信小游戏->>+.NET Core API: 提交 code
.NET Core API->>+微信服务器: code+appid+secret 换 openid/session_key
微信服务器-->>-.NET Core API: 返回 openid/session_key
.NET Core API->>+数据库: 创建/更新用户信息
.NET Core API-->>-微信小游戏: 返回 JWT Token
微信小游戏->>+.NET Core API: 后续请求携带 Token
.NET Core API-->>-微信小游戏: 返回授权数据
二、分步实现
1. 微信小游戏端(Unity/JavaScript)
// 调用微信登录接口
wx.login({
success: (res) => {
if (res.code) {
// 将 code 发送到后端
wx.request({
url: 'https://your-api.com/auth/wechat',
method: 'POST',
data: { code: res.code },
success: (response) => {
const token = response.data.token;
wx.setStorageSync('userToken', token); // 存储 Token
}
});
}
}
});
2. .NET Core 9 WebAPI 控制器
[ApiController]
[Route("auth")]
public class AuthController : ControllerBase
{
private readonly IUserService _userService; // 用户服务(注册/登录逻辑)
private readonly JwtSettings _jwtSettings; // JWT 配置
[HttpPost("wechat")]
public async Task<IActionResult> WeChatLogin([FromBody] WeChatLoginRequest request)
{
// 1. 用 code 换取 openid
var wechatUser = await GetWeChatUserInfo(request.Code);
// 2. 注册或更新用户
var user = await _userService.CreateOrUpdateUserAsync(
openId: wechatUser.OpenId,
sessionKey: wechatUser.SessionKey
);
// 3. 生成 JWT Token
var token = GenerateJwtToken(user.Id);
return Ok(new { Token = token });
}
private async Task<WeChatUserInfo> GetWeChatUserInfo(string code)
{
// 请求微信接口 (替换 YOUR_APPID 和 YOUR_SECRET)
using var client = new HttpClient();
var response = await client.GetStringAsync(
$"https://api.weixin.qq.com/sns/jscode2session?" +
$"appid=YOUR_APPID&secret=YOUR_SECRET&js_code={code}&grant_type=authorization_code"
);
var data = JsonSerializer.Deserialize<WeChatResponse>(response);
return new WeChatUserInfo
{
OpenId = data.openid,
SessionKey = data.session_key
};
}
private string GenerateJwtToken(int userId)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSettings.SecretKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[] { new Claim("uid", userId.ToString()) }),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(
new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256
)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
3. 用户服务层(注册逻辑)
public class UserService : IUserService
{
private readonly AppDbContext _dbContext;
public async Task<User> CreateOrUpdateUserAsync(string openId, string sessionKey)
{
var user = await _dbContext.Users.FirstOrDefaultAsync(u => u.WeChatOpenId == openId);
if (user == null)
{
// 新用户注册
user = new User
{
WeChatOpenId = openId,
SessionKey = sessionKey,
CreatedAt = DateTime.UtcNow
};
_dbContext.Users.Add(user);
}
else
{
// 更新会话密钥
user.SessionKey = sessionKey;
}
await _dbContext.SaveChangesAsync();
return user;
}
}
4. 授权过滤器(验证 Token)
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class JwtAuthorizeAttribute : Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
var token = context.HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSettings.SecretKey);
try {
tokenHandler.ValidateToken(token, new TokenValidationParameters {
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
}, out _);
}
catch {
context.Result = new UnauthorizedResult();
}
}
}
// 在控制器中使用
[HttpGet("protected-data")]
[JwtAuthorize]
public IActionResult GetProtectedData()
{
return Ok("授权成功!");
}
三、关键配置
-
微信小程序配置
- 开放平台申请 AppID/AppSecret
- 设置合法 API 域名(如
https://your-api.com)
-
.NET Core 配置
// appsettings.json { "JwtSettings": { "SecretKey": "your-64-byte-secret-key", // 至少 64 位 "ExpireDays": 7 } } -
数据库用户表
字段 类型 说明 Id int 主键 WeChatOpenId string(128) 微信唯一标识 SessionKey string(128) 微信会话密钥 CreatedAt datetime 注册时间
四、安全注意事项
-
敏感信息保护
AppSecret和SessionKey永远不返回给客户端- 使用
HttpOnlyCookie 或客户端安全存储(如微信 Storage)保存 Token
-
防篡改机制
- 微信返回的
openid/session_key需验证签名(官方文档)
- 微信返回的
-
Token 有效期
- JWT 过期时间建议 ≤
session_key有效期(微信默认 30 分钟)
- JWT 过期时间建议 ≤
五、常见问题
如何获取用户头像/昵称?
- 小游戏端调用
wx.getUserProfile()获取加密数据 - 后端用
session_key解密(需实现 AES-128-CBC 算法)
如何解决 code 被恶意刷取?
- 后端增加 IP 限流(如
AspNetCoreRateLimit包) - 验证
code长度(微信固定为 32 字符)
完整代码示例:GitHub Gist 链接
微信官方文档:小程序登录
.NET Core JWT 库:Microsoft.AspNetCore.Authentication.JwtBearer

浙公网安备 33010602011771号