为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Swift 在 MySQL 数据库中存储设备令牌

使用 Swift 在 MySQL 数据库中存储设备令牌

PHP
MM们 2022-06-17 10:32:56
我一直在取得进展,但在如何使用服务器端的 PHP 和我的 iOS 应用程序上的 Swift 代码将我的用户的设备令牌放入 MySQL 数据库方面停留了几天。它成功注册了推送通知,但不会发送到我的服务器。代码片段如下。此外,我还想发送设备的 IP 以匹配我应用的当前用户。任何帮助表示赞赏!斯威夫特代码:func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {    // 1. Convert device token to string    let tokenParts = deviceToken.map { data -> String in        return String(format: "%02.2hhx", data)    }    let token = tokenParts.joined()    // 2. Print device token to use for PNs payloads    print("Successfully registered for notifications!")    print("Device Token: \(token)")    URLRequest(url: URL(string:"https://MY_URL.com/registerPushApple.php?key=MY_KEY&token=\(token)")!)}PHP代码://Put in databasedate_default_timezone_set('America/New_York');$date = date("Y-m-d");$device_ip = $_GET['device_ip'];$device_token = $_GET['token'];$key = $_GET['key'];if($key == "MY_KEY") {    // Insert Info into Database    $mysqli->query("INSERT INTO device_info (date, device_ip, device_token) VALUES ('$date', '$device_ip', '$device_token')");} else {    die();}// close connection $mysqli->close();
查看完整描述

1 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

几点观察:


您的 Swift 代码没有将请求发送到服务器。您可能会执行以下操作:


var request = URLRequest(url: URL(string:"https://MY_URL.com/registerPushApple.php")!)

request.httpBody = "key=MY_KEY&token=\(token)".data(using: .utf8)

request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")

request.httpMethod = "POST"


let task = URLSession.shared.dataTask(with: request) { data, response, error in

    guard let data = data, error == nil else {

        print(error ?? "Unknown error")

        return

    }


    // OK, if you got here, the server successfully responded, but you now

    // need to parse it with `JSONDecoder` and make sure there weren’t any 

    // SQL errors reported. But I’m just going to print the response JSON for now:


    print(String(data: data, encoding: .utf8))

}

task.resume()

笔记:


这是一个POST请求;

我们在httpBody请求中发送我们的数据,而不是 URL;和

我们正在执行请求resume。

 

我还建议对请求正文进行百分比编码,以防您的任何值包含任何保留字符。或者使用像Alamofire这样的库,它可以让你摆脱构建格式良好的请求的麻烦。


您的 PHP 代码不会检查是否INSERT成功,如果没有,则以足够的信息进行响应,以便您诊断正在发生的事情。例如:


<?php


header('Content-type: application/json');


// You didn’t send IP in your request, so you won’t find it in `$_GET` or `$_POST`

// Perhaps https://stackoverflow.com/a/2031935/1271826


function get_ip_address(){

    foreach (array('HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR') as $key){

        if (array_key_exists($key, $_SERVER) === true){

            foreach (explode(',', $_SERVER[$key]) as $ip){

                $ip = trim($ip); // just to be safe


                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false){

                    return $ip;

                }

            }

        }

    }

}


$mysqli = new mysqli('localhost', 'user', 'pwd', 'db');


// check connection 


if ($mysqli->connect_errno) {

    echo json_encode(array('success' => false, 'message' => $mysqli->connect_error, 'sqlerrno' => $mysqli->connect_errno));

    exit();

}


$mysqli->set_charset('utf8');


// perform the insert

$device_ip = get_ip_address();

$device_token = $_POST['token'];

$key = $_POST['key'];

$sql = 'INSERT INTO device_info (date, device_ip, device_token, key) VALUES (NOW(), ?, ?, ?)';


if ($stmt = $mysqli->prepare($sql)) {

    $stmt->bind_param('sss', $device_ip, $device_token, $key);


    if (!$stmt->execute())

        $response = array('success' => false, 'message' => $mysqli->error, 'sqlerrno' => $mysqli->errno, 'sqlstate' => $mysqli->sqlstate);

    else

        $response = array('success' => true);


    $stmt->close();

} else {

    $response = array('success' => false, 'message' => $mysqli->error, 'sqlerrno' => $mysqli->errno, 'sqlstate' => $mysqli->sqlstate);

}


$mysqli->close();


echo json_encode($response);


?>

笔记:


您希望将您的值绑定到?SQL 中以防止 SQL 注入攻击(或使用real_escape_string);和

您想检查插入是否成功并返回有意义的 JSON 响应,无论成功与否。

现在,我只是把它删掉了,所以请原谅任何印刷错误。但希望这能给你基本的想法。


显然,您不应该只打印返回的 JSON,而是对其进行解析JSONDecoder并查看结果是否有错误。


同样,您的 PHP 可能应该对请求中的参数进行一些优雅的检查,如果没有,则返回漂亮的 JSON 错误响应。但希望这能让你朝着正确的方向前进。


你说:


我还想发送设备的 IP 以匹配我应用的当前用户。


不,您不希望设备在请求中添加其 IP 号码,因为设备只会知道其本地 IP 号码(例如,如果在 wifi 上,它通常是 192.168.0.x 之类的东西,许多用户可能有各自的 LAN 上相同的本地 IP 号)。显然,就服务器而言,这通常是没有意义的。您应该让 PHP 从它收到的请求中提取 IP 号,如上所示。


最重要的是,无论如何,我认为IP号码不是验证用户的好方法。如果您走进一家咖啡馆并使用他们的 wifi:IP 号码已更改。您打开 VPN:IP 号码再次更改。您失去 Internet 连接并重新连接:IP 号码可能再次更改。最重要的是,IP 编号(即使您让服务器获取它而不是要求设备找出它)可能会发生变化,并且不是验证用户的好方法。


不要误会我的意思:我不认为捕获 IP 号码一定是一个坏主意。但仅供参考。如果您想验证用户,通常还有其他更好的方法可以做到这一点。


查看完整回答
反对 回复 2022-06-17
  • 1 回答
  • 0 关注
  • 129 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信