C# 如何定制ASP.NETWebAPI JWT令牌响应?

C# 如何定制ASP.NETWebAPI JWT令牌响应?,c#,asp.net,asp.net-web-api,jwt,jwt-auth,C#,Asp.net,Asp.net Web Api,Jwt,Jwt Auth,我正在使用Asp.net Webform项目和Web API。我配置了基于JWT令牌的身份验证,现在我想定制身份验证响应 这是我的配置 Startup.cs public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration config = new HttpConfiguration(); // Web API routes

我正在使用Asp.net Webform项目和Web API。我配置了基于JWT令牌的身份验证,现在我想定制身份验证响应

这是我的配置

  • Startup.cs

    public class Startup
    {
         public void Configuration(IAppBuilder app)
         {
             HttpConfiguration config = new HttpConfiguration();
    
             // Web API routes
             config.MapHttpAttributeRoutes();
    
             app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    
             ConfigureOAuth(app);
    
             app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
    
             WebApiConfig.Register(config);
    
         }
    
         public void ConfigureOAuth(IAppBuilder app)
         {
    
             String apiHttpOnly = ConfigurationManager.AppSettings["AllowInsecureHttp"];
             String tokenTimeSpan = ConfigurationManager.AppSettings["tokenTimeSpanFromMinutes"];
    
             bool allowInsecureHttp = !String.IsNullOrEmpty(apiHttpOnly) ? 
                                      Convert.ToBoolean(apiHttpOnly) : false;
             int accessTokenExpireTimeSpan = !String.IsNullOrEmpty(tokenTimeSpan) ? 
                                      Convert.ToInt32(tokenTimeSpan) : 60;
    
             var authProvider = new AuthorizationServiceProvider();
             OAuthAuthorizationServerOptions options = new OAuthAuthorizationServerOptions
             {
                 //For Dev enviroment only (on production should be AllowInsecureHttp = false)
                 AllowInsecureHttp = allowInsecureHttp,
                 TokenEndpointPath = new PathString("/api/authenticate"),
                 AccessTokenExpireTimeSpan = TimeSpan.FromDays(accessTokenExpireTimeSpan),
                 Provider = authProvider
             };
    
             app.UseOAuthAuthorizationServer(options);
    
         }
    }
    
  • 授权服务提供者

     public class AuthorizationServiceProvider : OAuthAuthorizationServerProvider
     {
         public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
         {
             context.Validated();
             return base.ValidateClientAuthentication(context);
         }
    
         public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
         {
             var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    
             if (Membership.ValidateUser(context.UserName, context.Password))
             {
                 identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                 identity.AddClaim(new Claim("username", context.UserName));
                 identity.AddClaim(new Claim(ClaimTypes.Name, "admin admin"));
                 context.Validated(identity);
             }
             else
             {
                 context.SetError("invalid_grant", "Provide username and password is incorrect.");
    
             }
    
             return base.GrantResourceOwnerCredentials(context);
         }
     }
    
  • 当我使用正确的凭据调用API时,它返回如下

    {
        "access_token": "uEwmXl6N0mJXVUZesxA_2tG5lIuZUIUDaxtjAl0QGE6j2-J7n4c63zboOUClGjRQf1IDY9-nBgyq0HP5WR7MMxTYoHGIyiHIbcKu9AYwhECCGaVBCxY2Ounhit4N1pYK1vV6uX6AcoA-a0xhytF8Jz27D77ZvCLi3PuUQDEXSp0pkGG796wu1fRZCaRsCB-kLoa-_V7KJaGGhhoybN_c0GNOBhhwmGpx6Js26-Vx-lmWpfsPUE1aKrJfx-oMcyE5x7CooAlx4vA6iZhnNfmYdRejRKoKKnObyuAsym7mVdZY3bpv",
        "token_type": "bearer",
        "expires_in": 5183999
    }
    
    我想通过添加一些额外的属性来定制响应,比如

    {
        "access_token": "uEwmXl6N0mJXVUZesxA_2tG5lIuZUIUDaxtjAl0QGE6j2-J7n4c63zboOUClGjRQf1IDY9-nBgyq0HP5WR7MMxTYoHGIyiHIbcKu9AYwhECCGaVBCxY2Ounhit4N1pYK1vV6uX6AcoA-a0xhytF8Jz27D77ZvCLi3PuUQDEXSp0pkGG796wu1fRZCaRsCB-kLoa-_V7KJaGGhhoybN_c0GNOBhhwmGpx6Js26-Vx-lmWpfsPUE1aKrJfx-oMcyE5x7CooAlx4vA6iZhnNfmYdRejRKoKKnObyuAsym7mVdZY3bpv",
        "token_type": "bearer",
        "expires_in": 5183999,
        "attribute1" : "abc",
        "attribute2" : "ert"
    }
    

    有人有这样做的想法吗?

    最后,我调查了问题并找到了解决方案。我把它贴在这里了,也许它可以帮助别人

  • 添加身份验证属性

    var props = new AuthenticationProperties(new Dictionary<string, string>
    {
        {
             "attribute1" , "abc"
        },
        {
             "attribute2" , "ert"
        }
    });
    
  • 将票证添加到上下文中

    var ticket = new AuthenticationTicket(identity, props);
    
    context.Validated(ticket);
    
     public override Task TokenEndpoint(OAuthTokenEndpointContext context)
     {
         foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
         {
             context.AdditionalResponseParameters.Add(property.Key, property.Value);
         }
         return Task.FromResult<object>(null);
     }
    
  • 然后实现覆盖方法TokenEndpoint

    var ticket = new AuthenticationTicket(identity, props);
    
    context.Validated(ticket);
    
     public override Task TokenEndpoint(OAuthTokenEndpointContext context)
     {
         foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
         {
             context.AdditionalResponseParameters.Add(property.Key, property.Value);
         }
         return Task.FromResult<object>(null);
     }
    
    public覆盖任务令牌端点(OAuthTokenEndpointContext)
    {
    foreach(context.Properties.Dictionary中的KeyValuePair属性)
    {
    AdditionalResponseParameters.Add(property.Key,property.Value);
    }
    返回Task.FromResult(空);
    }
    
  • 最后,授权服务提供商

    public class AuthorizationServiceProvider : OAuthAuthorizationServerProvider
    {
        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
            return base.ValidateClientAuthentication(context);
        }
    
        public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    
            if (string.IsNullOrEmpty(context.UserName) || string.IsNullOrEmpty(context.Password))
            {
                context.SetError("invalid_request", "No username or password are provided.");
            }
            else if (Membership.ValidateUser(context.UserName, context.Password))
            {
                
                identity.AddClaim(new Claim("username", context.UserName));
                identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
    
                /*
                 * All custom response props are define here.
                 * --------usage----------
                 * use as dictionary
                 * */
                var props = new AuthenticationProperties(new Dictionary<string, string>
                {
                    //{
                    //    "test" , "val"
                    //}
                });
    
                var ticket = new AuthenticationTicket(identity, props);
    
    
                context.Validated(ticket);
            }
            else
            {
                context.SetError("invalid_grant", "Provide username and password is incorrect.");
    
            }
    
            return base.GrantResourceOwnerCredentials(context);
        }
    
        public override Task TokenEndpoint(OAuthTokenEndpointContext context)
        {
            foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
            {
                context.AdditionalResponseParameters.Add(property.Key, property.Value);
            }
            return Task.FromResult<object>(null);
        }
    }
    
    公共类AuthorizationServiceProvider:OAuthAuthorizationServerProvider { 公共覆盖任务ValidateClientAuthentication(OAuthValidateClientAuthenticationContext) { context.Validated(); 返回base.ValidateClientAuthentication(上下文); } 公共覆盖任务GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentials上下文) { var identity=newclaimsidentity(context.Options.AuthenticationType); if(string.IsNullOrEmpty(context.UserName)| string.IsNullOrEmpty(context.Password)) { SetError(“无效的_请求”,“未提供用户名或密码”); } else if(Membership.ValidateUser(context.UserName,context.Password)) { identity.AddClaim(新声明(“用户名”,context.username)); AddClaim(新声明(ClaimTypes.Name,context.UserName)); /* *这里定义了所有自定义响应道具。 *-----用途---------- *用作字典 * */ var props=新的AuthenticationProperties(新字典 { //{ //“测试”,“val” //} }); var票证=新的身份验证票证(身份、道具); 上下文。已验证(票证); } 其他的 { SetError(“无效的授权”,“提供的用户名和密码不正确”); } 返回base.GrantResourceOwnerCredentials(上下文); } 公共重写任务令牌端点(OAuthTokenEndpointContext) { foreach(context.Properties.Dictionary中的KeyValuePair属性) { AdditionalResponseParameters.Add(property.Key,property.Value); } 返回Task.FromResult(空); } } 有关更多信息-

    示例-