Last active
December 15, 2020 13:43
-
-
Save Shazwazza/8c60cd9c3fd732689eafd83a7554f421 to your computer and use it in GitHub Desktop.
How to change HttpRequest.IsSecureConnection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Install this http module which will replace the HttpContext.Current at the beginning | |
// of the request with a wrapped one | |
public class MyHttpModule : IHttpModule | |
{ | |
private static Lazy<FieldInfo> _workerRequestType = new Lazy<FieldInfo>(() | |
=> typeof(HttpContext).GetField("_wr", BindingFlags.NonPublic | BindingFlags.Instance)); | |
public void Init(HttpApplication context) | |
{ | |
context.BeginRequest += Context_BeginRequest; | |
} | |
private void Context_BeginRequest(object sender, EventArgs e) | |
{ | |
// get the IIS7WorkerRequest instance to wrap using reflection | |
var current = HttpContext.Current; | |
var wr = (HttpWorkerRequest)_workerRequestType.Value.GetValue(current); | |
// replace the current context instance and pass in our delegate | |
HttpContext.Current = new HttpContext(new MyWorkerRequest(wr, IsSecure)); | |
} | |
private bool IsSecure(HttpWorkerRequest originalRequest) | |
{ | |
// NOTE: We can't really get the headers from the original HttpWorkerRequest, | |
// we just keep using the singleton | |
return HttpContext.Current.Request.Headers.ContainsKey("HTTP_X_FORWARDED_PROTO") | |
&& HttpContext.Current.Request.Headers["HTTP_X_FORWARDED_PROTO"] == "https"; | |
} | |
public void Dispose() | |
{ | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// implement and override every single method of the base class and wrap the calls | |
// except for the IsSecure() method which will return a value from the callback specified | |
public class MyWorkerRequest : HttpWorkerRequest | |
{ | |
private readonly HttpWorkerRequest _wrapped; | |
private readonly Func<HttpWorkerRequest, bool> _isSecure; | |
public MyWorkerRequest(HttpWorkerRequest wrapped, Func<HttpWorkerRequest, bool> isSecure) | |
{ | |
_wrapped = wrapped; | |
_isSecure = isSecure; | |
} | |
// override and call the callback | |
public override bool IsSecure() => _isSecure(_wrapped); | |
public override int EndRead(IAsyncResult asyncResult) => _wrapped.EndRead(asyncResult); | |
public override bool Equals(object obj) => _wrapped.Equals(obj); | |
public override string GetAppPath() => _wrapped.GetAppPath(); | |
public override string GetAppPathTranslated() => _wrapped.GetAppPathTranslated(); | |
public override string GetAppPoolID() => _wrapped.GetAppPoolID(); | |
public override long GetBytesRead() => _wrapped.GetBytesRead(); | |
public override byte[] GetClientCertificate() => _wrapped.GetClientCertificate(); | |
public override byte[] GetClientCertificateBinaryIssuer() => _wrapped.GetClientCertificateBinaryIssuer(); | |
public override int GetClientCertificateEncoding() => _wrapped.GetClientCertificateEncoding(); | |
public override byte[] GetClientCertificatePublicKey() => _wrapped.GetClientCertificatePublicKey(); | |
public override DateTime GetClientCertificateValidFrom() => _wrapped.GetClientCertificateValidFrom(); | |
public override DateTime GetClientCertificateValidUntil() => _wrapped.GetClientCertificateValidUntil(); | |
public override long GetConnectionID() => _wrapped.GetConnectionID(); | |
public override string GetFilePath() => _wrapped.GetFilePath(); | |
public override string GetFilePathTranslated() => _wrapped.GetFilePathTranslated(); | |
public override int GetHashCode() => _wrapped.GetHashCode(); | |
public override string GetKnownRequestHeader(int index) => _wrapped.GetKnownRequestHeader(index); | |
public override string GetPathInfo() => _wrapped.GetPathInfo(); | |
public override byte[] GetPreloadedEntityBody() => _wrapped.GetPreloadedEntityBody(); | |
public override int GetPreloadedEntityBody(byte[] buffer, int offset) => _wrapped.GetPreloadedEntityBody(buffer, offset); | |
public override int GetPreloadedEntityBodyLength() => _wrapped.GetPreloadedEntityBodyLength(); | |
public override string GetProtocol() => _wrapped.GetProtocol(); | |
public override byte[] GetQueryStringRawBytes() => _wrapped.GetQueryStringRawBytes(); | |
public override string GetRemoteName() => _wrapped.GetRemoteName(); | |
public override int GetRequestReason() => _wrapped.GetRequestReason(); | |
public override string GetServerName() => _wrapped.GetServerName(); | |
public override string GetServerVariable(string name) => _wrapped.GetServerVariable(name); | |
public override int GetTotalEntityBodyLength() => _wrapped.GetTotalEntityBodyLength(); | |
public override string GetUnknownRequestHeader(string name) => _wrapped.GetUnknownRequestHeader(name); | |
public override string[][] GetUnknownRequestHeaders() => _wrapped.GetUnknownRequestHeaders(); | |
public override long GetUrlContextID() => _wrapped.GetUrlContextID(); | |
public override IntPtr GetUserToken() => _wrapped.GetUserToken(); | |
public override IntPtr GetVirtualPathToken() => _wrapped.GetVirtualPathToken(); | |
public override bool HeadersSent() => _wrapped.HeadersSent(); | |
public override bool IsClientConnected() => _wrapped.IsClientConnected(); | |
public override bool IsEntireEntityBodyIsPreloaded() => _wrapped.IsEntireEntityBodyIsPreloaded(); | |
public override string MachineConfigPath => _wrapped.MachineConfigPath; | |
public override string MachineInstallDirectory => _wrapped.MachineInstallDirectory; | |
public override string MapPath(string virtualPath) => _wrapped.MapPath(virtualPath); | |
public override int ReadEntityBody(byte[] buffer, int offset, int size) => _wrapped.ReadEntityBody(buffer, offset, size); | |
public override int ReadEntityBody(byte[] buffer, int size) => _wrapped.ReadEntityBody(buffer, size); | |
public override Guid RequestTraceIdentifier => _wrapped.RequestTraceIdentifier; | |
public override string RootWebConfigPath => _wrapped.RootWebConfigPath; | |
public override void SendCalculatedContentLength(int contentLength) => _wrapped.SendCalculatedContentLength(contentLength); | |
public override void SendCalculatedContentLength(long contentLength) => _wrapped.SendCalculatedContentLength(contentLength); | |
public override void SendResponseFromMemory(IntPtr data, int length) => _wrapped.SendResponseFromMemory(data, length); | |
public override void SetEndOfSendNotification(EndOfSendNotification callback, object extraData) => _wrapped.SetEndOfSendNotification(callback, extraData); | |
public override bool SupportsAsyncFlush => _wrapped.SupportsAsyncFlush; | |
public override bool SupportsAsyncRead => _wrapped.SupportsAsyncRead; | |
public override string ToString() => _wrapped.ToString(); | |
public override IAsyncResult BeginFlush(AsyncCallback callback, object state) => _wrapped.BeginFlush(callback, state); | |
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => _wrapped.BeginRead(buffer, offset, count, callback, state); | |
public override void CloseConnection() => _wrapped.CloseConnection(); | |
public override void EndFlush(IAsyncResult asyncResult) => _wrapped.EndFlush(asyncResult); | |
public override void EndOfRequest() => _wrapped.EndOfRequest(); | |
public override void FlushResponse(bool finalFlush) => _wrapped.FlushResponse(finalFlush); | |
public override string GetHttpVerbName() => _wrapped.GetHttpVerbName(); | |
public override string GetHttpVersion() => _wrapped.GetHttpVersion(); | |
public override string GetLocalAddress() => _wrapped.GetLocalAddress(); | |
public override int GetLocalPort() => _wrapped.GetLocalPort(); | |
public override string GetQueryString() => _wrapped.GetQueryString(); | |
public override string GetRawUrl() => _wrapped.GetRawUrl(); | |
public override string GetRemoteAddress() => _wrapped.GetRemoteAddress(); | |
public override int GetRemotePort() => _wrapped.GetRemotePort(); | |
public override string GetUriPath() => _wrapped.GetUriPath(); | |
public override void SendKnownResponseHeader(int index, string value) => _wrapped.SendKnownResponseHeader(index, value); | |
public override void SendResponseFromFile(string filename, long offset, long length) => _wrapped.SendResponseFromFile(filename, offset, length); | |
public override void SendResponseFromFile(IntPtr handle, long offset, long length) => _wrapped.SendResponseFromFile(handle, offset, length); | |
public override void SendResponseFromMemory(byte[] data, int length) => _wrapped.SendResponseFromMemory(data, length); | |
public override void SendStatus(int statusCode, string statusDescription) => _wrapped.SendStatus(statusCode, statusDescription); | |
public override void SendUnknownResponseHeader(string name, string value) => _wrapped.SendUnknownResponseHeader(name, value); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This needs to be declared first in the owin pipeline | |
app.Use(async (owinContext, next) => | |
{ | |
if (owinContext.Request.Scheme != "https" | |
&& owinContext.Request.Headers.TryGetValue("HTTP_X_FORWARDED_PROTO", out var headerVals) | |
&& headerVals.Length > 0 | |
&& headerVals[0] == "https") | |
{ | |
// setting the scheme to "https" is how IsSecure returns true | |
owinContext.Request.Scheme = headerVals[0]; | |
} | |
await next.Invoke(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment