JWT身份验证如何在单独的API项目而不是AuthServer项目中验证http请求

时间:2019-04-12 16:23:47

标签: c# asp.net-web-api asp.net-core jwt

在阅读了几篇文章之后,尤其是this

我制作了自己的具有

的ASP.NET Core解决方案
  

AuthenticationAuthorisation的1个项目(AuthServer),以及

     

1个项目(WebApi),用于我整个项目中的其余API。

问题是: 如何在我的WebApi项目中验证http请求?

我知道,一旦用户通过身份验证,客户端将持有令牌,对于后续请求,他们都需要传递int令牌,而在服务器端,它将以某种方式通过以下代码验证这些请求: AuthServer项目的Startup.cs:

services.AddAuthentication(x =>
        {
            x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        })
        .AddJwtBearer(x=> {
            x.Events = new JwtBearerEvents
            {
                OnTokenValidated = context =>
                {
                    var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>();
                    var userId = context.Principal.Identity.Name;
                    var user = userService.GetById(userId);
                    if(user == null)
                    {
                        context.Fail("Unauthorized");
                    }
                    return Task.CompletedTask;
                }
            };
            x.RequireHttpsMetadata = false;
            x.SaveToken = true;
            x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };

        });

但是对于WebApi项目,我需要做什么来验证令牌? 我想这不只是在控制器或类似这样的动作上放置注解( [Authorize]

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{ ....}

那我该怎么做才能在WebApi项目中验证令牌? 通过在每次收到请求时在我的AuthServer项目中调用Authenticate端点,然后在WebApi中执行代码?

2 个答案:

答案 0 :(得分:1)

我假设您要运行2个单独的ASP.NET应用程序。 您可以通过向您的WebApi发送http请求来验证来自AuthServer的请求。 您可以创建一个自定义属性,以完成此任务。 在WebApi项目中:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;

namespace YourNamespace
{
    public class YourCustomAttribute : TypeFilterAttribute
    { 
        public YourCustomAuthAttribute(
            : base(typeof(AuthFilter))
        {
            Arguments = new object[] {
               // arguments gets passed to AuthFilter contructor,

            };
        }
    }

    public class AuthFilter : IAsyncAuthorizationFilter
    {
        private static readonly HttpClient http = new HttpClient();

        public AuthFilter()
        {
        }

        //Change it to fit your logic
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            var authorizationHeader = context.HttpContext.Request.Headers["Authtorization"];
            if (authorizationHeader == StringValues.Empty)
            {
                context.Result = new UnauthorizedResult();
            }
            else
            {
                var response = await http.GetAsync(
                    "your AuthServer address/login/?token=" + authorizationHeader.ToString(),
                    HttpCompletionOption.ResponseHeadersRead //because we want only status code
                );
                if (response.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    context.Result = new ForbidResult();
                }
            }
        }
    }
}

假设您在AuthServer项目的LoginController中具有以下端点

[HttpGet]
public IActionResult ValidateToken(string token)
{
   //your logic here
}

属性用法与[Authorize]相同。

也请检查此链接(我已经使用了其中的一些代码)https://www.red-gate.com/simple-talk/dotnet/net-development/jwt-authentication-microservices-net/。 它显示了如何手动验证Jwt令牌。

您可能还需要在AuthServer项目中设置CORS,以允许WebApi发出请求 Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors(options =>
            {
                options.AddPolicy("AllowAllHeaders",
                      builder =>
                      {
                          builder.AllowAnyOrigin()
                                 .AllowAnyHeader()
                                 .AllowAnyMethod();
                      });
            });
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IServiceProvider serviceProvider)
        {
            app.UseCors("AllowAllHeaders");
        }

答案 1 :(得分:0)

After hours and hours reading, I found an article talking about whether to have AuthServer separated from your API Server.

In huge commercial projects, it's definitely better to have them separated, but in my case, it's just my side project, so I ended up with build them together to save energy.