ASP.NET Google 登录:传入消息具有意外的消息格式 'Raw'

ASP.NET Google Signin: The incoming message has an unexpected message format 'Raw'

我正在尝试使用此页面实现 Google 登录:https://developers.google.com/identity/sign-in/web/backend-auth 我的令牌验证调用是:

        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'https://www.example.com/api/gtokensignin');
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.onload = function () {
            console.log('Signed in as: ' + xhr.responseText);
        };
        xhr.send('idtoken=' + id_token);

我通过 Chrome 开发人员控制台中的 [常规] 选项卡检查了请求:

一般

Request URL: https://www.example.com/api/gtokensignin
Request Method: POST
Status Code: 400 
Remote Address: 192.168.178.219:443
Referrer Policy: strict-origin-when-cross-origin

回复headers

cache-control: private
content-length: 2903
content-type: text/html
date: Thu, 01 Jul 2021 13:23:35 GMT
server: Microsoft-IIS/10.0
x-aspnet-version: 4.0.30319
x-powered-by: ASP.NET

请求headers

:authority: www.example.com
:method: POST
:path: /api/gtokensignin
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9
content-length: 1220
content-type: application/x-www-form-urlencoded
cookie: ASP.NET_SessionId=ptesmo1fxwfcgv2cple6xdzi; G_ENABLED_IDPS=google; G_AUTHUSER_H=0; _ga=GA1.1.1295181445.1624434076; __gads=ID=a5e2262ee1a99a43-23e99f1715c900bb:T=1624434076:RT=1624434076:S=ALNI_MZMMJEkUKSKcUUh9w9uH8_Z84lLAQ; _ga_MLNSQWJ4J5=GS1.1.1625123053.36.0.1625123053.0
dnt: 1
origin: https://www.example.com
referer: https://www.example.com/test2.aspx
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-origin
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36

表单数据

idtoken: eyJhbGciOiJSUzI2NiIsImtpZCI6IjExMmU0YjUyYWI4MzMwMTdkMzg1Y2UwZDBiNGM2MDU4N2VkMjU4NDIiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiOTU1MjU1MDgxOTEwLWpkcWticDQzNWo1azBnampvZGYzNmZuODEzODZ2ZnFzLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiOTU1MjU1MDgxOTEwLWpkcWticDQzNWo1azBnampvZGYzNmZuODEzODZ2ZnFzLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzYzNjQ1MjYxMDUxNjAzODgxIiwiZW1haWwiOiJmbG9yYW5mZWxlbkBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6ImdEM0pQc3EyVnJLZlZNenAzbkpJYWciLCJuYW1lIjoiRmxvcmFuIEZlbGVuIiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FBVFhBSnhFMzdPMlJFRjJfLVozeVVZV1A2c1Z1Ylcta2I2TGgzSGNZWEpINnc9czk2LWMiLCJnaXZlbl9uYW1lIjoiRmxvcmFuIiwiZmFtaWx5X25hbWUiOiJGZWxlbiIsImxvY2FsZSI6ImVuIiwiaWF0IjoxNjI1MTY3MjM4LCJleHAiOjE2MjUxNzA4MzgsImp0aSI6ImMwMjgxYWE0YTE1NTBiZWY1ZDJlOTZhOWQwY2Y5ZTU1NTY1MjA1NGEifQ.S_ubEh_4IYhQTPVSye0-tma7pfhAu9xLOoKG5SoO08ZXhqpRxcvJu5C1E6luL9I-LYVLhUNHmplmtR0JJmg47x2lqFH_vwEEGmbhfdEBrEoCXShktxbfLu1p9WcK6MUFMZFT0q93Zp2PgPIfXp_caqqxMeAGEZfzWMK9ZmZhMfmTX_Ny2KlO4KJHR-FvY9Rv1XrcTrTiWfTclKFqpIvyWaUR-wk4srWpu1-riH5J9lz-VC-nmQAbWZw0kxD2DK0RjqsbeXJvPrrtjiCURM-s2b4tfvtyADRkgF2Nh9oOlsMJZRxKXoGNYsLoR0iYYcGbQm4NZGzVwmPj3pxtf1htEA

