.NET Core 中使用 JWT 令牌或 API 密钥的授权机制 [英] Authorization mechanism which uses JWT token OR API-key in .NET Core

查看:40
本文介绍了.NET Core 中使用 JWT 令牌或 API 密钥的授权机制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 .NET Core 3.1 的新手,我正在尝试创建一种授权机制,该机制将使用 JWT 令牌或 API 密钥.此机制将用于除为登录机制提供服务的端点之外的所有端点.我试图以显示的方式创建 API 密钥属性

参考这篇文章.

另外,也可以考虑基于Authorization方法对action方法进行分组,对于API-key相关的action方法或controller,只需添加自定义API-Key属性,action方法需要JWT认证,添加即可[Authorize] 属性.

I'm new to .NET Core 3.1 and I'm trying to create an authorization mechanism, that will use JWT tokens or API-key. This mechanism will be used for all endpoints except endpoints that will serve the login mechanism. 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. Is there any chance to have both authorization methods working in parallel? If so, please guide me on how to achieve that.

Sample code can be found 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.

The issue relates that when using custom API-Key attribute with the [Authorize] attribute together, the controller or the action method will be configured both JWT authentication and API-Key validation, in the request header, it should contain both the JWT token and API-Key. If any of them are missing, it will display a 401 Unauthorized error.

Is there any chance to have both authorization methods working in parallel? If so, please guide me on how to achieve that.

Do you mean use any of the authorization method, you could access the related action method, if that is the case, you could try to use the custom the Authorization attributes.

For example: create a CustomAuthorization with the following code:

[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;
    }
}

Then, use the above CustomAuthorization in the API controller:

[Route("api/[controller]")]
[ApiController]
//[Authorize]
//[ApiKey]
[CustomAuthorization]
public class ValuesController : ControllerBase
{
    // GET: api/<ValuesController>
    [HttpGet]
    public IEnumerable<string> Get()
    {
        return new string[] { "value1", "value2" };
    }

The result like this:

Refer this article.

Besides, you could also consider group the action method based on the Authorization method, for the API-key related action method or controller, only add the custom API-Key attribute, for the action method needs to JWT authentication, just add the [Authorize] attribute.

这篇关于.NET Core 中使用 JWT 令牌或 API 密钥的授权机制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