【问题标题】:ASP .NET 5 site loses session after [FromBody] PostASP .NET 5 站点在 [FromBody] 发布后失去会话
【发布时间】:2021-10-15 02:02:27
【问题描述】:

我们有一个带有登录名的 ASP.NET 5 Web 服务器,它使用 HttpContext.Session.SetString 设置会话变量。那是以后用的。这工作得很好。

现在我们需要一个入口点,您可以在其中将所有信息发布到它需要的网络服务器(例如登录信息)以返回网站。到目前为止,这是可行的,但是在我们在 Window 中加载任何其他网站后,会话丢失了。

在客户端,我们使用 CefSharp 浏览器将数据发布到站点(如此处所述 Send POST data to URL with CefSharp C# )。 虽然我必须先打开地址然后发布到它。 在服务器端,我们得到这样的信息。

        public IActionResult Entry(string id)
        {
            _logger.LogInformation("Entry");
            _logger.LogInformation("Session1: " + HttpContext.Session.Id);

            HttpContext.Session.SetString("test", "1");
            return new EmptyResult();
        }

        [HttpPost]
        public IActionResult Entry(string id, [FromBody]SomeClass request)
        {
            _logger.LogInformation("EntryPost");
            _logger.LogInformation("Session1: "+ HttpContext.Session.Id);
            process(request);
//(... set Session, create a Model and return a View)

打开站点进入“Entry”,然后帖子进入“EntryPost”。它们已经有不同的 SessionId,这并不是世界末日,但只要我们在 BrowserView 中单击一个按钮并加载一个新站点,Session 也会丢失。

我花了一些时间将每个 XML 的数据正确地发送到服务器,这部分工作没有问题。浏览器从该服务器保存 Cookie 通常没有问题,因为该网站通过上述登录页面正常工作。

我们通过重定向阅读了很多关于会话丢失的问题,因此我们将它们全部删除,这至少显示了没有会话丢失的初始站点,但在手动单击重新加载站点之后却没有。我们尝试了很多东西,但我们不知道会话为什么会中断。

如果有人有任何想法,请告诉我。

添加“简化”版本的浏览器代码:

public class HTML : Form
{
    public ChromiumWebBrowser browser;
    private static bool _init;

    private void InitBrowser(string url)
    {
        if (!_init) {
            CefSettings settings = new CefSettings() { PersistSessionCookies = true }; // One of the things we tried
            _init = Cef.Initialize(settings); 
        }
        if (browser == null && _init == true)
        {
            browser = new ChromiumWebBrowser(url);
            this.Controls.Add(browser);
        }
    }

    public void setAddress(string address)
    {
        if (address == "") address = "about:blank";
        if (browser != null && browser.IsBrowserInitialized)
        {
            browser.Load(address);
        }
        else
        {
            InitBrowser(address);
        }
    }

    public override bool EntryPost(SomeClass request)
    {
        string gciXML = XMLTools.Serialize(gci);

        // setAddress("https://OurWebserver:44333/"); // Login Page, Website Works without problems
        InitPost("https://OurWebserver:44333/Home/Entry/id", gciXML);

        return true;
    }

    // Start Post functionality

    private Queue<PostParams> _postParam = new Queue<PostParams>();

    private class PostParams
    {
        public string url;
        public string postData;
    }

    /// <summary>
    /// HTML Post. 
    /// Standard .NET Browser uses the same function name
    /// </summary>
    /// <param name="url"></param>
    /// <param name="postDataBytes"></param>
    internal void Navigate(string url, byte[] postDataBytes)
    {
        IFrame frame = browser.GetMainFrame();
        IRequest request = frame.CreateRequest();

        request.Url = url;
        request.Method = "POST";

        request.InitializePostData();
        var element = request.PostData.CreatePostDataElement();
        element.Bytes = postDataBytes;
        request.PostData.AddElement(element);

        NameValueCollection headers = new NameValueCollection();
        headers.Add("Content-Type", "application/xml");
        headers.Add("Connection", "keep-alive");
        request.Headers = headers;


        frame.LoadRequest(request);
        frame.GetTextAsync().ContinueWith(taskHtml =>
        {
            var html = taskHtml.Result;
            Console.WriteLine("HTML:" + html);
        });

        string script = string.Format("document.documentElement.outerHTML;");
        frame.EvaluateScriptAsync(script).ContinueWith(x =>
        {
            var response = x.Result;

            if (response.Success && response.Result != null)
            {
                var fullhtml = response.Result;
                Console.WriteLine("fullhtml:" + fullhtml.ToString());
            }
        }
        );
    }

    private void Browser_FrameLoadEnd_InitPost(object sender, FrameLoadEndEventArgs e)
    {
        // TODO Browser sometimes adds "/" to the url. This basicly runs into endless loop, but it works with the example
        if (browser.Address == _postParam.Peek().url)
        {
            browser.FrameLoadEnd -= Browser_FrameLoadEnd_InitPost;
            if (_postParam != null && _postParam.Count > 0)
            {
                PostParams postObject = _postParam.Dequeue();
                Navigate(postObject.url, Encoding.ASCII.GetBytes(postObject.postData));
                
                // TODO repeat process if the queue isn't empty , works well for one Post Request for now
            }
        }
        else
        {
            this.setAddress(_postParam.Peek().url);
        }
    }

    private void Browser_IsBrowserInitializedChanged_InitPost(object sender, EventArgs e)
    {
        if (browser.IsBrowserInitialized)
        {
            browser.IsBrowserInitializedChanged -= Browser_IsBrowserInitializedChanged_InitPost;

            this.setAddress(_postParam.Peek().url);
            browser.FrameLoadEnd += Browser_FrameLoadEnd_InitPost;
        }
    }

    /// <summary>
    /// puts the url and postData in a Queue and keeps it there until the Post is done
    /// </summary>
    /// <param name="pUrl"></param>
    /// <param name="pPostData"></param>
    internal void InitPost(string pUrl, string pPostData)
    {
        bool empty = _postParam.Count == 0;

        PostParams postObject = new PostParams() { url = pUrl, postData = pPostData };

        _postParam.Enqueue(postObject);

        if (empty)
        {
            // Decide what to do depending on the state of the browser
            if (browser == null) setAddress("");  // starts Init process
            if (!browser.IsBrowserInitialized)
            {
                browser.IsBrowserInitializedChanged += Browser_IsBrowserInitializedChanged_InitPost;
            }
            else
            {
                Browser_IsBrowserInitializedChanged_InitPost(null, null);
            }
        }
    }
    
}

解释:

  1. EntryPost 曾在表单上从外部调用一次。
  2. InitPost 决定首先做什么,按需启动 init 进程。您可以在创建时为浏览器提供一个 url - 这就是我决定将它与 setAddress 结合起来的原因。
  3. PostUrl 已加载,我们等待 FrameLoadEnd 事件。
  4. Frame 加载完成后,将发送 Post 请求。

导航是从上面链接的 stackoverflow 页面复制而来的。我想我添加了 Connection 标头。 Iirc 它会自动发送一堆头信息。

【问题讨论】:

  • They already have different SessionIds, which isn't the end of the world 实际上是。这意味着第二个操作启动了一个新会话,可能是因为它一个新会话,从一个新选项卡或新浏览器实例开始。您此时所做的任何事情都会在新会话上运行。就任何 HTTP 服务器而言,CefSharp 都是浏览器
  • 您有 CefSharp 问题,但没有 CefSharp 代码
  • @PanagiotisKanavos 你是对的。我添加了 CefSharp 代码。我想,由于正常的 LoginPage 工作正常,浏览器没有问题。但是当然还有很多其他代码可能会出现问题。 “这不是世界末日”我的意思实际上是,但我不知道这是问题根源的线索。

标签: c# asp.net .net asp.net-mvc


【解决方案1】:

似乎在导航功能中添加这个解决了它:

request.Flags = UrlRequestFlags.AllowStoredCredentials;

request.Flags = request.Flags|UrlRequestFlags.AllowStoredCredentials;

感谢@PanagiotisKanavos 告诉我问题出在浏览器中。我以为是在 ASP.NET 代码中。

【讨论】:

    猜你喜欢
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 2016-11-07
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多