重定向除Ajax/Javascript以外的方式发送身份验证请求,以避免CORS错误



问题描述:

假设我有一个web应用程序(Java+Saml2.0(,它有一个登录按钮来调用ADFS(身份提供者(进行身份验证。

它使用Javascript(Ajax也有同样的问题(来调用ADFS2016的一个端点。由于请求是从Javascript/Ajax发送的,浏览器会抛出CORS错误。(ADFS2016服务器端不支持修改CORS头/响应/来源(

我从某人那里听说,避免CORS错误的一种方法是使用重定向,而不是使用Ajax/Javascript直接调用一个URL/端点。

有人能为这种情况提供一些见解吗?如何在不引起CORS的情况下修改我的代码以进行这样的重定向?

附言:我不想降低浏览器安全级别以绕过CORS,我也不想升级到ADFS2019,尽管它支持自定义CORS来源。

我不确定你是否试图通过使用这样的javascript来实现一些特殊情况。但通常在使用SAML进行身份验证时,您会从后端发出HTTP重定向,作为对用户单击登录按钮的响应。

为了理解这一切,在本文中首先了解SAML身份验证流程是很重要的。

  1. 用户通过导航到受保护的页面或在本例中单击按钮来触发身份验证
  2. 应用程序或SAML中的服务提供商(SP(构建SAML身份验证请求,并通过将其添加为URL参数并向用户发送后端HTTP重定向来将其发送到IdP。身份验证请求也可以使用此处解释的HTTPPOST发送
  3. IdP以其认为合适的方式对用户进行身份验证
  4. IdP使用HTTPPOST以及SAML响应和SAML断言将用户发送回SP。这包含身份验证的结果以及关于用户的任何额外信息
  5. SP,您的应用程序,解释SAML响应,并允许用户进入受保护的应用程序。此重定向在URL中包含一个编码的SAML身份验证请求,ADFS解析该请求以了解身份验证请求来自何处以及如何对用户进行身份验证

有几个库和框架用于管理SAML传输,包括使用重定向或其他方法发送消息。如果您使用的是Java,Spring将SAML管理作为其安全框架的一部分。另一个库是PAC4J,它提供SAML模块

虽然这两种方法都适用于构建SP以与现有IdP集成的最常见用例,但如果您需要进行更多自定义用例或在自己的OpenSAML上构建IdP,则可以选择。OpenSAML是一个用于处理SAML的较低级别库。在我博客上的这篇文章中,我展示了如何使用OpenSAML的重定向来构建和发送SAML身份验证请求。

下面是一个使用OpenSAML的简化示例。有关完整示例,请参阅此处和此处的示例代码

身份验证请求是使用OpenSAML 构建的

AuthnRequest authnRequest = OpenSAMLUtils.buildSAMLObject(AuthnRequest.class);
authnRequest.setIssueInstant(Instant.now());
authnRequest.setDestination(IPD_SSO_DESTINATION);
authnRequest.setProtocolBinding(SAMLConstants.SAML2_ARTIFACT_BINDING_URI);
authnRequest.setAssertionConsumerServiceURL(SP_ASSERTION_CONSUMER_SERVICE_URL);
authnRequest.setID(RANDOM_ID);
authnRequest.setIssuer(ISSUER);
authnRequest.setNameIDPolicy(NAME_ID_POLICY);

将消息添加到消息上下文并设置目的地

MessageContext context = new MessageContext();
context.setMessage(authnRequest);
SAMLPeerEntityContext peerEntityContext =     context.getSubcontext(SAMLPeerEntityContext.class, true);
SAMLEndpointContext endpointContext =     peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
endpointContext.setEndpoint(MESSAGE_RECEIVER_ENDPOINT);

使用HTTP重定向发送消息

HTTPRedirectDeflateEncoder encoder = new HTTPRedirectDeflateEncoder();
encoder.setMessageContext(context);
encoder.setHttpServletResponse(httpServletResponse);
encoder.initialize();
encoder.encode();

对于那些想深入研究的人,我写了一本关于使用OpenSAML的书,OpenSAML指南,以及一本关于SAML作为框架的书,SAML2.0:设计安全身份联合

我的博客上也有很多资源

相关内容

  • 没有找到相关文章

最新更新