基于JWT密钥实现单点登录的C#代码示例请求
JWT单点登录(SSO)C#实现示例
一、发送端(外部系统)代码
外部系统负责生成包含用户名的JWT,使用预共享密钥签名。需引用System.IdentityModel.Tokens.Jwt和Microsoft.IdentityModel.Tokens NuGet包。
using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Microsoft.IdentityModel.Tokens; public class SsoSender { // 与接收端共享的密钥(建议从配置/环境变量读取,勿硬编码) private const string SharedSecretKey = "your_strong_shared_secret_min_16_chars"; private const string SsoEndpoint = "https://your-membership-site.com/api/sso/login"; public async Task SendSsoRequest(string username) { // 构造JWT声明,仅携带用户名和过期时间 var claims = new[] { new Claim(ClaimTypes.Name, username), new Claim(JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddMinutes(5).ToUnixTimeSeconds().ToString()) }; // 生成签名密钥 var key = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(SharedSecretKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); // 创建JWT令牌 var token = new JwtSecurityToken( issuer: "external-system", audience: "membership-site", claims: claims, expires: DateTime.UtcNow.AddMinutes(5), signingCredentials: creds); var tokenString = new JwtSecurityTokenHandler().WriteToken(token); // 发送GET请求到接收端SSO端点 using var httpClient = new HttpClient(); var response = await httpClient.GetAsync($"{SsoEndpoint}?token={Uri.EscapeDataString(tokenString)}"); response.EnsureSuccessStatusCode(); } }
二、接收端(会员网站WebAPI)代码
接收端负责验证JWT令牌,提取用户名后完成登录逻辑,最后跳转至会员首页。需基于ASP.NET Core实现。
1. 配置JWT验证(Program.cs)
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; var builder = WebApplication.CreateBuilder(args); // 添加JWT验证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = "external-system", ValidAudience = "membership-site", IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("your_strong_shared_secret_min_16_chars")) }; // 允许从URL查询参数获取JWT令牌 options.Events = new JwtBearerEvents { OnMessageReceived = context => { var token = context.Request.Query["token"]; if (!string.IsNullOrEmpty(token)) { context.Token = token; } return Task.CompletedTask; } }; }); builder.Services.AddAuthorization(); builder.Services.AddControllers(); var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
2. SSO登录端点(SsoController.cs)
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Mvc; using System.Security.Claims; [ApiController] [Route("api/sso")] public class SsoController : ControllerBase { private readonly IUserService _userService; public SsoController(IUserService userService) { _userService = userService; } [HttpGet("login")] public async Task<IActionResult> SsoLogin() { // 从已验证的JWT中获取用户名 var username = User.Identity?.Name; if (string.IsNullOrEmpty(username)) { return BadRequest("无效的SSO令牌"); } // 验证用户名是否存在于会员系统 if (!await _userService.IsUserExists(username)) { return NotFound("用户不存在"); } // 创建会员系统的Cookie登录凭证(复用现有登录逻辑) var claims = new List<Claim> { new Claim(ClaimTypes.Name, username) // 按需添加会员系统所需的角色、权限等声明 }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProps = new AuthenticationProperties { IsPersistent = true }; await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProps); // 跳转至会员网站首页 return Redirect("/home"); } } // 示例用户服务接口(需根据实际业务实现) public interface IUserService { Task<bool> IsUserExists(string username); }
关键注意事项
- 共享密钥需足够复杂(至少16位),避免硬编码,建议从环境变量或加密配置读取。
- JWT令牌设置合理过期时间(如5分钟),降低被滥用风险。
- 生产环境必须使用HTTPS传输,防止令牌被窃取。
- 接收端Cookie认证配置需与现有会员系统保持一致,确保登录状态兼容。
内容的提问来源于stack exchange,提问作者brother
相关产品推荐
相关产品推荐

