在数据库中保存IP

问题描述 投票:2回答:4

当用户登录时,我想把他们的IP保存在数据库中。我如何做到这一点?MySQL字段用什么类型最好?获取IP的PHP代码是怎样的?

我想把它作为一个额外的安全功能,用于登录的东西。我想除了检查会话之外,还要检查用户从数据库中登录的IP和用户现在的IP。所以它首先检查会话,然后检查你是否有一个有效的IP。

这是一个很好的额外功能吗?我还可以做什么其他的事情来使它更安全?

php mysql ip
4个回答
9
投票

看看mysql中的INET_NTOA和INET_ATON函数。它们可以将点符号的IP地址转换为32位的整数。这允许你存储的IP只有4个字节,而不是一个15个字节。确保你使用一个无符号的int而不是有符号的int。


2
投票

关于William Leader的建议,PHP有两个函数ip2long和long2ip,正是他所说的。


0
投票

正如 Lauri Lehtinen 所说的,你可以使用 $_SERVER['REMOTE_ADDR'] 获取IP地址,一个简单的PHP代码,看下面......

<?php
$conn = mysql_connect("server","username","password");//server, username and password are your server address and access details
if(!$conn)
    die("cannot connect to mysql server" . mysql_error());
mysql_select_db("database Name", $conn);
$sql = "INSERT INTO table_name (IP_Address) VALUES(" . $_SERVER['REMOTE_ADDR'] . ")";
if(!mysql_query($sql,$conn))
    die("ERROR: " .mysql_error());
mysql_close($con);
?>

这只是一个例子,只要修改它来满足你的需求......


0
投票

TLDR; 使用VARBINARY(16)并使用INET6_ATON和INET6_NTOA函数来写入存储在DB中的$_SERVER['REMOTE_ADDR']。

在回答这个问题之前,最好先讨论一下如何获取IP地址。如果你会用它来做一些重要的事情(比如安全检查),那么你应该只用$_SERVER['REMOTE_ADDR'],因为它是唯一可信的来源(由web服务器生成,并通过TCPIP三路握手保证良好)......除非你在本地网络中使用应用程序......等等。如果是网站,用$_SERVER['REMOTE_ADDR']取用户IP。

这个IP可以是代理服务器的IP。如果用户在代理服务器后面,你可以通过获取代理服务器(有时)添加的头文件来最终获得原始用户IP。这是个101函数。

     $ip = filter_var(
            array_map("trim", 
                explode("," ,
                    $_SERVER['HTTP_CLIENT_IP']??
                    $_SERVER['HTTP_X_FORWARDED_FOR']??
                    $_SERVER['HTTP_X_FORWARDED']??
                    $_SERVER['HTTP_FORWARDED_FOR']??
                    $_SERVER['HTTP_FORWARDED']??
                    $_SERVER['REMOTE_ADDR']
                )
            )[0],
          FILTER_VALIDATE_IP);
    $ip = $ip!=""?$ip:"Invalid IP";
    echo $ip;

但要注意的是,任何以HTTP_*开头的头信息都可以被用户伪造(他可以在那里写任何他想写的东西。所以这个是不可信的。

说到这里,如果你使用PHP和MySQLMariaDB,你可以用下面的方法存储IP(在下面的例子中,我存储了IP和登录系统的尝试次数)。

    CREATE TABLE login_logs_hash(
         ip VARBINARY(16) NOT NULL,
         PRIMARY KEY(ip) USING HASH,
         attempts INT UNSIGNED NOT NULL DEFAULT 1
    )ENGINE = MEMORY;

当登录不成功(无效的用户名和密码)时,在脚本的某个地方。

    ...
    $sql = "INSERT INTO login_logs_hash (ip) 
            VALUES (INET6_ATON('".$_SERVER['REMOTE_ADDR']."'))
            ON DUPLICATE KEY UPDATE attempts = attempts+1";
    $result = mysqli_query($link, $sql);
    ...

通过这个例子我终于向你展示了答案--最好的列是VARBINARY(16)。它可以同时存储IPv6和IPv4。

重要的是:不要把它改成BINARY(16),即使你最终会认为固定列宽更好。如果你按照我的例子,它将不会正确地存储IPv4地址。

© www.soinside.com 2019 - 2024. All rights reserved.