Possible Bug With ASP.NET MVC 3 Routing?

微笑、不失礼 提交于 2019-11-29 05:54:04

This appears to be related to Cookieless Sessions in the ASP.NET pipeline. It strips that URL pattern inside CookielessHelper.cs (System.Web.Security) while processing the request:

    // This function is called for all requests -- it must be performant.
    //    In the common case (i.e. value not present in the URI, it must not
    //    look at the headers collection
    internal void RemoveCookielessValuesFromPath() 
    {
        // See if the path contains "/(XXXXX)/" 
        string   path      = _Context.Request.ClientFilePath.VirtualPathString; 
        // Optimize for the common case where there is no cookie
        if (path.IndexOf('(') == -1) { 
            return;
        }
        int      endPos    = path.LastIndexOf(")/", StringComparison.Ordinal);
        int      startPos  = (endPos > 2 ?  path.LastIndexOf("/(", endPos - 1, endPos, StringComparison.Ordinal) : -1); 

        if (startPos < 0) // pattern not found: common case, exit immediately 
            return; 

        if (_Headers == null) // Header should always be processed first 
            GetCookielessValuesFromHeader();

        // if the path contains a cookie, remove it
        if (IsValidHeader(path, startPos + 2, endPos)) 
        {
            // only set _Headers if not already set 
            if (_Headers == null) { 
                _Headers = path.Substring(startPos + 2, endPos - startPos - 2);
            } 
            // Rewrite the path
            path = path.Substring(0, startPos) + path.Substring(endPos+1);

            // remove cookie from ClientFilePath 
            _Context.Request.ClientFilePath = VirtualPath.CreateAbsolute(path);
            // get and append query string to path if it exists 
            string rawUrl = _Context.Request.RawUrl; 
            int qsIndex = rawUrl.IndexOf('?');
            if (qsIndex > -1) { 
                path = path + rawUrl.Substring(qsIndex);
            }
            // remove cookie from RawUrl
            _Context.Request.RawUrl = path; 

            if (!String.IsNullOrEmpty(_Headers)) { 
                _Context.Request.ValidateCookielessHeaderIfRequiredByConfig(_Headers); // ensure that the path doesn't contain invalid chars 
                _Context.Response.SetAppPathModifier("(" + _Headers + ")");

                // For Cassini and scenarios where aspnet_filter.dll is not used,
                // HttpRequest.FilePath also needs to have the cookie removed.
                string filePath = _Context.Request.FilePath;
                string newFilePath = _Context.Response.RemoveAppPathModifier(filePath); 
                if (!Object.ReferenceEquals(filePath, newFilePath)) {
                    _Context.RewritePath(VirtualPath.CreateAbsolute(newFilePath), 
                                         _Context.Request.PathInfoObject, 
                                         null /*newQueryString*/,
                                         false /*setClientFilePath*/); 
                }
            }
        }
    } 

Your pattern matches this:

    ///////////////////////////////////////////////////////////////////////
    /////////////////////////////////////////////////////////////////////// 
    // Make sure sub-string if of the pattern: A(XXXX)N(XXXXX)P(XXXXX) and so on. 
    static private bool IsValidHeader(string path, int startPos, int endPos)
    { 
        if (endPos - startPos < 3) // Minimum len is "X()"
            return false;

        while (startPos <= endPos - 3) { // Each iteration deals with one "A(XXXX)" pattern 

            if (path[startPos] < 'A' || path[startPos] > 'Z') // Make sure pattern starts with a capital letter 
                return false; 

            if (path[startPos + 1] != '(') // Make sure next char is '(' 
                return false;

            startPos += 2;
            bool found = false; 
            for (; startPos < endPos; startPos++) { // Find the ending ')'

                if (path[startPos] == ')') { // found it! 
                    startPos++; // Set position for the next pattern
                    found = true; 
                    break; // Break out of this for-loop.
                }

                if (path[startPos] == '/') { // Can't contain path separaters 
                    return false;
                } 
            } 
            if (!found)  {
                return false; // Ending ')' not found! 
            }
        }

        if (startPos < endPos) // All chars consumed? 
            return false;

        return true; 
    }

You might want to try adding an IgnoreRoute to your route mapping - but I admit I'm not sure what format to provide to match all your possible cookieless paths.

I agree with @pjumble analysis, but not to his solution.
Disable cookieless authentication for either form authentication or anonymous authentication.

This will prevent users with cookies disabled to authenticate. But who cares anyway, everyone nowdays have cookies activated as no modern website will work without.

Add in web.config:

<anonymousIdentification enabled="false" />
<authentication mode="None" />

or

<anonymousIdentification enabled="true" cookieless="UseCookies" ... />
<authentication mode="Forms">
  <forms name="Auth" cookieless="UseCookies" ... />
</authentication>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!