编辑2:我最终只是切换到POST请求,并将latitude
,longitude
和deviceToken
放在正文中。这解决了问题。我猜想如果查询字符串太长,iOS将截断标题。我会将其发布为答案,但这更多是替代方法,而不是解决方法。
编辑1:将一些日志添加到服务器后,我发现了问题。由于某种原因,iOS切断了我的身份验证令牌的结尾。这是服务器上记录的内容(长度1015):
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImNjMTFhZWFlYmNhMjJlNzIzYzRhZDE5ZTQzNTgxNmE5ZGM4MTllMjk4OGUyMzZmYTUzYjMwNDUyYTQ2YzhkZDg2NjVlYTU4ZGJmYmY0MTIwIn0.eyJhdWQiOiIxMCIsImp0aSI6ImNjMTFhZWFlYmNhMjJlNzIzYzRhZDE5ZTQzNTgxNmE5ZGM4MTllMjk4OGUyMzZmYTUzYjMwNDUyYTQ2YzhkZDg2NjVlYTU4ZGJmYmY0MTIwIiwiaWF0IjoxNTMzNzYwNjk1LCJuYmYiOjE1MzM3NjA2OTUsImV4cCI6MTU2NTI5NjY5NSwic3ViIjoiMSIsInNjb3BlcyI6W119.OSu3q5Gxj6Sad5B44J1kUTHs0H9Yc86Hw0oXtm-CmXyO_NirIX3oVxvEsACGpn-4gMMFOx61pJ4mb43pTg9dhIgmgDmywv5mkzRC-pLd5PiSaq4YpxFxlbk_rXZWDXGgGeLwh9iZl7-ByusECeKdn0LrqE3X0XrEehU25OLPI-lDq_hREVMV-eE4zTAunCbhLGMbNCMYZuvEB8NwBhKZSpdoIGS1buZmiUCupUTajgkgfMAVup2ym45s_0eIPvLjcDZgVvpaUgkvUBUPVcEoz-kkL7BTQjmgz0aPLhWYA116pa8pU_lwzuBzU7T85FCy6Mqlas6sg2aGI5RFhcWpFrNHvenNJ7Hd3PlgZHj5bHXpEmQtu93-50Z1tkG4h-wOZ9vxV9WHvDDRzfUg5aivqJtje1dLVLkyb2Eov_gpxhJWHSeAK3laN7_K0YL_gXN0lPey8kMsSuX74rPlOuiKZXsooYoP2VU_4EMxJgBPtUjuBq4o4RqZulFQljLUN02iPaevL1c3Q9LBlXr81O6qhKTjRZ4M3fdxjRkODgBnarQhGdGTnpwSnMn1UtUvjjTJKlnrRxwj4nsZCQI06YHXB06GOV85-5ChB6-c1xFa_Xp
在iOS中(长度为1079):
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImNjMTFhZWFlYmNhMjJlNzIzYzRhZDE5ZTQzNTgxNmE5ZGM4MTllMjk4OGUyMzZmYTUzYjMwNDUyYTQ2YzhkZDg2NjVlYTU4ZGJmYmY0MTIwIn0.eyJhdWQiOiIxMCIsImp0aSI6ImNjMTFhZWFlYmNhMjJlNzIzYzRhZDE5ZTQzNTgxNmE5ZGM4MTllMjk4OGUyMzZmYTUzYjMwNDUyYTQ2YzhkZDg2NjVlYTU4ZGJmYmY0MTIwIiwiaWF0IjoxNTMzNzYwNjk1LCJuYmYiOjE1MzM3NjA2OTUsImV4cCI6MTU2NTI5NjY5NSwic3ViIjoiMSIsInNjb3BlcyI6W119.OSu3q5Gxj6Sad5B44J1kUTHs0H9Yc86Hw0oXtm-CmXyO_NirIX3oVxvEsACGpn-4gMMFOx61pJ4mb43pTg9dhIgmgDmywv5mkzRC-pLd5PiSaq4YpxFxlbk_rXZWDXGgGeLwh9iZl7-ByusECeKdn0LrqE3X0XrEehU25OLPI-lDq_hREVMV-eE4zTAunCbhLGMbNCMYZuvEB8NwBhKZSpdoIGS1buZmiUCupUTajgkgfMAVup2ym45s_0eIPvLjcDZgVvpaUgkvUBUPVcEoz-kkL7BTQjmgz0aPLhWYA116pa8pU_lwzuBzU7T85FCy6Mqlas6sg2aGI5RFhcWpFrNHvenNJ7Hd3PlgZHj5bHXpEmQtu93-50Z1tkG4h-wOZ9vxV9WHvDDRzfUg5aivqJtje1dLVLkyb2Eov_gpxhJWHSeAK3laN7_K0YL_gXN0lPey8kMsSuX74rPlOuiKZXsooYoP2VU_4EMxJgBPtUjuBq4o4RqZulFQljLUN02iPaevL1c3Q9LBlXr81O6qhKTjRZ4M3fdxjRkODgBnarQhGdGTnpwSnMn1UtUvjjTJKlnrRxwj4nsZCQI06YHXB06GOV85-5ChB6-c1xFa_XpeAvmftgz9xSKCxdlvwyQRU3NYpKd0eSJedVFEniHgjjwIhg4KYillScIrgFoo5NI
服务器令牌的末尾缺少64个字符。
我正在尝试从我的iOS应用发送带有URL中几个查询参数的GET请求。在添加新参数deviceToken
之前,一切工作正常。之后,服务器以身份验证失败响应。最奇怪的是:我同时记录了auth令牌和URL字符串,并且可以成功地从Postman发出完全相同的请求,而没有任何auth错误。
此代码收到失败的身份验证响应(请注意,queryString
包含deviceToken
):
let escapedDeviceToken = deviceToken.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) ?? ""
let queryString = "latitude=\(location.coordinate.latitude)&longitude=\(location.coordinate.longitude)&deviceToken=\(escapedDeviceToken)"
let urlString = "\(account.serverAddress)?\(queryString)"
print("--- URL string \(account.authToken) \(urlString)")
let url = URL.init(string: urlString)!
var request = URLRequest(url: url)
request.setValue(account.authToken, forHTTPHeaderField: "Authorization")
print("--- Sending location update")
let dataTask = URLSession.shared.dataTask(with: request) {data, response, error in
if let response = response {
print("--- response \(response.debugDescription)")
}
if let error = error {
print("--- Location update failed \(error.localizedDescription)")
} else if let data = data {
print("--- Location update success %@", data)
}
}
dataTask.resume()
它将记录此URL和身份验证令牌:
--- URL string
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImNjMTFhZWFlYmNhMjJlNzIzYzRhZDE5ZTQzNTgxNmE5ZGM4MTllMjk4OGUyMzZmYTUzYjMwNDUyYTQ2YzhkZDg2NjVlYTU4ZGJmYmY0MTIwIn0.eyJhdWQiOiIxMCIsImp0aSI6ImNjMTFhZWFlYmNhMjJlNzIzYzRhZDE5ZTQzNTgxNmE5ZGM4MTllMjk4OGUyMzZmYTUzYjMwNDUyYTQ2YzhkZDg2NjVlYTU4ZGJmYmY0MTIwIiwiaWF0IjoxNTMzNzYwNjk1LCJuYmYiOjE1MzM3NjA2OTUsImV4cCI6MTU2NTI5NjY5NSwic3ViIjoiMSIsInNjb3BlcyI6W119.OSu3q5Gxj6Sad5B44J1kUTHs0H9Yc86Hw0oXtm-CmXyO_NirIX3oVxvEsACGpn-4gMMFOx61pJ4mb43pTg9dhIgmgDmywv5mkzRC-pLd5PiSaq4YpxFxlbk_rXZWDXGgGeLwh9iZl7-ByusECeKdn0LrqE3X0XrEehU25OLPI-lDq_hREVMV-eE4zTAunCbhLGMbNCMYZuvEB8NwBhKZSpdoIGS1buZmiUCupUTajgkgfMAVup2ym45s_0eIPvLjcDZgVvpaUgkvUBUPVcEoz-kkL7BTQjmgz0aPLhWYA116pa8pU_lwzuBzU7T85FCy6Mqlas6sg2aGI5RFhcWpFrNHvenNJ7Hd3PlgZHj5bHXpEmQtu93-50Z1tkG4h-wOZ9vxV9WHvDDRzfUg5aivqJtje1dLVLkyb2Eov_gpxhJWHSeAK3laN7_K0YL_gXN0lPey8kMsSuX74rPlOuiKZXsooYoP2VU_4EMxJgBPtUjuBq4o4RqZulFQljLUN02iPaevL1c3Q9LBlXr81O6qhKTjRZ4M3fdxjRkODgBnarQhGdGTnpwSnMn1UtUvjjTJKlnrRxwj4nsZCQI06YHXB06GOV85-5ChB6-c1xFa_XpeAvmftgz9xSKCxdlvwyQRU3NYpKd0eSJedVFEniHgjjwIhg4KYillScIrgFoo5NI
http://192.168.1.61:80/api/updateLocation?latitude=44.0478080936615&longitude=-123.089300322125&deviceToken=fxdyzROI-vs%3AAPA91bFAdN3IR2bAxBS4rihVUCWsA1njO6RDgZ0fBDJRWvRisEKJz9I1ZTmeN6gsV85Dmg-0ZtGGqz9DSWmjZjqmyRrZ4feVBgUNPtfjALCZJM7hyScEyy02YixrW9zgcOK8sSW0JvFSrzpiPWYfdUZOt8gmU-8-NQ
这是我在Laravel服务器上看到的:
ERROR: exception 'League\OAuth2\Server\Exception\OAuthServerException' with message 'The resource owner or authorization server denied the request.' in /Users/james/projects/GoNoteDev/server/vendor/league/oauth2-server/src/Exception/OAuthServerException.php:165
Stack trace:
0 ./vendor/league/oauth2-server/src/AuthorizationValidators/BearerTokenValidator.php(53): League\OAuth2\Server\Exception\OAuthServerException::accessDenied('Access token co...')
1 ./vendor/league/oauth2-server/src/ResourceServer.php(82): League\OAuth2\Server\AuthorizationValidators\BearerTokenValidator->validateAuthorization(Object(Zend\Diactoros\ServerRequest))
2 ./vendor/laravel/passport/src/Guards/TokenGuard.php(110): League\OAuth2\Server\ResourceServer->validateAuthenticatedRequest(Object(Zend\Diactoros\ServerRequest))
3 ./vendor/laravel/passport/src/Guards/TokenGuard.php(90): Laravel\Passport\Guards\TokenGuard->authenticateViaBearerToken(Object(Illuminate\Http\Request))
4 ./vendor/laravel/passport/src/PassportServiceProvider.php(251): Laravel\Passport\Guards\TokenGuard->user(Object(Illuminate\Http\Request))
5 [internal function]: Laravel\Passport\PassportServiceProvider->Laravel\Passport\{closure}(Object(Illuminate\Http\Request))
6 ./vendor/laravel/framework/src/Illuminate/Auth/RequestGuard.php(55): call_user_func(Object(Closure), Object(Illuminate\Http\Request))
7 ./app/Http/Middleware/AuthApi.php(13): Illuminate\Auth\RequestGuard->user(Object(Illuminate\Http\Request))
8 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): App\Http\Middleware\AuthApi->handle(Object(Illuminate\Http\Request), Object(Closure))
9 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
10 ./vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
11 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
12 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
13 ./vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(49): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
14 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): Illuminate\Routing\Middleware\ThrottleRequests->handle(Object(Illuminate\Http\Request), Object(Closure), '1000', '1')
15 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
16 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(102): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
17 ./vendor/laravel/framework/src/Illuminate/Routing/Router.php(561): Illuminate\Pipeline\Pipeline->then(Object(Closure))
18 ./vendor/laravel/framework/src/Illuminate/Routing/Router.php(520): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
19 ./vendor/laravel/framework/src/Illuminate/Routing/Router.php(498): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
20 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(174): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
21 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
22 ./app/Http/Middleware/Cors.php(30): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
23 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): App\Http\Middleware\Cors->handle(Object(Illuminate\Http\Request), Object(Closure))
24 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
25 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(30): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
26 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
27 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
28 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(30): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
29 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
30 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
31 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
32 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))
33 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
34 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(46): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
35 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(148): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
36 ./vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
37 ./vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(102): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
38 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(149): Illuminate\Pipeline\Pipeline->then(Object(Closure))
39 ./vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
40 ./public/index.php(54): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
41 ./server.php(21): require_once('/Users/james/pr...')
42 {main}
然后我从iOS日志中获取确切的身份验证令牌和URL,并将其粘贴到邮递员中:
成功。邮递员请求后,我的Laravel服务器日志:
[2018-08-08 14:17:38] INFO: -123.08930032212 44.047808093662 fxdyzROI-vs:APA91bFAdN3IR2bAxBS4rihVUCWsA1njO6RDgZ0fBDJRWvRisEKJz9I1ZTmeN6gsV85Dmg-0ZtGGqz9DSWmjZjqmyRrZ4feVBgUNPtfjALCZJM7hyScEyy02YixrW9zgcOK8sSW0JvFSrzpiPWYfdUZOt8gmU-8-NQ 2
[2018-08-08 14:17:38] INFO: Sending PN to fxdyzROI-vs:APA91bFAdN3IR2bAxBS4rihVUCWsA1njO6RDgZ0fBDJRWvRisEKJz9I1ZTmeN6gsV85Dmg-0ZtGGqz9DSWmjZjqmyRrZ4feVBgUNPtfjALCZJM7hyScEyy02YixrW9zgcOK8sSW0JvFSrzpiPWYfdUZOt8gmU-8-NQ
[2018-08-08 14:17:39] INFO: Success
这是iOS HTTP代码中的错误吗?为什么只有从iOS发送请求时才会失败?看来iOS正在剥离或破坏我的Authorization
标头。
还有两件事:
deviceToken
参数。deviceToken
参数会使请求始终成功。&deviceToken=
代替&someOtherNameHere=
会导致相同的问题(似乎与deviceToken
参数完全无关)。