ASP.NET MVC 应用程序应用程序/json 响应内容神秘地被文本/html 内容覆盖

Posted

技术标签:

【中文标题】ASP.NET MVC 应用程序应用程序/json 响应内容神秘地被文本/html 内容覆盖【英文标题】:ASP.NET MVC app application/json response content mysteriously being overwritten by text/html content 【发布时间】:2021-06-22 18:54:44 【问题描述】:

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

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

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

首先是代码 sn-p,我为这个问题简化了它。返回 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=ObsfucatedFor***&client_secret=ObsfucatedFor***&refresh_token=ObsfucatedFor***

这是正确的结果,适当地指示错误,并呈现为 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=ObsfucatedFor***&client_secret=ObsfucatedFor***&refresh_token=ObsfucatedFor***

响应保持 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">
<!--
bodymargin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;
fieldsetpadding:0 15px 10px 15px; 
h1font-size:2.4em;margin:0;color:#FFF;
h2font-size:1.7em;margin:0;color:#CC0000; 
h3font-size:1.2em;margin:10px 0 0 0;color:#000000; 
#headerwidth:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS", Verdana, sans-serif;color:#FFF;
background-color:#555555;
#contentmargin:0 0 0 2%;position:relative;
.content-containerbackground:#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 页面)。

非常感谢任何帮助。

【问题讨论】:

【参考方案1】:

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

除了:

Response.SuppressFormsAuthenticationRedirect = true;

原来你还需要设置:

Response.TrySkipIisCustomErrors = true;

为了让 IIS 远离您的业务。

【讨论】:

以上是关于ASP.NET MVC 应用程序应用程序/json 响应内容神秘地被文本/html 内容覆盖的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ASP.net MVC 程序中获取纯 c# 程序中的 JSON 数据?

从 ASP.net Core 2 MVC 应用程序中的 appSettings.json 存储/检索 ConnectionString

在ASP.NET MVC中全局应用JSON Serializer设置

ASP.NET MVC 应用程序应用程序/json 响应内容神秘地被文本/html 内容覆盖

传递需要的大量 Json 对象时如何改进 Asp.net Mvc 应用程序?

ASP.NET MVC、JSON 和非 JavaScript 客户端