问题描述
我正在尝试使用此页面实施 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 开发者控制台中的 [General] 选项卡检查了请求:
一般
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
响应标头
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
请求标头
: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
但是服务器返回如下错误:
传入的消息具有意外的消息格式“原始”。操作的预期消息格式是“Xml”; '杰森'。这可能是因为尚未在绑定上配置 WebContentTypeMapper。有关详细信息,请参阅 WebContentTypeMapper 的文档。
完全错误:
服务器在处理请求时遇到错误。请参阅服务帮助页面以构建对服务的有效请求。异常消息是“传入的消息具有意外的消息格式“原始”。操作的预期消息格式是“Xml”; '杰森'。这可能是因为尚未在绑定上配置 WebContentTypeMapper。有关更多详细信息,请参阅 WebContentTypeMapper 的文档。'。有关更多详细信息,请参阅服务器日志。异常堆栈跟踪是:
在 System.ServiceModel.dispatcher.Demultiplexingdispatchmessageformatter.DeserializeRequest(Message message,Object[] parameters) 在 System.ServiceModel.dispatcher.UriTemplatedispatchFormatter.DeserializeRequest(Message message,Object[] parameters) 在 System.ServiceModel.dispatcher.dispatchOperationRuntime.DeserializeInputs(MessageRpc& rpc) 在 System.ServiceModel.dispatcher.dispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) 在 System.ServiceModel.dispatcher.ImmutabledispatchRuntime.ProcessMessage5(MessageRpc& rpc) 在 System.ServiceModel.dispatcher.ImmutabledispatchRuntime.ProcessMessage11(MessageRpc& rpc) 在 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,
但后来我得到了错误
'RequestFormat' 未声明。由于其保护级别,它可能无法访问。
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 检查资源可用性时,我看到了这个页面:
我已经检查过了:
- WCF service error - Incoming message has an unexpected message format 'Raw'. Expected message formats are 'Xml','Json'
- WCF request: "The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml'; 'Json'"
- The expected message formats for the operation are 'Xml','Json'
更新 1
我尝试通过 JSON 而不是表单发布,但随后出现错误:
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& 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)</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));
如果您坚持将数据作为表单发布,请查看此答案。 https://stackoverflow.com/a/6329148/5964792
更新 1 根据您的更新,您的服务器接受 JSON 请求,但无法将其反序列化为 System.String,因为您正在发布一个对象。要将字符串作为 JSON 发送,试试这个
var xhr = new XMLHttpRequest();
xhr.open('POST','application/json'); // because we are sending json
xhr.send(JSON.stringify(id_token));