首页 > 解决方案 > ASP.NET MVC 应用程序应用程序/json 响应内容神秘地被文本/html 内容覆盖

问题描述

我已经在 ASP.NET MVC 应用程序中构建了 oauth2 服务器的功能。

它一切正常,并指定了所有非错误产生的正面案例。但是我遇到了一个问题,似乎 MVC 想要在混合中很晚才指定 application/json 的地方注入 text/html。

这很奇怪,因为如果我使用诸如soap UI之类的工具进行测试以发布到我的端点,并且soap UI与我的服务器运行在同一台机器上运行,错误结果会完美地返回并按照指定的方式返回。但是,如果我在另一台机器上(甚至在我的网络上)使用soap UI 进行测试,那么我尝试编写的JSON 将被一些注入的文本/html 覆盖。

首先是我为这个问题简化的代码片段。返回 JsonResult 的控制器操作如下所示:

    public JsonResult RefreshOauth2Token(string grant_type, string client_id, string client_secret, string refresh_token)
    {
        try
        {
            var resultFromMyDB = DoMyBusinessToRefreshToken(string grant_type, string client_id, string client_secret, string refresh_token);

            // This positive case works perfectly.
            return Json(new
            {
                access_token = resultFromMyDB.AccessToken,
                token_type = resultFromMyDB.TokenType,
                expires_in = resultFromMyDB.ExpiresInSeconds,
                refresh_token = resultFromMyDB.RefreshToken
            });
        }
        catch (Exception e)
        {
            string error;
            string errorDescription = e.Message;

            switch (e)
            {
                case MyInvalidClientException:
                    error = "invalid_client";
                    Response.StatusCode = 401;
                    break;
                case MyInvalidGrantException:
                    error = "invalid_grant";
                    Response.StatusCode = 400;
                    break;
                case MyInvalidRequestException:
                    error = "invalid_request";
                    Response.StatusCode = 400;
                    break;
                case MyUnsupportedGrantTypeException:
                    error = "unsupported_grant_type";
                    Response.StatusCode = 400;
                    break;
                case MyUnsupportedTokenTypeException:
                    error = "unsupported_token_type";
                    Response.StatusCode = 400;
                    break;
                default:
                    error = "server_error";
                    Response.StatusCode = 500;
                    break;
            }
            Response.SuppressFormsAuthenticationRedirect = true;

            // When I trace code to this point, everything looks fine.
            // But for some reason something subverts my JSON much farther down the pipeline....
            return Json(new { error, error_description = errorDescription });
        }
    }

这是在我的试用版中发布的请求的样子:

POST https://localhost/oauth2token HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 245
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.5 (Java/12.0.1)

grant_type=refresh_token&client_id=ObsfucatedForStackOverflow&client_secret=ObsfucatedForStackOverflow&refresh_token=ObsfucatedForStackOverflow

这是正确的结果,适当地指示错误,并呈现为 JSON:

HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
X-UA-Compatible: IE=Edge
Date: Thu, 25 Mar 2021 22:24:06 GMT
Content-Length: 71

{"error":"invalid_client","error_description":"Invalid Oauth2 Client."}

但是如果我现在转移到另一台机器上运行soapUI,发布请求,这次发布为:

POST https://my.machine.com/oauth2token HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 245
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.5 (Java/12.0.1)

grant_type=refresh_token&client_id=ObsfucatedForStackOverflow&client_secret=ObsfucatedForStackOverflow&refresh_token=ObsfucatedForStackOverflow

响应保持 401 的状态码(正确),但不知何故 application/json 内容类型已被 text/html 覆盖,实际内容也已被覆盖:

HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store
Pragma: no-cache
Content-Type: text/html
Expires: -1
X-UA-Compatible: IE=Edge
Date: Thu, 25 Mar 2021 22:29:46 GMT
Content-Length: 1293

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/>
<title>401 - Unauthorized: Access is denied due to invalid credentials.</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}
fieldset{padding:0 15px 10px 15px;} 
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} 
#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;
background-color:#555555;}
#content{margin:0 0 0 2%;position:relative;}
.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
-->
</style>
</head>
<body>
<div id="header"><h1>Server Error</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>401 - Unauthorized: Access is denied due to invalid credentials.</h2>
  <h3>You do not have permission to view this directory or page using the credentials that you supplied.</h3>
 </fieldset></div>
</div>
</body>
</html>

这不是期望的行为,但对于我的生活,我无法弄清楚是什么在注入 html 代码。有没有可能它甚至不是 MVC 而是 IIS?如何通过注入我不想停止注入的东西来强制这种试图“帮助”我的行为?我只想不理会 JSON。

请注意,注入的 HTML 不是来自表单身份验证。如果您查看上面的 c# 源代码,您将看到表单身份验证被禁止。(没有那行代码,就会注入一个完全不同的 HTML 页面)。

非常感谢任何帮助。

标签: c#jsonasp.net-mvc

解决方案


原来微软提供了另一个标志来抑制这种行为。

此外:

Response.SuppressFormsAuthenticationRedirect = true;

原来你还需要设置:

Response.TrySkipIisCustomErrors = true;

为了让 IIS 远离您的业务。


推荐阅读