但是,服务器returns出现如下错误:

The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.

完整错误:

The server encountered an error processing the request. Please see the service help page for constructing valid requests to the service. The exception message is 'The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.'. See server logs for more details. The exception stack trace is:

at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters) at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

Iapi.vb

<OperationContract()>
    <Web.WebInvoke(Method:="POST", ResponseFormat:=Web.WebMessageFormat.Json, BodyStyle:=Web.WebMessageBodyStyle.Bare,
UriTemplate:="gtokensignin")>
    Function gtokensignin(ByVal str As String) As Stream   

我最初在上面的代码中有 BodyStyle:=Web.WebMessageBodyStyle.WrappedRequest。 我还尝试在 OperationContract() 中将 BodyStyle= 更改为 BodyStyle=WebMessageBodyStyle.Wrapped,但会引发相同的错误。

我还尝试将签名更改为:
<Web.WebInvoke(Method:="POST", RequestFormat = WebMessageFormat.Json, ResponseFormat:=Web.WebMessageFormat.Json, BodyStyle:=Web.WebMessageBodyStyle.Bare, 但后来我得到了错误

'RequestFormat' is not declared. It may be inaccessible due to its protection level.

web.config

<services>
  <service behaviorConfiguration="ServiceBehaviour" name="Mysite.api">
    <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="Binding" contract="Mysite.Iapi" />
    <endpoint address="" behaviorConfiguration="web" binding="webHttpBinding" bindingConfiguration="httpbind" contract="Mysite.Iapi" />
  </service>
</services>     

当我通过 https://www.example.com/api.svc/help/operations/gtokensignin 检查资源可用性时,我看到了这个页面:

我已经检查过:

更新 1

我尝试 post 通过 JSON 而不是表单 post,但我得到了错误:

The server encountered an error processing the request. Please see the <a rel="help-page" href="https://www.example.com/api.svc/help">service help page</a> for constructing valid requests to the service. The exception message is 'There was an error deserializing the object of type System.String. End element 'root' from namespace '' expected. Found element 'idtoken' from namespace ''.'. See server logs for more details. The exception stack trace is: 
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator reader, Boolean verifyObjectName, DataContractResolver dataContractResolver)
   at System.Runtime.Serialization.Json.DataContractJsonSerializer.ReadObject(XmlDictionaryReader reader, Boolean verifyObjectName)
   at System.ServiceModel.Dispatcher.SingleBodyParameterDataContractMessageFormatter.ReadObject(Message message)
   at System.ServiceModel.Dispatcher.SingleBodyParameterMessageFormatter.DeserializeRequest(Message message, Object[] parameters)
   at System.ServiceModel.Dispatcher.DemultiplexingDispatchMessageFormatter.DeserializeRequest(Message message, Object[] parameters)
   at System.ServiceModel.Dispatcher.UriTemplateDispatchFormatter.DeserializeRequest(Message message, Object[] parameters)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.DeserializeInputs(MessageRpc&amp; rpc)
   at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc&amp; rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc&amp; rpc)
   at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)
   at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</p>

基于服务器错误。它只接受 JSON 或 XML。 所以尝试像这样将 id_token 作为 JSON 发送。

var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.example.com/api/gtokensignin');
xhr.setRequestHeader('Content-Type', 'application/json'); // because we are sending json 

const data = {
    "idtoken": id_token,
};

xhr.send(JSON.stringify(data));

如果您坚持以表单形式发送数据 post 请查看此答案。

更新 1 根据您的更新,您的服务器接受了 JSON 请求,但无法将其反序列化为 System.String,因为您正在 posting 一个对象。要将字符串作为 JSON 发送,试试这个

var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://www.example.com/api/gtokensignin');
xhr.setRequestHeader('Content-Type', 'application/json'); // because we are sending json 

xhr.send(JSON.stringify(id_token));