在 .NET Core 中使用 JWT 令牌或 API-key 的授权机制
Authorization mechanism which uses JWT token OR API-key in .NET Core
我是 .NET Core 3.1 的新手,我正在尝试创建一个授权机制,它将使用 JWT 令牌或 API-key。此机制将用于所有端点,但服务于登录机制的端点除外。我试图以 here 所示的方式创建一个 API-key 属性并用它装饰所有控制器,但是,这仅在未设置 [Authorize] 属性时有效。当我设置 [Authorize] 属性并在我的 API-key 属性中设置一个断点时,它永远不会到达并且我得到 401 Unauthorized 作为响应。是否有机会让两种授权方法并行工作?如果是这样,请指导我如何实现它。
可以找到示例代码here
I was trying to create an API-key attribute in a way shown here and
decorate all controllers with it but, this was only working when no
[Authorize] attribute was set. When I set [Authorize] attribute and
set a breakpoint in my API-key attribute it will never be reached and
I'm getting 401 Unauthorized as a response.
问题涉及当自定义API-Key属性与[Authorize]
属性一起使用时,控制器或操作方法将同时配置JWT认证和API-Key验证,在请求 header,它应该同时包含 JWT 令牌和 API-Key。如果缺少其中任何一个,它将显示 401 未授权错误。
Is there any chance to have both authorization methods working in
parallel? If so, please guide me on how to achieve that.
你的意思是使用任何一种授权方法,你可以访问相关的操作方法,如果是这样,你可以尝试使用自定义的授权属性。
例如:使用以下代码创建一个 CustomAuthorization:
[AttributeUsage(AttributeTargets.Class)]
public class CustomAuthorization : Attribute, IAuthorizationFilter
{
/// <summary>
/// This will Authorize User
/// </summary>
/// <returns></returns>
public void OnAuthorization(AuthorizationFilterContext filterContext)
{
if (filterContext != null)
{
//get the authorization header
Microsoft.Extensions.Primitives.StringValues authTokens;
filterContext.HttpContext.Request.Headers.TryGetValue("Authorization", out authTokens);
var _token = authTokens.FirstOrDefault();
if (_token != null)
{
string authToken = _token;
if (authToken != null)
{
if (IsValidToken(authToken))
{
filterContext.HttpContext.Response.Headers.Add("Authorization", authToken);
filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");
filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");
return;
}
else
{
filterContext.HttpContext.Response.Headers.Add("Authorization", authToken);
filterContext.HttpContext.Response.Headers.Add("AuthStatus", "NotAuthorized");
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Not Authorized";
filterContext.Result = new JsonResult("NotAuthorized")
{
Value = new
{
Status = "Error",
Message = "Invalid Token"
},
};
}
}
}
else
{
//if the request header doesn't contain the authorization header, try to get the API-Key.
Microsoft.Extensions.Primitives.StringValues apikey;
var key = filterContext.HttpContext.Request.Headers.TryGetValue("ApiKey", out apikey);
var keyvalue = apikey.FirstOrDefault();
//if the API-Key value is not null. validate the API-Key.
if(keyvalue != null)
{
filterContext.HttpContext.Response.Headers.Add("ApiKey", keyvalue);
filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");
filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");
return;
}
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Please Provide authToken";
filterContext.Result = new JsonResult("Please Provide auth Token")
{
Value = new
{
Status = "Error",
Message = "Please Provide auth Token"
},
};
}
}
}
public bool IsValidToken(string authToken)
{
//validate Token here
return true;
}
}
然后,在API控制器中使用上面的CustomAuthorization:
[Route("api/[controller]")]
[ApiController]
//[Authorize]
//[ApiKey]
[CustomAuthorization]
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
结果是这样的:
参考this article.
另外,也可以考虑根据Authorization方法对action方法进行分组,对于API-key相关的action方法或controller,只添加自定义的API-Key属性,因为action方法需要JWT认证,只需添加[Authorize]
属性。
我是 .NET Core 3.1 的新手,我正在尝试创建一个授权机制,它将使用 JWT 令牌或 API-key。此机制将用于所有端点,但服务于登录机制的端点除外。我试图以 here 所示的方式创建一个 API-key 属性并用它装饰所有控制器,但是,这仅在未设置 [Authorize] 属性时有效。当我设置 [Authorize] 属性并在我的 API-key 属性中设置一个断点时,它永远不会到达并且我得到 401 Unauthorized 作为响应。是否有机会让两种授权方法并行工作?如果是这样,请指导我如何实现它。
可以找到示例代码here
I was trying to create an API-key attribute in a way shown here and decorate all controllers with it but, this was only working when no [Authorize] attribute was set. When I set [Authorize] attribute and set a breakpoint in my API-key attribute it will never be reached and I'm getting 401 Unauthorized as a response.
问题涉及当自定义API-Key属性与[Authorize]
属性一起使用时,控制器或操作方法将同时配置JWT认证和API-Key验证,在请求 header,它应该同时包含 JWT 令牌和 API-Key。如果缺少其中任何一个,它将显示 401 未授权错误。
Is there any chance to have both authorization methods working in parallel? If so, please guide me on how to achieve that.
你的意思是使用任何一种授权方法,你可以访问相关的操作方法,如果是这样,你可以尝试使用自定义的授权属性。
例如:使用以下代码创建一个 CustomAuthorization:
[AttributeUsage(AttributeTargets.Class)]
public class CustomAuthorization : Attribute, IAuthorizationFilter
{
/// <summary>
/// This will Authorize User
/// </summary>
/// <returns></returns>
public void OnAuthorization(AuthorizationFilterContext filterContext)
{
if (filterContext != null)
{
//get the authorization header
Microsoft.Extensions.Primitives.StringValues authTokens;
filterContext.HttpContext.Request.Headers.TryGetValue("Authorization", out authTokens);
var _token = authTokens.FirstOrDefault();
if (_token != null)
{
string authToken = _token;
if (authToken != null)
{
if (IsValidToken(authToken))
{
filterContext.HttpContext.Response.Headers.Add("Authorization", authToken);
filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");
filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");
return;
}
else
{
filterContext.HttpContext.Response.Headers.Add("Authorization", authToken);
filterContext.HttpContext.Response.Headers.Add("AuthStatus", "NotAuthorized");
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Not Authorized";
filterContext.Result = new JsonResult("NotAuthorized")
{
Value = new
{
Status = "Error",
Message = "Invalid Token"
},
};
}
}
}
else
{
//if the request header doesn't contain the authorization header, try to get the API-Key.
Microsoft.Extensions.Primitives.StringValues apikey;
var key = filterContext.HttpContext.Request.Headers.TryGetValue("ApiKey", out apikey);
var keyvalue = apikey.FirstOrDefault();
//if the API-Key value is not null. validate the API-Key.
if(keyvalue != null)
{
filterContext.HttpContext.Response.Headers.Add("ApiKey", keyvalue);
filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");
filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");
return;
}
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Please Provide authToken";
filterContext.Result = new JsonResult("Please Provide auth Token")
{
Value = new
{
Status = "Error",
Message = "Please Provide auth Token"
},
};
}
}
}
public bool IsValidToken(string authToken)
{
//validate Token here
return true;
}
}
然后,在API控制器中使用上面的CustomAuthorization:
[Route("api/[controller]")]
[ApiController]
//[Authorize]
//[ApiKey]
[CustomAuthorization]
public class ValuesController : ControllerBase
{
// GET: api/<ValuesController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
结果是这样的:
参考this article.
另外,也可以考虑根据Authorization方法对action方法进行分组,对于API-key相关的action方法或controller,只添加自定义的API-Key属性,因为action方法需要JWT认证,只需添加[Authorize]
属性。