我有一个网站正在尝试调用另一个网站上的MVC控制器操作。这两个网站都设置为AD FS 2.0中的依赖方信任。在两个网站之间的浏览器窗口中打开页面时,一切都经过身份验证并正常工作。但是,当尝试使用 AJAX 方法从JavaScript调用一个控制器动作时,总是失败。下面是我尝试做的事情的代码片段。。
$.ajax({
url: "relyingPartySite/Controller/Action",
data: { foobar },
dataType: "json",
type: "POST",
async: false,
cache: false,
success: function (data) {
// do something here
},
error: function (data, status) {
alert(status);
}
});
问题是AD FS使用JavaScript向依赖方发布隐藏的html表单。使用Fiddler跟踪时,我可以看到它到达AD FS站点并返回此html表单,该表单应发布并重定向到经过身份验证的控制器操作。问题是这个表单作为 AJAX 请求的结果返回,并且显然会失败,因为ajax请求期望来自控制器的json这似乎是一个常见的场景,那么从 AJAX 与AD FS通信并处理此重定向的正确方法是什么呢?
7条答案
按热度按时间jqjz2hbq1#
您有两个选择。更多信息here。
第一种是在入口应用程序(基于HTML的应用程序)和API解决方案之间共享会话cookie。您可以配置这两个应用程序使用相同的WIF cookie。这仅在两个应用程序位于同一根域时有效。请参阅上面的帖子或此stackoverflow question。
另一个选项是禁用 AJAX 请求的passiveRedirect(如Gutek's answer)。这将返回一个http状态代码401,您可以在Javascript中处理。当您检测到401时,你加载了一个虚拟页面(或“验证”对话框,如果需要再次提供凭据,则该对话框可兼作登录对话框)。当iFrame完成后,您可以再次尝试调用。这一次,会话cookie将出现在调用中,并且调用应该成功。
kiayqfof2#
如果您不想接收带有链接的HTML,可以在
WSFederationAuthenticationModule
上处理AuthorizationFailed
,并仅在Ajax调用时将RedirectToIdentityProvider
设置为false
。例如:
Authorize
属性将返回状态代码401
,如果您希望有不同的内容,则可以实现自己的Authorize
属性并在Ajax请求上编写特殊代码。snz8szmq3#
在我目前工作的项目中,我们遇到了同样的问题,客户端上的SAML令牌过期,导致 AJAX 调用出现问题。在我们的特定情况下,我们需要在遇到第一个401后将所有请求排队,并在成功认证后重新发送所有请求。认证使用Adam米尔斯建议的iframe解决方案,而且在需要输入用户凭证的情况下更进一步,这是通过显示通知用户登录外部视图的对话框来完成的(由于ADFS不允许在iframe中显示登录页面,至少不允许在默认配置中显示)在此期间,等待请求正在等待完成,但用户需要从外部页面登录。如果用户选择取消,也可以拒绝等待请求,在这种情况下,将为每个请求调用jquery错误。
下面是示例代码要点的链接:
https://gist.github.com/kavhad/bb0d8e4a446496a6c05a
注意我的代码是基于jquery处理所有 AJAX 请求的用法。如果你的ajax请求是由vanilla javascript,其他库或框架处理的,那么你可能会在这个例子中找到一些灵感。jquery用户界面的用法仅仅是因为对话框,代表了一小部分代码,可以很容易地被替换掉。
更新抱歉我更改了我的github帐户名,这就是为什么链接不起作用。现在应该可以了。
chhkpiq44#
首先你说你正在尝试对另一个网站进行 AJAX 调用,你的调用是否符合网页浏览器的same origin policy?如果符合,那么你希望从服务器得到html作为响应,将ajax调用的
datatype
更改为dataType: "html"
,然后将表单插入到DOM中。4nkexdtk5#
也许this serie的前两篇文章会对你有所帮助。他们考虑了ADFS和 AJAX 请求
我想我会尝试做的是看看为什么认证cookie不通过 AJAX 传输,并找到一种方法来发送它们与我的请求.或者 Package ajax调用在一个函数中,通过检索html表单,将其隐藏地附加到DOM,提交它(它将有希望设置好cookie),然后发送您最初想要发送的适当请求来进行预认证
km0tfn4u6#
只能使用此类型的数据类型
如果你能看到你的fiddler只返回html,那么就把你的数据类型改为html,或者如果那只是一个脚本代码,那么你就可以使用script。
6ss1mwsb7#
你应该创建一个像json.php这样的任意名称的文件,然后把连接到relayparty网站,这应该工作
$.ajax({ url: "json.php", data: { foobar }, dataType: "json", type: "POST", async: false, cache: false, success: function (data) { // do something here }, error: function (data, status) { alert(status); } });