You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Azure AD作为IDP的SAML认证RestAssured实现问题

解决RestAssured处理SAML+Ping Federator+Azure AD SSO登录的问题

问题背景

现有基于SAML认证、Azure AD作为IDP的应用,SSO登录流程如下:

  • 请求SAML重定向URL /Saml/SAMLLoginRedirect
  • 自动重定向至Ping Federator,重定向URL包含SAMLRequest Token和RelayState,最终响应返回带新令牌的提交表单
  • 使用该响应参数请求IDP地址 login.microsoftonline.com//saml2 未达预期

已通过JMeter解决:开启跟随重定向,提取首个请求头中的URL,携带Cookie重新请求Ping Federator后完成IDP流程,但RestAssured中遇到以下问题:

  • 启用重定向无法捕获中间响应头信息,后续处理失败
  • 禁用重定向虽能获取重定向URL,但携带Cookie请求该URL时返回500错误,无法获取预期响应与Cookie

所有到IDP前的请求均为GET请求。

解决方案

1. 自定义重定向策略捕获中间会话信息

RestAssured默认的重定向处理会自动跳转,无法捕获中间步骤的响应头和Cookie。通过自定义RedirectStrategy,可以在跟随重定向的同时记录关键信息,保留完整会话上下文。

自定义重定向策略代码:

import io.restassured.RestAssured;
import io.restassured.config.RedirectConfig;
import io.restassured.config.RestAssuredConfig;
import org.apache.http.Header;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolException;
import org.apache.http.client.RedirectStrategy;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.protocol.HttpContext;
import java.util.HashMap;
import java.util.Map;

public class CustomRedirectStrategy extends DefaultRedirectStrategy {
    private String pingFederatorRedirectUrl;
    private final Map<String, String> sessionCookies = new HashMap<>();

    @Override
    public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
        boolean isRedirect = super.isRedirected(request, response, context);
        if (isRedirect) {
            // 提取重定向URL
            pingFederatorRedirectUrl = response.getFirstHeader("Location").getValue();
            // 提取所有Set-Cookie头,整理为键值对
            Header[] cookieHeaders = response.getHeaders("Set-Cookie");
            for (Header header : cookieHeaders) {
                String cookiePair = header.getValue().split(";")[0];
                String[] keyValue = cookiePair.split("=", 2);
                if (keyValue.length == 2) {
                    sessionCookies.put(keyValue[0].trim(), keyValue[1].trim());
                }
            }
        }
        return isRedirect;
    }

    public String getPingFederatorRedirectUrl() {
        return pingFederatorRedirectUrl;
    }

    public Map<String, String> getSessionCookies() {
        return sessionCookies;
    }
}

测试代码中使用该策略:

// 初始化自定义重定向策略
CustomRedirectStrategy customRedirectStrategy = new CustomRedirectStrategy();

// 配置RestAssured启用自定义重定向逻辑
RestAssured.config = RestAssuredConfig.config()
        .redirect(RedirectConfig.redirectConfig()
                .followRedirects(true)
                .redirectStrategy(customRedirectStrategy));

// 第一步:请求SAMLLoginRedirect,触发重定向并捕获信息
RestAssured.given()
        .when()
        .get("/Saml/SAMLLoginRedirect")
        .then()
        .statusCode(200);

// 获取捕获的Ping Federator地址和会话Cookie
String pingUrl = customRedirectStrategy.getPingFederatorRedirectUrl();
Map<String, String> cookies = customRedirectStrategy.getSessionCookies();

// 第二步:请求Ping Federator,携带完整会话Cookie
String pingResponse = RestAssured.given()
        .cookies(cookies)
        .when()
        .get(pingUrl)
        .then()
        .statusCode(200)
        .extract()
        .asString();

// 第三步:解析Ping响应中的表单参数,请求Azure AD IDP
// 使用Jsoup解析HTML表单(需引入Jsoup依赖)
org.jsoup.nodes.Document doc = org.jsoup.Jsoup.parse(pingResponse);
org.jsoup.nodes.Element form = doc.selectFirst("form");
String samlRequest = form.selectFirst("input[name='SAMLRequest']").val();
String relayState = form.selectFirst("input[name='RelayState']").val();
String idpUrl = form.attr("action");

// 提交表单到Azure AD IDP(注意表单method可能为POST)
RestAssured.given()
        .formParam("SAMLRequest", samlRequest)
        .formParam("RelayState", relayState)
        .when()
        .post(idpUrl)
        .then()
        .statusCode(200);

2. 确保携带完整会话Cookie(禁用重定向场景)

如果选择禁用自动重定向,需确保请求Ping Federator时携带第一步请求返回的所有Cookie,而非仅重定向响应中的Cookie,避免因会话不完整导致500错误。

示例代码:

// 第一步:禁用重定向,请求SAMLLoginRedirect
io.restassured.response.Response firstResponse = RestAssured.given()
        .redirects().follow(false)
        .when()
        .get("/Saml/SAMLLoginRedirect");

// 获取所有会话Cookie和重定向URL
Map<String, String> allCookies = firstResponse.getCookies();
String pingUrl = firstResponse.getHeader("Location");

// 第二步:携带所有Cookie请求Ping Federator
io.restassured.response.Response pingResponse = RestAssured.given()
        .cookies(allCookies)
        // 可选:添加Referer、User-Agent等请求头模拟浏览器行为
        .header("Referer", "你的应用域名/Saml/SAMLLoginRedirect")
        .header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
        .when()
        .get(pingUrl);

// 后续解析表单并请求IDP的步骤同前...

3. 验证请求头完整性

部分场景下,Ping Federator会验证请求的Referer、User-Agent等头信息,确保请求来自合法来源。如果遇到500错误,可添加这些头信息模拟浏览器请求,提升兼容性。

内容的提问来源于stack exchange,提问作者Sasitharan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:45:42