我们在内部应用程序中使用ADFS --用户在任何时候都会透明地登录到我们的应用程序中。但是,如果用户打开一个页面超过一个小时,然后尝试在该页面上执行一些操作(除了导航到另一个页面),他们会得到一个错误:
此页面正在访问不在其控制范围内的信息。这构成了安全风险。你想继续吗?
该页面似乎试图将该请求重定向到ADFS服务器,浏览器正在阻止该请求。
因此,我的问题是:如何捕捉这种情况并让用户到ADFS服务器进行重新身份验证?
我还没有在谷歌上找到任何关于这个的运气。
发布于 2016-09-07 15:15:48
您可以在global.asax中手动检查和重新发出安全令牌,并使用它创建滑动会话。使用滑动会话,您可以选择推迟重新身份验证,直到它变得“安全”这样做(当数据将不再丢失由于ADFS重定向)。
在SessionSecurityTokenReceived事件中,您可以计算令牌和请求。如果令牌已过期,并且请求将经历重定向造成的数据丢失,则可以重新发出新的“临时”令牌。新令牌的使用寿命应该非常短,只要足够长,就可以安全地完成当前的请求。然后,令牌将过期,并在下一个请求中再次进行计算。
protected void SessionAuthenticationModule_SessionSecurityTokenReceived(object sender, SessionSecurityTokenReceivedEventArgs e)
{
var now = DateTime.UtcNow;
SessionSecurityToken token = e.SessionToken;
var httpContext = new HttpContextWrapper(this.Context);
if (now > token.ValidTo
&& (httpContext.Request.IsAjaxRequest() || httpContext.Request.HttpMethod == "POST"))
{
var sessionAuthModule = (SessionAuthenticationModule)sender;
e.SessionToken = sessionAuthModule.CreateSessionSecurityToken(token.ClaimsPrincipal,
token.Context,
now,
now.AddMinutes(2),
token.IsPersistent);
e.ReissueCookie = true;
}
}ADFS会话将继续将重新身份验证推迟到下一个GET请求。然后重定向将最终发生,用户将得到一个正常寿命的适当令牌。
发布于 2013-10-08 21:40:56
更新:下面的解决方案取决于iframes。ADFS3.0的X帧选项默认为拒绝,没有更改设置的选项.因此,此解决方案只适用于ADFS2.1和更早的版本。
在您的global.asax.cs中,您将希望捕获任何中间AJAX 302,并将它们转换为401未经授权的。这将阻止调用(并弹出该消息),并将我们发送到$(document).ajaxError()。
protected void Application_EndRequest()
{
var context = new HttpContextWrapper(this.Context);
if (context.Response.StatusCode == 302 && context.Request.IsAjaxRequest())
{
context.Response.Clear();
context.Response.StatusCode = 401;
}
}然后,在那里,拦截任何401秒,然后再进行其他错误处理。我选择向用户显示一条消息。您可以在这里完成下一步,但是为了可读性,我将ajaxSettings对象发送到另一个函数。返回true,这样它就不会继续您的其他错误处理。
如果您想要检查这是ADFS,event.target.referrer将具有尝试重定向的URL。
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
if (xhr.status == 401) {
alert("Your session has timed out. Click OK to reauthorize and extend your session.");
TriggerReauthenticationRefresher(ajaxSettings);
return true;
}
…the rest of the error handling code…
});针对这种情况,我的页面中有一个空的div,id为‘刷新框’,但是您可以在DOM中的任何元素上这样做。将一个iframe放到您域中的某个虚拟页面上。在我的例子中,ADFSRefresher.cshtml的内容只是
<div><input type="hidden" value="@DateTime.Now.ToString()" /></div>我不是使用全局变量,而是使用.data()存储.data()。我们还需要跟踪iframe重新加载多少次,所以我们也在存储负载计数。将iframe插入DOM中,它将启动。
function TriggerReauthenticationRefresher(ajaxSettings) {
var refreshframe = '<iframe src="@Url.Action("ADFSRefresher", "Debug")" style="display:none" onload="TrackFrameReloads()" />';
$('#refresherBox').data('loadcount', 0);
$('#refresherBox').data('originalRequestSettings', ajaxSettings);
$('#refresherBox').html(refreshframe);
}TrackFrameReloads将在iframe每次完成加载时开火。因为我们知道有一个即将到来的ADFS重定向,它将发射两次。第一次是重定向,第二次是它的src url。因此,当它第一次启动时,我们只需增加负载计数。
第二次发射时,我们知道我们已经被成功地重新认证了。检索ajaxSettings,清除存储的数据,然后可以重用原始设置来发送AJAX调用!它将通过,不重定向,并运行其原来的成功和完整的功能。
function TrackFrameReloads() {
var i = $('#refresherBox').data('loadcount');
if (i == 1) {
alert('Your session has been extended.');
var ajaxSettings = $('#refresherBox').data('originalRequestSettings');
$('#refresherBox').removeData();
$.ajax(ajaxSettings);
} else {
$('#refresherBox').data("loadcount", 1);
}
}请注意,如果您定义了它们,错误和完整的函数将已经触发。
如果愿意,可以跳过给用户的两条警告消息。取决于您的ADFS设置,这应该只需1秒,并且用户不需要被告知这一切都发生了!
https://stackoverflow.com/questions/15668751
复制相似问题