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

求WCF REST基于Token认证完整示例含web.config及JWT取值方法

WCF REST 基于JWT Token认证完整实现示例

1. 核心实现代码

BearerTokenMessageInspector 实现

using System;
using System.IdentityModel.Tokens.Jwt;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using System.Web;
using Microsoft.IdentityModel.Tokens;
using System.Security.Claims;

public class BearerTokenMessageInspector : IDispatchMessageInspector
{
    private readonly string _secretKey;

    public BearerTokenMessageInspector(string secretKey)
    {
        _secretKey = secretKey;
    }

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        var httpRequest = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
        var authorizationHeader = httpRequest.Headers["Authorization"];

        if (!string.IsNullOrEmpty(authorizationHeader) && authorizationHeader.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
        {
            var token = authorizationHeader.Substring("Bearer ".Length).Trim();
            try
            {
                var jwtHandler = new JwtSecurityTokenHandler();
                var validationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(_secretKey)),
                    ValidateIssuer = false, // 按需开启 issuer 验证
                    ValidateAudience = false, // 按需开启 audience 验证
                    ClockSkew = TimeSpan.Zero
                };

                var claimsPrincipal = jwtHandler.ValidateToken(token, validationParameters, out _);
                // 将解析后的Claims存入OperationContext,供服务方法调用
                OperationContext.Current.IncomingMessageProperties["JwtClaims"] = claimsPrincipal.Claims;
            }
            catch (Exception ex)
            {
                throw new FaultException("无效或过期的Token: " + ex.Message);
            }
        }
        else
        {
            throw new FaultException("缺少合法的Authorization请求头");
        }
        return null;
    }

    public void BeforeSendReply(ref Message reply, object correlationState)
    {
        // 无需处理回复逻辑
    }
}

JWT认证行为扩展(用于注册Inspector)

using System.ServiceModel.Configuration;
using System.ServiceModel.Description;

public class BearerTokenBehavior : BehaviorExtensionElement, IEndpointBehavior
{
    public override Type BehaviorType => typeof(BearerTokenBehavior);

    protected override object CreateBehavior()
    {
        return this;
    }

    public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        // 从配置读取密钥,避免硬编码
        var secretKey = System.Configuration.ConfigurationManager.AppSettings["JwtSecretKey"];
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new BearerTokenMessageInspector(secretKey));
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

2. Web.config 完整配置

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <!-- JWT对称加密密钥,生产环境建议加密存储 -->
    <add key="JwtSecretKey" value="Your_Secure_Symmetric_Key_At_Least_16_Characters"/>
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.7.2"/>
    <httpRuntime targetFramework="4.7.2"/>
  </system.web>
  <system.serviceModel>
    <extensions>
      <!-- 注册自定义Token认证行为扩展 -->
      <behaviorExtensions>
        <add name="bearerTokenAuthentication" type="YourNamespace.BearerTokenBehavior, YourServiceAssemblyName"/>
      </behaviorExtensions>
    </extensions>
    <bindings>
      <webHttpBinding>
        <binding name="RestBinding">
          <!-- 生产环境请改用Transport模式启用HTTPS -->
          <security mode="TransportCredentialOnly">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
    <behaviors>
      <endpointBehaviors>
        <behavior name="RestBehavior">
          <webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json"/>
          <!-- 启用自定义Token认证 -->
          <bearerTokenAuthentication/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service name="YourNamespace.YourRestService" behaviorConfiguration="ServiceBehavior">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="RestBinding"
                  contract="YourNamespace.IYourRestService" behaviorConfiguration="RestBehavior"/>
      </service>
    </services>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

3. 在WCF服务中访问JWT值

服务契约定义

using System.ServiceModel;
using System.ServiceModel.Web;

[ServiceContract]
public interface IYourRestService
{
    [OperationContract]
    [WebGet(UriTemplate = "GetCurrentUserInfo", ResponseFormat = WebMessageFormat.Json)]
    UserInfo GetCurrentUserInfo();
}

public class UserInfo
{
    public string UserId { get; set; }
    public string UserName { get; set; }
    public string[] Roles { get; set; }
}

服务实现(获取JWT Claims)

using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Security.Claims;

public class YourRestService : IYourRestService
{
    public UserInfo GetCurrentUserInfo()
    {
        if (OperationContext.Current.IncomingMessageProperties.TryGetValue("JwtClaims", out var claimsObj) && claimsObj is IEnumerable<Claim> claims)
        {
            return new UserInfo
            {
                UserId = claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value,
                UserName = claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value,
                Roles = claims.Where(c => c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray()
            };
        }
        throw new FaultException("无法从Token中获取用户信息");
    }
}

关键注意事项

  • 需安装NuGet包 System.IdentityModel.Tokens.Jwt(选择兼容.NET Framework 4.x的稳定版本)
  • 替换代码和配置中的YourNamespace、YourServiceAssemblyName、Your_Secure_Symmetric_Key_At_Least_16_Characters为实际业务内容
  • 生产环境必须启用HTTPS,将web.config中security mode改为Transport
  • 可根据业务需求调整JWT验证参数(如开启Issuer、Audience验证)

内容的提问来源于stack exchange,提问作者Ingo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:52:46