在 ASP.NET Identity 中处理未经身份验证或未经授权的 API 请求

Handling unauthenticated or unauthorized API requests in ASP.NET Identity

提问人:Suiarm1 提问时间:11/3/2023 最后编辑:Zhi LvSuiarm1 更新时间:11/6/2023 访问量:111

问:

我目前正在从事一个 ASP.NET 项目,我正在使用 ASP.NET Identity 来管理用户帐户。我的 Web 应用程序中还包含一个 API。我目前的问题是,当客户端发出未经身份验证或授权的 API 请求时,它们会被重定向到登录/禁止页面。但是,我希望此类 API 请求返回 JSON 错误,而不是将用户重定向到登录页面。谁能帮我了解如何在我的 ASP.NET 应用程序中自定义此行为?我是否需要配置任何特定的中间件或设置来实现此行为?任何帮助或建议将不胜感激。

asp.net asp.net-mvc asp.net-core asp.net-identity

评论


答:

0赞 Yuning Duan 11/3/2023 #1

在你随后的描述中,我理解你

想要发出 API 请求以返回 JSON 错误而不是 将用户重定向到登录页面

在我的选择中,我建议您可以创建一个中间件来处理 API 请求和网页请求:

public class ApiRequestMiddleware
{
    private readonly RequestDelegate _next;

    public ApiRequestMiddleware(RequestDelegate next)
    {
        _next = next;
    }
 
    public async Task Invoke(HttpContext context)
    {
        if (context.Request.Path.StartsWithSegments("/api"))
        {
            
            try
            {
                
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                context.Response.ContentType = "application/json";

                var errorResponse = new
                {
                    message = "Unauthorized API requests",
                    error = "Authentication failed"
                };

                await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
            }
            catch (Exception ex)
            {
                
                context.Response.StatusCode = StatusCodes.Status500InternalServerError;
                context.Response.ContentType = "application/json";

                var errorResponse = new
                {
                    message = "serve error",
                    error = ex.Message
                };

                await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
            }
        }
        else
        {
            
            await _next(context);
        }
    }
}

评论

0赞 Suiarm1 11/3/2023
您的解决方案将为每个 API 请求返回一个 JSON 错误,无论它是授权的还是未经授权的。
0赞 Yuning Duan 11/6/2023 #2

根据您对我的解决方案的建议,我对我的代码进行了改进:

 public class ApiRequestMiddleware
    {
        private readonly RequestDelegate _next;
       
        public ApiRequestMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            if (context.Request.Path.StartsWithSegments("/api"))
            {
                
                try
                {
                    if  (context.User.Identity.IsAuthenticated && context.User.IsInRole("Administrator"))
                        {
                        var user = context.User;
                        var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                        var username = user.FindFirst(ClaimTypes.Name)?.Value;
                      
                        context.Response.ContentType = "application/json";
                        var successResponse = new
                        {
                            message = "Authorization passed",
                            UserId = userId,
                            Username = username
                        };
                        await context.Response.WriteAsync(JsonConvert.SerializeObject(successResponse));

                    }
                    else
                    { 
                        context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                        context.Response.ContentType = "application/json";

                        var errorResponse = new
                        {
                            message = "Unauthorized API requests",
                            error = "Authentication failed"
                        };

                        await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
                    }
                }
                catch (Exception ex)
                { 
                    context.Response.StatusCode = StatusCodes.Status500InternalServerError;
                    context.Response.ContentType = "application/json";

                    var errorResponse = new
                    {
                        message = "serve error",
                        error = ex.Message
                    };

                    await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
                }
            }
            else
            {
                await _next(context);
            }
        }
    }

}

当我通过授权时,API 将返回当前用户数据:enter image description here

当我未经授权的 API 请求时,它将返回一个 json:

enter image description here

还有其他方法:

public async Task Invoke(HttpContext context)
{
    if (context.Request.Path.StartsWithSegments("/api"))
    {
                
        try
        {
            if  (context.User.Identity.IsAuthenticated && context.User.IsInRole("Administrator"))
                {
                        
                if (context.Request.Path.StartsWithSegments("/api/Test"))
                {
                    await CallApiResource(context);
                }
            }
            else
            { 
                context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                context.Response.ContentType = "application/json";

                var errorResponse = new
                {
                    message = "Unauthorized API requests",
                    error = "Authentication failed"
                };

                await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
            }
        }
        catch (Exception ex)
        { 
            context.Response.StatusCode = StatusCodes.Status500InternalServerError;
            context.Response.ContentType = "application/json";

            var errorResponse = new
            {
                message = "serve error",
                error = ex.Message
            };

            await context.Response.WriteAsync(JsonConvert.SerializeObject(errorResponse));
        }
    }
    else
    {
        await _next(context);
    }
}

private async Task CallApiResource(HttpContext context)
{
           
     var apiController = new TestApiController();
     var apiData = apiController.GetUsers() as ObjectResult;

     if (apiData != null)
     {
         var users = apiData.Value;

               
         var successResponse = new
         {
             message = "Authorization passed",
             data = users
         };

         var json = JsonConvert.SerializeObject(successResponse);

         context.Response.ContentType = "application/json";
         context.Response.StatusCode = StatusCodes.Status200OK;
         await context.Response.WriteAsync(json);
     }
}

[Route("api/test")]
[ApiController]
public class TestApiController : ControllerBase
{
    [HttpGet("users")]
    public IActionResult GetUsers()
    {
       
        var users = new List<string> { "User1", "User2", "User3" };

        return Ok(users);
    }
}

当我通过授权时,我可以通过CallApiResource获取用户:enter image description here

当我未经授权时:enter image description here