[feat]新增ForceRedirect,强制跳转。指定目标schema和host,在GET访问发现不一致时强制跳转,host支持*。常用于强制跳转https,如https://*:8081

This commit is contained in:
大石头 2024-04-18 18:05:41 +08:00
parent ed35914f53
commit 14cba92919
11 changed files with 74 additions and 8 deletions

View File

@ -6,7 +6,7 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:8080;https://localhost:5001",
"applicationUrl": "http://localhost:8080;https://localhost:8080",
"dotnetRunMessages": true
},
"Docker": {

View File

@ -70,7 +70,7 @@ public class SsoController : ControllerBaseX
public SsoController(ICacheProvider cacheProvider) => _cache = cacheProvider.Cache;
#region
private String GetUserAgent() => Request.Headers["User-Agent"] + "";
private String GetUserAgent() => Request.Headers.UserAgent + "";
/// <summary>第三方登录</summary>
/// <param name="name"></param>

View File

@ -90,6 +90,7 @@
<Compile Include="..\NewLife.CubeNC\ViewModels\SearchField.cs" Link="ViewModels\SearchField.cs" />
<Compile Include="..\NewLife.CubeNC\ViewModels\TextAligns.cs" Link="ViewModels\TextAligns.cs" />
<Compile Include="..\NewLife.CubeNC\ViewModels\ViewKinds.cs" Link="ViewModels\ViewKinds.cs" />
<Compile Include="..\NewLife.CubeNC\WebMiddleware\MiddlewareHelper.cs" Link="WebMiddleware\MiddlewareHelper.cs" />
<Compile Include="..\NewLife.CubeNC\WebMiddleware\TenantMiddleware.cs" Link="WebMiddleware\TenantMiddleware.cs" />
</ItemGroup>
<ItemGroup>

View File

@ -82,6 +82,11 @@ public class CubeSetting : Config<CubeSetting>
[Description("机器人错误码。设置后拦截各种爬虫并返回相应错误如404/500默认0不拦截")]
[Category("通用")]
public Int32 RobotError { get; set; }
/// <summary>强制跳转。指定目标schema和host在GET访问发现不一致时强制跳转host支持*。常用于强制跳转https如https://*:8081</summary>
[Description("强制跳转。指定目标schema和host在GET访问发现不一致时强制跳转host支持*。常用于强制跳转https如https://*:8081")]
[Category("通用")]
public String ForceRedirect { get; set; }
#endregion
#region

View File

@ -38,13 +38,16 @@ public class RunTimeMiddleware
/// <returns></returns>
public async Task Invoke(HttpContext ctx)
{
var userAgent = ctx.Request.Headers["User-Agent"] + "";
var userAgent = ctx.Request.Headers.UserAgent + "";
var ua = new UserAgentParser();
ua.Parse(userAgent);
// 识别拦截爬虫
if (!ValidRobot(ctx, ua)) return;
// 强制访问Https
if (MiddlewareHelper.CheckForceRedirect(ctx)) return;
var ip = ctx.GetUserHost();
ManageProvider.UserHost = ip;

View File

@ -282,7 +282,7 @@ public class UserController : EntityController<User, UserModel>
// 部分提供支持应用内免登录,直接跳转
if (ms != null && ms.Count > 0 && logId == 0 && GetRequest("autologin") != "0")
{
var agent = Request.Headers["User-Agent"] + "";
var agent = Request.Headers.UserAgent + "";
if (!agent.IsNullOrEmpty())
{
foreach (var item in ms)

View File

@ -73,7 +73,7 @@ public class SsoController : ControllerBaseX
public virtual ActionResult Index() => Redirect("~/");
#region
private String GetUserAgent() => Request.Headers["User-Agent"] + "";
private String GetUserAgent() => Request.Headers.UserAgent + "";
/// <summary>第三方登录</summary>
/// <param name="name"></param>

View File

@ -31,7 +31,7 @@ public static class SameSiteCookiesServiceCollectionExtensions
{
if (options.SameSite == SameSiteMode.None)
{
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
var userAgent = httpContext.Request.Headers.UserAgent.ToString();
if (DisallowsSameSiteNone(userAgent))
{

View File

@ -79,6 +79,16 @@ public class CubeSetting : Config<CubeSetting>
[Description("机器人错误码。设置后拦截各种爬虫并返回相应错误如404/500默认0不拦截")]
[Category("通用")]
public Int32 RobotError { get; set; }
///// <summary>强制使用SSL。强制访问https使用http访问时跳转</summary>
//[Description("强制使用SSL。强制访问https使用http访问时跳转")]
//[Category("通用")]
//public Boolean ForceSSL { get; set; }
/// <summary>强制跳转。指定目标schema和host在GET访问发现不一致时强制跳转host支持*。常用于强制跳转https如https://*:8081</summary>
[Description("强制跳转。指定目标schema和host在GET访问发现不一致时强制跳转host支持*。常用于强制跳转https如https://*:8081")]
[Category("通用")]
public String ForceRedirect { get; set; }
#endregion
#region

View File

@ -0,0 +1,45 @@
using NewLife.Web;
using HttpContext = Microsoft.AspNetCore.Http.HttpContext;
namespace NewLife.Cube.WebMiddleware;
/// <summary>中间件助手</summary>
public static class MiddlewareHelper
{
/// <summary>检查是否强制跳转</summary>
/// <param name="ctx"></param>
/// <returns></returns>
public static Boolean CheckForceRedirect(HttpContext ctx)
{
if (ctx.Request.Method != "GET") return false;
var set = CubeSetting.Current;
if (set.ForceRedirect.IsNullOrEmpty()) return false;
// 分解跳转地址
var ss = set.ForceRedirect.Split("://", ":");
var scheme = ss.Length > 0 ? ss[0] : "";
var host = ss.Length > 1 ? ss[1] : ss[0];
var port = ss.Length > 2 ? ss[2].ToInt() : 0;
if (ss.Length == 1) scheme = null;
if (host == "*") host = null;
if (scheme.IsNullOrEmpty() && host.IsNullOrEmpty() && port == 0) return false;
var uri = ctx.Request.GetRawUrl();
if ((scheme.IsNullOrEmpty() || uri.Scheme.EqualIgnoreCase(scheme)) &&
(host.IsNullOrEmpty() || uri.Host.EqualIgnoreCase(host)) &&
(port == 0 || port == uri.Port)) return false;
// 重建url
if (scheme.IsNullOrEmpty()) scheme = uri.Scheme;
if (host.IsNullOrEmpty()) host = uri.Host;
if (port == 0) port = uri.Port;
var url = $"{scheme}://{host}:{port}{uri.PathAndQuery}";
ctx.Response.Redirect(url);
return true;
}
}

View File

@ -1,5 +1,4 @@
using System.Diagnostics;
using System.Net;
using System.Web;
using NewLife.Common;
using NewLife.Cube.Entity;
@ -38,7 +37,7 @@ public class RunTimeMiddleware
/// <returns></returns>
public async Task Invoke(HttpContext ctx)
{
var userAgent = ctx.Request.Headers["User-Agent"] + "";
var userAgent = ctx.Request.Headers.UserAgent + "";
var ua = new UserAgentParser();
ua.Parse(userAgent);
ctx.Items["UserAgent"] = ua;
@ -46,6 +45,9 @@ public class RunTimeMiddleware
// 识别拦截爬虫
if (!ValidRobot(ctx, ua)) return;
// 强制访问Https
if (MiddlewareHelper.CheckForceRedirect(ctx)) return;
var ip = ctx.GetUserHost();
ManageProvider.UserHost = ip;