通过调用其他服务来消费JWT



有许多资源描述了使用.Net Web API在C#中实现JWT创建和使用。然而,我正在努力使我当前的系统适应列出的任何教程。

到目前为止,我一直在发送我的JWT令牌作为查询字符串的一部分,如下所示:

/api/用户?jwt=

我的路线看起来像这样:

public async Task<IHttpActionResult> GetUsers(string jwt)
{
       var userValidationResult = await Utility.ValidateUser(jwt);
       if (!userValidationResult.Validated)
       {
           return Unauthorized();
       }
       ...
}

您可以在下面查看该验证用户方法的内容。请注意,我实际上是通过将JWT发送到另一个服务器进行身份验证来验证它的。

   public class UserValidationResult
   {
       public bool Validated { get; set; }
       public string Email { get; set; }
       public List<string> Roles { get; set; }
   }
   public static Task<UserValidationResult> ValidateUser(string jwt)
   {
       var taskCompletionSource = new TaskCompletionSource<UserValidationResult>();
       var authenticationRoute = "http://authserver:5000/authenticate?jwt=" +jwt;
       var authenticationClient = new RestClient(authenticationRoute);
       var authenticationRequest = new RestRequest(Method.GET);
       authenticationClient.ExecuteAsync(authenticationRequest, authenticationResponse =>
       {
           var authenticationResponseInJson = JObject.Parse(authenticationResponse.Content.ToString());
           var payload = JObject.Parse(authenticationResponseInJson["payload"].ToString());
           taskCompletionSource.SetResult(new UserValidationResult()
           {
               Validated = bool.Parse(authenticationResponseInJson["success"].ToString()),
               Email = ...
               Roles = ...
           });
       });
       return taskCompletionSource.Task;
   }

这很管用。然而,我更喜欢使用您在所有OWIN/Katana教程中看到的漂亮的[Authorize]属性。有没有一种方法可以让Owin中间件像现在一样,根据我的Validate方法验证jwt令牌,除了使用Authorize属性?

编辑

因此,我实现了以下中间件,并在我的启动类中使用它:

public class AuthorizationMiddleware : OwinMiddleware
{
    private OwinMiddleware _next;
    public AuthorizationMiddleware(OwinMiddleware next):base(next)
    {
    }
    public override async Task Invoke(IOwinContext context)
    {
        var jwt = context.Request.Query.Get("jwt");
        if (jwt != null)
        {
            var userValidationResult = await Utility.ValidateUser(jwt);
            if (userValidationResult.Validated)
            {
                var jwtoken = new JwtSecurityToken(jwt);
                var identity = new ClaimsIdentity("jwt");
                //foreach (var role in userValidationResult.Roles)
                //    identity.AddClaim(new Claim(ClaimTypes.Role, role));
                identity.AddClaim(new Claim(ClaimTypes.Email, userValidationResult.Email));
                context.Request.User = new ClaimsPrincipal(identity);
            }
        }
        await _next.Invoke(context);
    }
}
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use<AuthorizationMiddleware>();
        var config = new HttpConfiguration();
        app.UseWebApi(config);
    }
}

但是,我用Authorize属性修饰的路由似乎都没有碰到invoke方法中的任何断点。我总是得到一个未经授权的401。为什么会这样?

您可以在OWIN管道之上实现一个基本中间件。简单的东西可以满足你的要求:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use(async (ctx, next) =>
        {
            var jwt = ctx.Request.Query.Get("jwt");
            if (jwt != null)
            {
                var userValidationResult = await Utility.ValidateUser(jwt);
                if (userValidationResult.Validated)
                {
                    var identity = new ClaimsIdentity("jwt");
                    foreach(var role in userValidationResult.Roles)
                        identity.AddClaim(new Claim(ClaimTypes.Role, role));
                    identity.AddClaim(new Claim(ClaimTypes.Email, userValidationResult.Email));
                    //etc... add every claim
                    ctx.Request.User = new ClaimsPrincipal(identity);
                }
            }
            await next.Invoke();
        });
        var config = new HttpConfiguration();
        app.UseWebApi(config);
        //etc...
    }
}

这只是一个存根,您可能需要扩展代码以使其在您的特定环境中工作。

像这样的中间件将设置Request.User,然后由其他中间件使用(包括Web API Authorize过滤器)。然后,您可以使用[Authorize()]属性自由地装饰控制器/操作。

如果您需要更灵活的东西,那么我建议您阅读更多关于如何实现身份验证中间件的内容。

Brock Allen的这个资源也可以帮助您实现这样一个实现:OWIN身份验证中间件体系结构。

相关内容

最新更新