Skip to content

Instantly share code, notes, and snippets.

@Shazwazza
Last active December 15, 2020 13:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Shazwazza/8c60cd9c3fd732689eafd83a7554f421 to your computer and use it in GitHub Desktop.
Save Shazwazza/8c60cd9c3fd732689eafd83a7554f421 to your computer and use it in GitHub Desktop.
How to change HttpRequest.IsSecureConnection
// 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()
{
}
}
// 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 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