内网多个服务,使用的是http
域名请求经过https 协议请求到网关,网关使用http转发到内网服务。
内网获取到的协议头自然是http的,但是经过网关后header中带有了原始请求的协议头,存储在 X-Forwarded-Proto 中。
当内网要验证权限时候,有可能涉及到301,302的跳转。本次解决的问题,通过授权的跳转前事件 进行解决的,如果读者感兴趣可以通过中间件来解决
首先,在注册cookie票据认证时候需要配置上事件的处理程序
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Cookie.Name = "xxxx";
options.LoginPath = "/account/login"; //默认此路径,可以使用自定义路径
options.AccessDeniedPath = "/account/accessDenied";
options.Events.OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, options.Events.OnRedirectToAccessDenied); //注册跳转到未授权页面前的执行程序
options.Events.OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, options.Events.OnRedirectToLogin); //注册跳转到登录页面 前 的执行程序
});
或
//设置ajax下对状态码的处理逻辑,避免401 403这样的状态会返回302状态码
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, options.Events.OnRedirectToAccessDenied);
options.Events.OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, options.Events.OnRedirectToLogin);
});
执行程序中对响应的状态码,跳转地址等做处理。 本程序自动检测原始请求是https的时候,将内网的301/302 跳转地址转为 https头,这样就要不会出现协议降级的问题
//程序方法替换重定向方法
Func<RedirectContext<CookieAuthenticationOptions>, Task> ReplaceRedirector(HttpStatusCode statusCode, Func<RedirectContext<CookieAuthenticationOptions>, Task> existingRedirector)
{
Func<RedirectContext<CookieAuthenticationOptions>, Task> abc = (context) =>
{
Console.WriteLine("授权认证失败");
if (context.Request.Headers.ContainsKey("X-Requested-With") && context.Request.Headers["x-Requested-With"] == "XMLHttpRequest")
{
context.Response.StatusCode = (int)statusCode;
return Task.CompletedTask;
}
string reqScheme = Utils.Core.RequestHelper.GetScheme();
Console.WriteLine("认证请求的协议:" + reqScheme);
if (reqScheme == "https" && !context.RedirectUri.StartsWith("https"))
{
//检测并替换Response
context.Response.StatusCode = 301;
context.RedirectUri = "https" + context.RedirectUri.Remove(0, 4);
//return Task.CompletedTask;
}
return existingRedirector(context);
};
return abc;
}
附上检测协议头的方法:
public static string GetScheme()
{
string schemes = HttpContextUtil.Current.Request.Headers["X-Forwarded-Proto"].FirstOrDefault();
if (string.IsNullOrWhiteSpace(schemes))
{
return HttpContextUtil.Current.Request.Scheme;
}
string[] s=schemes.Split(',',StringSplitOptions.RemoveEmptyEntries);
return s[0];
}
HttpContextUtil.Current.Request 就是 http请求的 Request ,读者想办法自行获取到就可以替换这里的 Request对象
本文链接:https://blog.nnwk.net/article/139
有问题请留言。版权所有,转载请在显眼位置处保留文章出处,并留下原文连接
Leave your question and I'll get back to you as soon as I see it. All rights reserved. Please keep the source and links
友情链接:
子卿全栈
全部评论