使用IDP登录时SessionId发生变化

Ros*_*son 1 .net c# asp.net session saml

我正在使用一些遗留代码来修复有关登录重定向的错误。简而言之,当用户加载包含登录页面链接的页面,单击进入 SSO 登录页面的登录链接,然后登录该 SSO 页面时,他们不会被重定向到主页,而是会被重定向到主页。他们最后的页面。经过研究,以前的开发人员解决这个问题的方法是将“深层链接”保存为会话数据中的变量(其会话 ID 保存在客户端的 cookie 中和服务器的内存中)。理论上,用户登录时应该从会话数据中检索到深层链接,然后他们应该被重定向。但是,这就是发现问题的地方:第二次调用(当用户登录时)中的会话 ID 具有不同的会话 ID,因此在此会话 ID 的会话数据中找不到匹配的深层链接。

我可以证明会话 ID 已正确存储在 Chrome 和 SAML Tracer 的 cookie 中,并且 SAML 调用连续发生,中间没有发生其他调用。我没有看到会话 ID 在参数或 http 标头中传递(尽管用户登录后应访问的正确链接作为第一个 SSO 请求中的引用者传递)。

我还应该注意,我们正在使用 ComponentSpace 的 SAML 库。此外,当首次调用转到 SSO 页面时,重定向时会出现 302 Found 错误。我认为这是故意的,但我不能百分百确定。SSO 是 ADFS。

公司里已经没有人参与过这段代码的工作了,而且这个代码库和这些库对我来说都是新的。我还不确定这是否是此应用程序或我们连接到的自定义 SSO 网站的问题,我需要以某种方式证明这一点。根据 TFS,我们与此问题相关的代码在两年或更长时间内都没有发生更改。

我的问题:

  1. 为什么第一次调用到第二次调用时会话 ID 会发生变化?
  2. 是否需要进行额外的设置来保存通话过程中的会话数据?一般来说,我不希望不同的调用有不同的会话 ID 吗?
  3. 单个用户的会话如何持续?
  4. 如何证明问题是由我们的应用程序还是我们连接的应用程序引起的?

以下是用户单击登录页面链接时第一次 SSO 调用的代码:

public ActionResult SingleSignOn()
    {
        try
        {
            if (!string.IsNullOrEmpty(ssoUrl))
            {
                _accountRespository.SetDeepLink();
                var sessionId = System.Web.HttpContext.Current.Session.SessionID;
                // Redirect to SSO Site. Reentry point is Controllers/SAMLController.cs::AssertionConsumerService() .
                return Redirect(ssoUrl);
Run Code Online (Sandbox Code Playgroud)

以下是单击带有凭据的登录按钮后第二次调用的代码:

[HttpPost]
    public ActionResult AssertionConsumerService()
    {
        try
        {
            bool isInResponseTo = false;
            string partnerIdP = null;
            string userName = null;
            IDictionary<string, string> claims = null;
            string relayState = null;
            var sessionId = System.Web.HttpContext.Current.Session.SessionID;
            SAMLServiceProvider.ReceiveSSO(Request, out isInResponseTo, out partnerIdP, out userName, out claims, out relayState);

            // Resolve the page redirect.
            if (string.IsNullOrWhiteSpace(relayState))
            {
                // If relayState is not provided by ADFS, get it from the session variable.
                relayState = _accountRepository.GetDeepLink();
                _accountRepository.ClearDeepLink();

                if (string.IsNullOrWhiteSpace(relayState))
                {
                    // If no target URL is provided, default back to the home page.
                    relayState = "~/";
                }
            }
Run Code Online (Sandbox Code Playgroud)

以下是 SetDeepLink 和 GetDeepLink 调用的代码:

public string GetDeepLink()
    {
        var httpContext = HttpContext.Current;
        if (httpContext == null)
        {
            throw new NullReferenceException("Can't access deep link session variable. HttpContext.Current is null.");
        }
        return (string)httpContext.Session[Constants.SessionDeepLinkUrl];
    }

public void SetDeepLink()
    {
        var httpContext = HttpContext.Current;
        if (httpContext == null)
        {
            throw new NullReferenceException("Can't access deep link session variable. HttpContext.Current is null.");
        }
        var queryString = httpContext.Request.Url.Query;
        if (!string.IsNullOrWhiteSpace(queryString))
        {
            var deepLink = HttpUtility.ParseQueryString(queryString)?.Get(Constants.DeepLinkQueryString);
            httpContext.Session[Constants.SessionDeepLinkUrl] = deepLink;
        }
    }
Run Code Online (Sandbox Code Playgroud)

先感谢您。

小智 5

Chrome 和其他浏览器最近对 cookie 的 SameSite 属性的处理方式进行了更改。当参与 SAML SSO 时,这可能会影响所有 cookie,包括 ASP.NET 会话 cookie。我怀疑这就是您所看到的问题。

您需要为 ASP.NET 会话 cookie 指定 SameSite=None 和 Secure。这可以通过更新应用程序 web.config 来完成:

<sessionState cookieSameSite="None" />
<httpCookies requireSSL="true"/>
Run Code Online (Sandbox Code Playgroud)

更详细的信息请参考:

https://www.componentspace.com/Forums/10816/Application-Cookie-SameSite-None