dotnet最小webApi开发实践

dotnet最小webApi开发实践

软件开发过程中,经常需要写一些功能验证代码。通常是创建一个console程序来验证测试,但黑呼呼的方脑袋界面,实在是不讨人喜欢。

Web开发目前已是网络世界中的主流,微软在asp.net框架大行其道之下,也整了个最小webapi项目开发向导。

今天,我也拥抱一下新的开发模式,来使用webapi方式来做一个小的应用实践。

打开宇宙最强编辑器VS2022,根据向导进行创建新项目,我们选择ASP.NET Core Web API项目。

填写项目配置信息,我们今天来创建一个访客IP白名单授权的功能。功能就是当访客访问web页面时,页面请求api授权,api对网络授权请求来源进行判断,当访客来源地址为白名单中的地址时,返回一个http 200的响应,当访客来源IP不在白名单时,返回一个 http 401未证的响应。

.net框架选项中,最低只有.net8.0可选

点击创建,vs自动为我们生成了项目和代码

复制代码
namespace flyfire.whitelistAuthorization
{
    public class Program
    {
        public static void Main( string [] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            // Add services to the container.
            builder.Services.AddControllers();

            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle

            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            var app = builder.Build();

            // Configure the HTTP request pipeline.

            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseAuthorization();
            app.MapControllers();
            app.Run();
        }
    }
}

框架不仅生成了代码,还默认增加了调试模式下使用丝袜哥(swagger)作为web测试的界面,真是贴心啊。

向导生成了一个天气预报的类和一个web控制器

天气预报的类

复制代码
namespace flyfire.whitelistAuthorization
{
    public class WeatherForecast
    {
        public DateOnly Date {  get ;  set ; }
        public int TemperatureC {  get ;  set ; }
        public int TemperatureF => 32 + ( int )(TemperatureC / 0.5556);
        public string ? Summary {  get ;  set ; }
    }
}

天气预报web控制器

复制代码
using Microsoft.AspNetCore.Mvc;
namespace flyfire.whitelistAuthorization.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };

        private readonly ILogger<WeatherForecastController> _logger;
        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet(Name = "GetWeatherForecast")]
         public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }
    }
}

什么代码都不用写,一个最小示例webApi接口方法就OK了。

下面我们来编写一个自己的功能。

在解决方案管理器控制目录上,右键菜单,新建一个API控制器。

选择API分类

我们创建一个名为 "WhitelistAuthorization"的空的API控制器.

我们将在WhitelistAuthorization控制器中,实现一个Authorization接口方法,当请求来源的IP地址为白名单地址时,返回StatusCode 200,并返回一些信息,否则返回StatusCode 401和未授权信息。

我们在appsetting.json中使用的个section存放白名单IP信息。

复制代码
 "WhiteIpList": {
    "IpList": [
      "127.0.0.1"
    ]
  }

我们创建一个类WhiteIpList用于映射配置数据。

复制代码
public class WhiteIpList
{
    public List< string > IpList {  get ;  set ; }
}

在Main函数中,增加如下代码,将配置段实例化绑定并注入到依赖注入(DI)容器

builder.Services.Configure<WhiteIpList>(builder.Configuration.GetSection("WhiteIpList"));

然后,我们在WhitelistAuthorization控制器的构造函数中,注入配置参数。

private readonly WhiteIpList _whiteIpList;

public WhitelistAuthorizationController(IOptions<WhiteIpList> whiteIpList)

{

_whiteIpList = whiteIpList.Value;

}

接着,我们增加一个认证授权方法,用于认证授权,返回状态码200或401。

复制代码
       [HttpGet("[action]")]
       [HttpPost("[action]")]
        public IActionResult Authorization()
        {
            var remote_ip = GetClientIpAddress(HttpContext.Request);

            if (Untility.IsIpExist(_whiteIpList.IpList, remote_ip))
            {
                return Ok(new
                {
                    body = new
                    {
                        code = 200
                    }
                });
            }
            else
            {
                return StatusCode(401, "Unauthorized: IP address not in whitelist.");
            }
        }

HttpRequest的HttpContext.Connection.RemoteIpAddress中可获得浏览端的IP地址。

不过,如果认证服务接口需经过Nginx转发时,则需要对Nginx进行一些配置以及相应的代码处理方可有效获取到浏览端的IP。

