求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
相关产品推荐
相关产品推荐

