解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
3.84 KiB
X
using System.Net;
using NewLife.Log;

namespace NewLife.Http;

/// <summary>HTTP中间件委托</summary>
/// <param name="context">Http上下文</param>
/// <param name="next">下一个中间件或处理器的调用委托</param>
/// <returns>异步任务</returns>
public delegate Task HttpMiddlewareDelegate(IHttpContext context, Func<Task> next);

/// <summary>CORS 跨域中间件</summary>
/// <remarks>
/// <para>自动处理 OPTIONS 预检请求和设置 CORS 响应头。</para>
/// <para>
/// 响应头取值只来自配置,不随请求源变化,因此无需 <c>Vary: Origin</c>;
/// 若将来改为按请求源回显,必须同时补上该头部,否则共享缓存会把某个源的响应发给其它源。
/// </para>
/// 
/// <code>
/// server.Use(new CorsMiddleware
/// {
///     AllowOrigin = "*",
///     AllowMethods = "GET, POST, PUT, DELETE",
///     AllowHeaders = "Content-Type, Authorization",
///     AllowCredentials = false,
///     MaxAge = 3600
/// });
/// </code>
/// </remarks>
public class CorsMiddleware
{
    #region 属性
    /// <summary>允许的源。默认 *</summary>
    public String AllowOrigin { get; set; } = "*";

    /// <summary>允许的方法。默认 GET, POST, PUT, DELETE, OPTIONS</summary>
    public String AllowMethods { get; set; } = "GET, POST, PUT, DELETE, OPTIONS";

    /// <summary>允许的请求头。默认 Content-Type, Authorization, X-Requested-With</summary>
    public String AllowHeaders { get; set; } = "Content-Type, Authorization, X-Requested-With";

    /// <summary>暴露的响应头</summary>
    public String? ExposeHeaders { get; set; }

    /// <summary>是否允许携带凭据</summary>
    public Boolean AllowCredentials { get; set; }

    /// <summary>预检缓存时间(秒)</summary>
    public Int32 MaxAge { get; set; } = 3600;
    #endregion

    /// <summary>中间件入口</summary>
    /// <param name="context">Http上下文</param>
    /// <param name="next">下一个中间件</param>
    /// <returns></returns>
    public Task Invoke(IHttpContext context, Func<Task> next)
    {
        var req = context.Request;

        // 设置 CORS 响应头
        SetCorsHeaders(context);

        // 处理 OPTIONS 预检请求
        if (req?.Method == "OPTIONS")
        {
            context.Response.StatusCode = HttpStatusCode.NoContent;
            return TaskEx.CompletedTask;
        }

        return next();
    }

    private void SetCorsHeaders(IHttpContext context)
    {
        var res = context.Response;

        if (!AllowOrigin.IsNullOrEmpty())
        {
            // 通配源与凭据同用被 Fetch 规范禁止(浏览器直接拒收该响应),属于配置错误。
            // 此处失败关闭:不发通配源并警示,而不是按请求源回显——回显等于把“任意源 + 凭据”放行,
            // 属 CORS 反射型漏洞,对 Cookie 鉴权的后台即 CSRF 与数据泄露面。要用凭据请把 AllowOrigin 设为明确的源
            if (AllowCredentials && AllowOrigin.EqualIgnoreCase("*"))
                XTrace.WriteLine("[CorsMiddleware] 配置无效:AllowOrigin=* 与 AllowCredentials=true 不能同时使用,已忽略 Access-Control-Allow-Origin。请把 AllowOrigin 设置为明确的源。");
            else
                res.Headers["Access-Control-Allow-Origin"] = AllowOrigin;
        }

        if (!AllowMethods.IsNullOrEmpty())
            res.Headers["Access-Control-Allow-Methods"] = AllowMethods;

        if (!AllowHeaders.IsNullOrEmpty())
            res.Headers["Access-Control-Allow-Headers"] = AllowHeaders;

        if (!ExposeHeaders.IsNullOrEmpty())
            res.Headers["Access-Control-Expose-Headers"] = ExposeHeaders;

        if (AllowCredentials)
            res.Headers["Access-Control-Allow-Credentials"] = "true";

        if (MaxAge > 0)
            res.Headers["Access-Control-Max-Age"] = MaxAge + "";
    }
}