当网络HTTP请求经过Nginx服务器转发时,Web API仍然有可能获取到请求方的IP地址,但这取决于Nginx的配置以及Web API如何解析这些信息。

Nginx配置

Nginx可以通过proxy_set_header指令来添加或修改转发给后端服务器的请求头。为了获取请求方的IP地址,你需要在Nginx配置文件中设置X-Forwarded-For请求头,该请求头会包含客户端的原始IP地址。

例如,你可以在Nginx的配置文件(通常是nginx.conf或某个站点的配置文件)中添加以下行:

proxy_set_header X-Forwarded-For $remote_addr;

这行代码会将客户端的IP地址添加到X-Forwarded-For请求头中,并将其转发给后端服务器。如果客户端和Nginx之间有多层代理,X-Forwarded-For请求头可能会包含多个IP地址,第一个地址通常是客户端的原始IP。

Web API解析

在Web API中,你需要检查X-Forwarded-For请求头来获取客户端的IP地址。这通常涉及到从HTTP请求中提取请求头信息。

以下是一个在ASP.NET Core Web API中获取客户端IP地址的示例代码:

复制代码
    csharp

    public string GetClientIpAddress(HttpRequest request)

    {

        // 首先尝试从X-Forwarded-For请求头中获取IP地址

        var xForwardedFor = request.Headers["X-Forwarded-For"].ToString();

        if (!string.IsNullOrEmpty(xForwardedFor))

        {

            // 如果X-Forwarded-For包含多个IP地址,取第一个地址作为客户端IP

            var ipAddresses = xForwardedFor.Split(',');

            return ipAddresses.FirstOrDefault()?.Trim();

        }

 

        // 如果X-Forwarded-For不存在,则尝试从RemoteAddress属性中获取IP地址

        return request.HttpContext.Connection.RemoteIpAddress?.ToString();

    }

 

在这段代码中,我们首先尝试从X-Forwarded-For请求头中获取IP地址。如果请求头不存在或为空,我们则回退到从RemoteAddress属性中获取IP地址。但请注意,当请求经过Nginx转发时,RemoteAddress属性可能会包含Nginx服务器的IP地址,而不是客户端的IP地址。

注意事项

安全性:X-Forwarded-For请求头可以被客户端伪造,因此它不应该被视为绝对可靠的客户端IP地址来源。在需要高安全性的场景中,你可能需要采取额外的措施来验证客户端的IP地址。

配置一致性:确保你的Nginx服务器和后端Web API都正确配置了相关的请求头处理和解析逻辑。

多层代理:如果请求经过了多层代理服务器,X-Forwarded-For请求头可能会包含多个IP地址。你需要确定如何解析和使用这些地址。如果X-Forwarded-For包含多个IP地址,取第一个地址作为客户端IP

运行项目,在swaggerUI界面框架中进行测试验证

使用localhost地址测试,无法得到有效的IP址,白名单验证失败。

使用127.0.0.1的回环地址测试,可通过白名单验证。

以上,我们使用少量代码,就简单实现了一个支持Get和Post方法的并且可使用配置文件的Authorization授权接口。

相关推荐
贾光辉11 天前
.NET 中的线程安全数据结构
.net core
贾光辉12 天前
在 .NET Core 中使用 ActionBlock 实现高效率的多步骤数据处理
.net core
贾光辉13 天前
在.NET Core中使用异步多线程高效率的处理大量数据的最佳实践
.net core
波多尔斯基16 天前
CompilerGenerated与GeneratedCode区别
c#·.net·mvvm·.net core
贾光辉17 天前
使用 .NET Core 实现一个自定义日志记录器
.net core·ef core
亦世凡华、18 天前
从零开始:如何在.NET Core Web API中完美配置Swagger文档
开发语言·c#·swagger·.net core·web api
贾光辉25 天前
深入理解 Task.Delay 的定时精度及其影响因素
.net core
hez20101 个月前
0. RyuJIT Tutorials - RyuJIT 的历史和架构
.net·.net core·clr·compiler
小吴同学·1 个月前
项目代码第2讲:从0实现LoginController.cs,UsersController.cs、User相关的后端接口对应的前端界面
c#·.net·.netcore·.net core