Asp.net OWIN WS-Federation在SSL代理后重定向
我正在尝试编写我的第一个启用ADFS的ASP.Net web应用程序。该应用程序在我的本地计算机上运行正常,但当我将其发布到IIS(位于SSL代理之后)时,我的应用程序最终会将经过身份验证的用户重定向到应用程序的http地址,而不是https地址。我如何解决这个问题 为了澄清流程的故障,以下是发生的情况:Asp.net OWIN WS-Federation在SSL代理后重定向,asp.net,owin,adfs,ws-federation,Asp.net,Owin,Adfs,Ws Federation,我正在尝试编写我的第一个启用ADFS的ASP.Net web应用程序。该应用程序在我的本地计算机上运行正常,但当我将其发布到IIS(位于SSL代理之后)时,我的应用程序最终会将经过身份验证的用户重定向到应用程序的http地址,而不是https地址。我如何解决这个问题 为了澄清流程的故障,以下是发生的情况: 未经验证的用户浏览应用程序主页并重定向至Idp[良好] 用户在Idp进行身份验证,令牌通过https POST发送回我的应用程序[良好] 我的应用程序分配一个cookie,并将用户重定向到ht
public partial class Startup
{
private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata
});
}
}
我已经读过几篇关于ssl代理背后的identity/auth的类似问题的帖子,并且建议对我没有影响。我猜是因为重定向是由ws-fed中间件而不是cookie提供者执行的。明白了
在阅读了OWIN/Katana源代码之后,我在ws-fed代码中找到了允许您操作url的钩子。在我的例子中,如果检测到SSL代理的存在(通过检查请求头),我将重写URL以实现https而不是http
public partial class Startup
{
private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata,
Notifications = new WsFederationAuthenticationNotifications
{
SecurityTokenValidated = (notification) =>
{
notification.AuthenticationTicket.Properties.RedirectUri = ApplySchemeFromSSLProxy(notification.Request, notification.AuthenticationTicket.Properties.RedirectUri);
return Task.FromResult(0);
},
RedirectToIdentityProvider = (notification) =>
{
if (notification.ProtocolMessage.IsSignOutMessage)
{
notification.ProtocolMessage.Wreply = ApplySchemeFromSSLProxy(notification.Request, notification.ProtocolMessage.Wreply);
}
return Task.FromResult(0);
}
}
});
}
/// <summary>
/// If there is evidence of an SSL proxy in use, convert the uri to https.
/// </summary>
/// <param name="request"></param>
/// <param name="uri"></param>
/// <returns>Converted URI</returns>
private string ApplySchemeFromSSLProxy(IOwinRequest request, string uri)
{
if (
Uri.IsWellFormedUriString(uri, UriKind.Absolute) &&
request.Headers.Any(h =>
h.Key.ToLower().StartsWith("x-forwarded-proto") &&
h.Value.Contains(Uri.UriSchemeHttps)
)
)
{
var uriBuilder = new UriBuilder(uri)
{
Scheme = Uri.UriSchemeHttps,
Port = -1 // default port for scheme
};
return uriBuilder.ToString();
}
else
{
return uri;
}
}
}
公共部分类启动
{
私有静态字符串realm=ConfigurationManager.AppSettings[“ida:Wtrealm”];
私有静态字符串adfsMetadata=ConfigurationManager.AppSettings[“ida:adfsMetadata”];
public void ConfigureAuth(IAppBuilder应用程序)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(新的CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
新WsFederationAuthenticationOptions
{
Wtrealm=realm,
MetadataAddress=adfsMetadata,
通知=新WsFederationAuthenticationNotifications
{
SecurityTokenValidated=(通知)=>
{
notification.AuthenticationTicket.Properties.RedirectUri=ApplySchemeFromSSLProxy(notification.Request,notification.AuthenticationTicket.Properties.RedirectUri);
返回Task.FromResult(0);
},
RedirectToIdentityProvider=(通知)=>
{
if(notification.ProtocolMessage.IsSignOutMessage)
{
notification.ProtocolMessage.Wreply=ApplySchemeFromSSLProxy(notification.Request,notification.ProtocolMessage.Wreply);
}
返回Task.FromResult(0);
}
}
});
}
///
///如果有证据表明正在使用SSL代理,请将uri转换为https。
///
///
///
///转换URI
私有字符串ApplySchemeFromSSLProxy(IOwinRequest请求,字符串uri)
{
如果(
IsWellFormedUriString(Uri,UriKind.Absolute)和
request.Headers.Any(h=>
h、 Key.ToLower().StartsWith(“x-forwarded-proto”)和
h、 Value.Contains(Uri.UriSchemeHttps)
)
)
{
var uriBuilder=新的uriBuilder(uri)
{
Scheme=Uri.UriSchemeHttps,
端口=-1//方案的默认端口
};
返回uriBuilder.ToString();
}
其他的
{
返回uri;
}
}
}
明白了
在阅读了OWIN/Katana源代码之后,我在ws-fed代码中找到了允许您操作url的钩子。在我的例子中,如果检测到SSL代理的存在(通过检查请求头),我将重写URL以实现https而不是http
public partial class Startup
{
private static string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
private static string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata,
Notifications = new WsFederationAuthenticationNotifications
{
SecurityTokenValidated = (notification) =>
{
notification.AuthenticationTicket.Properties.RedirectUri = ApplySchemeFromSSLProxy(notification.Request, notification.AuthenticationTicket.Properties.RedirectUri);
return Task.FromResult(0);
},
RedirectToIdentityProvider = (notification) =>
{
if (notification.ProtocolMessage.IsSignOutMessage)
{
notification.ProtocolMessage.Wreply = ApplySchemeFromSSLProxy(notification.Request, notification.ProtocolMessage.Wreply);
}
return Task.FromResult(0);
}
}
});
}
/// <summary>
/// If there is evidence of an SSL proxy in use, convert the uri to https.
/// </summary>
/// <param name="request"></param>
/// <param name="uri"></param>
/// <returns>Converted URI</returns>
private string ApplySchemeFromSSLProxy(IOwinRequest request, string uri)
{
if (
Uri.IsWellFormedUriString(uri, UriKind.Absolute) &&
request.Headers.Any(h =>
h.Key.ToLower().StartsWith("x-forwarded-proto") &&
h.Value.Contains(Uri.UriSchemeHttps)
)
)
{
var uriBuilder = new UriBuilder(uri)
{
Scheme = Uri.UriSchemeHttps,
Port = -1 // default port for scheme
};
return uriBuilder.ToString();
}
else
{
return uri;
}
}
}
公共部分类启动
{
私有静态字符串realm=ConfigurationManager.AppSettings[“ida:Wtrealm”];
私有静态字符串adfsMetadata=ConfigurationManager.AppSettings[“ida:adfsMetadata”];
public void ConfigureAuth(IAppBuilder应用程序)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(新的CookieAuthenticationOptions());
app.UseWsFederationAuthentication(
新WsFederationAuthenticationOptions
{
Wtrealm=realm,
MetadataAddress=adfsMetadata,
通知=新WsFederationAuthenticationNotifications
{
SecurityTokenValidated=(通知)=>
{
notification.AuthenticationTicket.Properties.RedirectUri=ApplySchemeFromSSLProxy(notification.Request,notification.AuthenticationTicket.Properties.RedirectUri);
返回Task.FromResult(0);
},
RedirectToIdentityProvider=(通知)=>
{
if(notification.ProtocolMessage.IsSignOutMessage)
{
notification.ProtocolMessage.Wreply=ApplySchemeFromSSLProxy(notification.Request,notification.ProtocolMessage.Wreply);
}
返回Task.FromResult(0);
}
}
});
}
///
///如果有证据表明正在使用SSL代理,请将uri转换为https。
///
///
///
///转换URI
私有字符串ApplySchemeFromSSLProxy(IOwinRequest请求,字符串uri)
{
如果(
IsWellFormedUriString(Uri,UriKind.Absolute)和
request.Headers.Any(h=>
h、 Key.ToLower().StartsWith(“x-forwarded-proto”)&&