You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 06:45:33