php+redis实现ip白名单并提供可配置ip页面

2017-04-24 13:33

ip白名单或者黑名单,目的是为了达到一种受限访问,希望在名单内用户可以访问,就把名单叫白名单;希望在名单内用户拒绝访问,就是黑名单。无论我们希望使用哪种名单方式,实现方式都一样。

在nginx下我们通常会考虑用nginx+lua的方式来实现,它很优雅速度快。确实,这是一种方案,我也做过这种方案的研究。但我觉的它不够灵活,我选择在应用程序中来实现名单机制。

主要思路:用户->获取ip->redis取出名单库->比对->处理

代码Github库:https://github.com/jacoobwang...

控制访问

<?php
    isAccess();
    /**
     * 检测是否在白名单内,否则拒绝访问
     * 
     * @return void
     */
    function isAccess(){
        $ip = getRemoteIp();
        if(!empty($ip)) {
            $inst = new Redis();
            $inst->connect('127.0.0.1', 6379);
            $ip_white_list = $inst->sMembers('ip_blacklist');
            if(!in_array($ip, $ip_white_list)) {
                echo '<h1 align=center>HTTP/1.1 403 Forbidden</h1>';
                header('HTTP/1.1 403 Forbidden');
            }
        }
        
    }
    /**
     * 获取用户的IP
     * 
     * @return void
     */
    function getRemoteIp(){
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }elseif(isset($_SERVER['HTTP_CLIENT_IP'])){
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }elseif(getenv('HTTP_X_FORWARDED_FOR')){
            $ip = getenv('HTTP_X_FORWARED_FOR');
        }elseif(getenv('HTTP_CLIENT_IP')){
            $ip = getenv('HTTP_CLIENT_IP');
        }elseif($_SERVER['REMOTE_ADDR']){
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        else{
            $ip = null;
        }
        return $ip;
    }

动态配置页面

<?php
$inst = new Redis();
$inst->connect('127.0.0.1', 6379);
$ip = $inst->sMembers('ip_blacklist');
$li = '';
foreach($ip as $val) {
    $li .= '<li><span>'.$val.'</span>&nbsp;<a data="'.$val.'" class="js_del" href="javascript:void(0)">delete</a></li>';
}
?>

<html>
    <head>
        <style>
            ul,li {
                list-style: none;
            }
            ul {
                margin: 0;
                padding: 0;
            }
            li {
                padding: 5px;
                padding-top:0;
            }
        </style>
    </head>
    <body>
        <ul id="ipList">
            <?php echo $li;?>   
        </ul>  

        <input type="text" name="ip_text" />
        <button id="submit">add</button>        
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.0/jquery.js"></script>
    <script>
        $(function(){
            // 删除
            $('#ipList').on('click','.js_del',function(){
                var _this = this,
                    ip_text = $(this).attr('data'); 
                $.ajax({
                    url: 'http://localhost:6699/ip-white-php/ip.php',
                    method: 'POST',
                    data: 'type=delete&ip='+ip_text,
                    success: function(res){
                       if(res == 1){
                           alert('success');
                           $(_this).parent().remove();
                       } else {
                           alert('failed');
                       }     
                    }
                })
            })
            // 添加
            $('#submit').click(function(){
                var ip_text = $("input[type=text]").val(),
                    re = /^\d{2,3}.\d{2,3}.\d{2,3}.\d{1,3}$/;
                if (!re.test(ip_text)) {
                    alert('您输入的IP格式不对');
                    return;
                }   
                $.ajax({
                    url: 'http://localhost:6699/ip-white-php/ip.php',
                    method: 'POST',
                    data: 'type=add&ip='+ip_text,
                    success: function(res){
                       if(res == 1){
                           alert('success');
                           $('#ipList').append('<li><span>'+ip_text+'</span>&nbsp;<a data="'+ip_text+'" class="js_del" href="javascript:void(0)">delete</a></li>')
                       } else {
                           alert('failed');
                       }
                    }
                })
            })
        })
    </script>
</html>

配置页面接口

<?php
$inst = new Redis();
$inst->connect('127.0.0.1', 6379);
$type = isset($_POST['type']) ? $_POST['type'] : ''; 
$ip = isset($_POST['ip']) ? $_POST['ip'] : '';
if(!empty($ip)){
    $isExist = $inst->sIsMember('ip_blacklist',$ip);
    
    if($isExist) {
        if($type == 'delete'){
            // delete
            $rs = $inst->sRemove('ip_blacklist',$ip);
            echo $rs;
        }
    } else {
        if($type == 'add'){
            if(preg_match('/^\d{2,3}.\d{2,3}.\d{2,3}.\d{1,3}$/',$ip)) {
                $rs = $inst->sAdd('ip_blacklist',$ip);
                echo $rs;
            } else {
                echo 2;
            }
        }
    }
}