ECharts 响应式

ECharts 响应式

ECharts 图表显示在用户指定高宽的 DOM 节点(容器)中。

有时候我们希望在 PC 和 移动设备上都能够很好的展示图表的内容,实现响应式的设计,为了解决这个问题,ECharts 完善了组件的定位设置,并且实现了类似 CSS Media Query 的自适应能力。


ECharts 组件的定位和布局

大部分『组件』和『系列』会遵循两种定位方式。

left/right/top/bottom/width/height 定位方式

这六个量中,每个量都可以是『绝对值』或者『百分比』或者『位置描述』。

  • 绝对值

    单位是浏览器像素(px),用 number 形式书写(不写单位)。例如 {left: 23, height: 400}

  • 百分比

    表示占 DOM 容器高宽的百分之多少,用 string 形式书写。例如 {right: '30%', bottom: '40%'}

  • 位置描述

    • 可以设置 left: 'center',表示水平居中。
    • 可以设置 top: 'middle',表示垂直居中。

这六个量的概念,和 CSS 中六个量的概念类似:

  • left:距离 DOM 容器左边界的距离。
  • right:距离 DOM 容器右边界的距离。
  • top:距离 DOM 容器上边界的距离。
  • bottom:距离 DOM 容器下边界的距离。
  • width:宽度。
  • height:高度。

在横向,left、right、width 三个量中,只需两个量有值即可,因为任两个量可以决定组件的位置和大小,例如 left 和 right 或者 right 和 width 都可以决定组件的位置和大小。 纵向,top、bottom、height 三个量,和横向类同不赘述。

center / radius 定位方式

  • center

    是一个数组,表示 [x, y],其中,xy可以是『绝对值』或者『百分比』,含义和前述相同。

  • radius

    是一个数组,表示 [内半径, 外半径],其中,内外半径可以是『绝对值』或者『百分比』,含义和前述相同。

    在自适应容器大小时,百分比设置是很有用的。

横向(horizontal)和纵向(vertical)

ECharts的『外观狭长』型的组件(如 legend、visualMap、dataZoom、timeline等),大多提供了『横向布局』『纵向布局』的选择。例如,在细长的移动端屏幕上,可能适合使用『纵向布局』;在PC宽屏上,可能适合使用『横向布局』。

横纵向布局的设置,一般在『组件』或者『系列』的 orient 或者 layout 配置项上,设置为 ‘horizontal’ 或者 ‘vertical’。


实例

以下实例中我们可以可尝试拖动右下角的圆点,图表会随着屏幕尺寸变化,legend 和 系列会自动改变布局位置和方式。

实例中我们使用了 jQuery 来加载外部数据,使用时我们需要引入 jQuery 库。

实例

$.when(
    $.getScript(‘https://www.runoob.com/static/js/timelineGDP.js’),
    $.getScript(‘https://www.runoob.com/static/js/draggable.js’)
).done(function () {

    draggable.init(
        $(‘div[_echarts_instance_]’)[0],
        myChart,
        {
            width: 700,
            height: 400,
            throttle: 70
        }
    );

    myChart.hideLoading();

    option = {
        baseOption: {
            title : {
                text: ‘南丁格尔玫瑰图’,
                subtext: ‘纯属虚构’,
                x:‘center’
            },
            tooltip : {
                trigger: ‘item’,
                formatter: “{a} <br/>{b} : {c} ({d}%)”
            },
            legend: {
                data:[‘rose1’,‘rose2’,‘rose3’,‘rose4’,‘rose5’,‘rose6’,‘rose7’,‘rose8’]
            },
            toolbox: {
                show : true,
                feature : {
                    mark : {show: true},
                    dataView : {show: true, readOnly: false},
                    magicType : {
                        show: true,
                        type: [‘pie’, ‘funnel’]
                    },
                    restore : {show: true},
                    saveAsImage : {show: true}
                }
            },
            calculable : true,
            series : [
                {
                    name:‘半径模式’,
                    type:‘pie’,
                    roseType : ‘radius’,
                    label: {
                        normal: {
                            show: false
                        },
                        emphasis: {
                            show: true
                        }
                    },
                    lableLine: {
                        normal: {
                            show: false
                        },
                        emphasis: {
                            show: true
                        }
                    },
                    data:[
                        {value:10, name:‘rose1’},
                        {value:5, name:‘rose2’},
                        {value:15, name:‘rose3’},
                        {value:25, name:‘rose4’},
                        {value:20, name:‘rose5’},
                        {value:35, name:‘rose6’},
                        {value:30, name:‘rose7’},
                        {value:40, name:‘rose8’}
                    ]
                },
                {
                    name:‘面积模式’,
                    type:‘pie’,
                    roseType : ‘area’,
                    data:[
                        {value:10, name:‘rose1’},
                        {value:5, name:‘rose2’},
                        {value:15, name:‘rose3’},
                        {value:25, name:‘rose4’},
                        {value:20, name:‘rose5’},
                        {value:35, name:‘rose6’},
                        {value:30, name:‘rose7’},
                        {value:40, name:‘rose8’}
                    ]
                }
            ]
        },
        media: [
            {
                option: {
                    legend: {
                        right: ‘center’,
                        bottom: 0,
                        orient: ‘horizontal’
                    },
                    series: [
                        {
                            radius: [20, ‘50%’],
                            center: [‘25%’, ‘50%’]
                        },
                        {
                            radius: [30, ‘50%’],
                            center: [‘75%’, ‘50%’]
                        }
                    ]
                }
            },
            {
                query: {
                    minAspectRatio: 1
                },
                option: {
                    legend: {
                        right: ‘center’,
                        bottom: 0,
                        orient: ‘horizontal’
                    },
                    series: [
                        {
                            radius: [20, ‘50%’],
                            center: [‘25%’, ‘50%’]
                        },
                        {
                            radius: [30, ‘50%’],
                            center: [‘75%’, ‘50%’]
                        }
                    ]
                }
            },
            {
                query: {
                    maxAspectRatio: 1
                },
                option: {
                    legend: {
                        right: ‘center’,
                        bottom: 0,
                        orient: ‘horizontal’
                    },
                    series: [
                        {
                            radius: [20, ‘50%’],
                            center: [‘50%’, ‘30%’]
                        },
                        {
                            radius: [30, ‘50%’],
                            center: [‘50%’, ‘70%’]
                        }
                    ]
                }
            },
            {
                query: {
                    maxWidth: 500
                },
                option: {
                    legend: {
                        right: 10,
                        top: ‘15%’,
                        orient: ‘vertical’
                    },
                    series: [
                        {
                            radius: [20, ‘50%’],
                            center: [‘50%’, ‘30%’]
                        },
                        {
                            radius: [30, ‘50%’],
                            center: [‘50%’, ‘75%’]
                        }
                    ]
                }
            }
        ]
    };

    myChart.setOption(option);

});

尝试一下 »

要在 option 中设置 Media Query 须遵循如下格式:

option = {
    baseOption: { // 这里是基本的『原子option』。
        title: {...},
        legend: {...},
        series: [{...}, {...}, ...],
        ...
    },
    media: [ // 这里定义了 media query 的逐条规则。
        {
            query: {...},   // 这里写规则。
            option: {       // 这里写此规则满足下的option。
                legend: {...},
                ...
            }
        },
        {
            query: {...},   // 第二个规则。
            option: {       // 第二个规则对应的option。
                legend: {...},
                ...
            }
        },
        {                   // 这条里没有写规则,表示『默认』,
            option: {       // 即所有规则都不满足时,采纳这个option。
                legend: {...},
                ...
            }
        }
    ]
};

上面的例子中,baseOption、以及 media 每个 option 都是『原子 option』,即普通的含有各组件、系列定义的 option。而由『原子option』组合成的整个 option,我们称为『复合 option』。baseOption 是必然被使用的,此外,满足了某个 query 条件时,对应的 option 会被使用 chart.mergeOption() 来 merge 进去。

query

每个 query 类似于这样:

{
    minWidth: 200,
    maxHeight: 300,
    minAspectRatio: 1.3
}

现在支持三个属性:width、height、aspectRatio(长宽比)。每个属性都可以加上 min 或 max 前缀。比如,minWidth: 200 表示『大于等于200px宽度』。两个属性一起写表示『并且』,比如:{minWidth: 200, maxHeight: 300} 表示『大于等于200px宽度,并且小于等于300px高度』。

option

media中的 option 既然是『原子 option』,理论上可以写任何 option 的配置项。但是一般我们只写跟布局定位相关的,例如截取上面例子中的一部分 query option:

media: [
    ...,
    {
        query: {
            maxAspectRatio: 1           // 当长宽比小于1时。
        },
        option: {
            legend: {                   // legend 放在底部中间。
                right: 'center',
                bottom: 0,
                orient: 'horizontal'    // legend 横向布局。
            },
            series: [                   // 两个饼图左右布局。
                {
                    radius: [20, '50%'],
                    center: ['50%', '30%']
                },
                {
                    radius: [30, '50%'],
                    center: ['50%', '70%']
                }
            ]
        }
    },
    {
        query: {
            maxWidth: 500               // 当容器宽度小于 500 时。
        },
        option: {
            legend: {
                right: 10,              // legend 放置在右侧中间。
                top: '15%',
                orient: 'vertical'      // 纵向布局。
            },
            series: [                   // 两个饼图上下布局。
                {
                    radius: [20, '50%'],
                    center: ['50%', '30%']
                },
                {
                    radius: [30, '50%'],
                    center: ['50%', '75%']
                }
            ]
        }
    },
    ...
]

多个 query 被满足时的优先级

注意,可以有多个 query 同时被满足,会都被 mergeOption,定义在后的后被 merge(即优先级更高)。

默认 query

如果 media 中有某项不写 query,则表示『默认值』,即所有规则都不满足时,采纳这个option。

容器大小实时变化时的注意事项

在不少情况下,并不需要容器DOM节点任意随着拖拽变化大小,而是只是根据不同终端设置几个典型尺寸。

但是如果容器DOM节点需要能任意随着拖拽变化大小,那么目前使用时需要注意这件事:某个配置项,如果在某一个 query option 中出现,那么在其他 query option 中也必须出现,否则不能够回归到原来的状态。(left/right/top/bottom/width/height 不受这个限制。)

『复合 option』 中的 media 不支持 merge

也就是说,当第二(或三、四、五 …)次 chart.setOption(rawOption) 时,如果 rawOption 是 复合option(即包含 media 列表),那么新的 rawOption.media 列表不会和老的 media 列表进行 merge,而是简单替代。当然,rawOption.baseOption 仍然会正常和老的 option 进行merge。

其实,很少有场景需要使用『复合 option』来多次 setOption,而我们推荐的做法是,使用 mediaQuery 时,第一次setOption使用『复合 option』,后面 setOption 时仅使用 『原子 option』,也就是仅仅用 setOption 来改变 baseOption。

以下中我们使用了 jQuery 来加载外部数据,使用时我们需要引入 jQuery 库。该实例是一个和时间轴结合的例子:

实例

$.when(
    $.getScript(‘https://www.runoob.com/static/js/timelineGDP.js’),
    $.getScript(‘https://www.runoob.com/static/js/draggable.js’)
).done(function () {

    draggable.init(
        $(‘div[_echarts_instance_]’)[0],
        myChart,
        {
            width: 700,
            height: 630,
            lockY: true,
            throttle: 70
        }
    );

    myChart.hideLoading();

    var categoryData = [
        ‘北京’,‘天津’,‘河北’,‘山西’,‘内蒙古’,‘辽宁’,‘吉林’,‘黑龙江’,
        ‘上海’,‘江苏’,‘浙江’,‘安徽’,‘福建’,‘江西’,‘山东’,‘河南’,
        ‘湖北’,‘湖南’,‘广东’,‘广西’,‘海南’,‘重庆’,‘四川’,‘贵州’,
        ‘云南’,‘西藏’,‘陕西’,‘甘肃’,‘青海’,‘宁夏’,‘新疆’
    ];

    option = {
        baseOption: {
            timeline: {
                axisType: ‘category’,
                autoPlay: true,
                playInterval: 1000,
                data: [
                    ‘2002-01-01’, ‘2003-01-01’, ‘2004-01-01’,
                    ‘2005-01-01’, ‘2006-01-01’, ‘2007-01-01’,
                    ‘2008-01-01’, ‘2009-01-01’, ‘2010-01-01’,
                    ‘2011-01-01’
                ],
                label: {
                    formatter : function(s) {
                        return (new Date(s)).getFullYear();
                    }
                }
            },
            title: {
                subtext: ‘Media Query 示例’
            },
            tooltip: {
                trigger:‘axis’,
                axisPointer: {
                    type: ‘shadow’
                }
            },
            xAxis: {
                type: ‘value’,
                name: ‘GDP(亿元)’,
                max: 30000,
                data: null
            },
            yAxis: {
                type: ‘category’,
                data: categoryData,
                axisLabel: {interval: 0},
                splitLine: {show: false}
            },
            legend: {
                data: [‘第一产业’, ‘第二产业’, ‘第三产业’, ‘GDP’, ‘金融’, ‘房地产’],
                selected: {
                    ‘GDP’: false, ‘金融’: false, ‘房地产’: false
                }
            },
            calculable : true,
            series: [
                {name: ‘GDP’, type: ‘bar’},
                {name: ‘金融’, type: ‘bar’},
                {name: ‘房地产’, type: ‘bar’},
                {name: ‘第一产业’, type: ‘bar’},
                {name: ‘第二产业’, type: ‘bar’},
                {name: ‘第三产业’, type: ‘bar’},
                {name: ‘GDP占比’, type: ‘pie’}
            ]
        },
        media: [
            {
                option: {
                    legend: {
                        orient: ‘horizontal’,
                        left: ‘right’,
                        itemGap: 10
                    },
                    grid: {
                        left: ‘10%’,
                        top: 80,
                        right: 90,
                        bottom: 100
                    },
                    xAxis: {
                        nameLocation: ‘end’,
                        nameGap: 10,
                        splitNumber: 5,
                        splitLine: {
                            show: true
                        }
                    },
                    timeline: {
                        orient: ‘horizontal’,
                        inverse: false,
                        left: ‘20%’,
                        right: ‘20%’,
                        bottom: 10,
                        height: 40
                    },
                    series: [
                        {name: ‘GDP占比’, center: [‘75%’, ‘30%’], radius: ‘28%’}
                    ]
                }
            },
            {
                query: {maxWidth: 670, minWidth: 550},
                option: {
                    legend: {
                        orient: ‘horizontal’,
                        left: 200,
                        itemGap: 5
                    },
                    grid: {
                        left: ‘10%’,
                        top: 80,
                        right: 90,
                        bottom: 100
                    },
                    xAxis: {
                        nameLocation: ‘end’,
                        nameGap: 10,
                        splitNumber: 5,
                        splitLine: {
                            show: true
                        }
                    },
                    timeline: {
                        orient: ‘horizontal’,
                        inverse: false,
                        left: ‘20%’,
                        right: ‘20%’,
                        bottom: 10,
                        height: 40
                    },
                    series: [
                        {name: ‘GDP占比’, center: [‘75%’, ‘30%’], radius: ‘28%’}
                    ]
                }
            },
            {
                query: {maxWidth: 550},
                option: {
                    legend: {
                        orient: ‘vertical’,
                        left: ‘right’,
                        itemGap: 5
                    },
                    grid: {
                        left: 55,
                        top: ‘32%’,
                        right: 100,
                        bottom: 50
                    },
                    xAxis: {
                        nameLocation: ‘middle’,
                        nameGap: 25,
                        splitNumber: 3
                    },
                    timeline: {
                        orient: ‘vertical’,
                        inverse: true,
                        right: 10,
                        top: 150,
                        bottom: 10,
                        width: 55
                    },
                    series: [
                        {name: ‘GDP占比’, center: [‘45%’, ‘20%’], radius: ‘28%’}
                    ]
                }
            }
        ],
        options: [
            {
                title: {text: ‘2002全国宏观经济指标’},
                series: [
                    {data: dataMap.dataGDP[‘2002’]},
                    {data: dataMap.dataFinancial[‘2002’]},
                    {data: dataMap.dataEstate[‘2002’]},
                    {data: dataMap.dataPI[‘2002’]},
                    {data: dataMap.dataSI[‘2002’]},
                    {data: dataMap.dataTI[‘2002’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2002sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2002sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2002sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2003全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2003’]},
                    {data: dataMap.dataFinancial[‘2003’]},
                    {data: dataMap.dataEstate[‘2003’]},
                    {data: dataMap.dataPI[‘2003’]},
                    {data: dataMap.dataSI[‘2003’]},
                    {data: dataMap.dataTI[‘2003’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2003sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2003sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2003sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2004全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2004’]},
                    {data: dataMap.dataFinancial[‘2004’]},
                    {data: dataMap.dataEstate[‘2004’]},
                    {data: dataMap.dataPI[‘2004’]},
                    {data: dataMap.dataSI[‘2004’]},
                    {data: dataMap.dataTI[‘2004’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2004sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2004sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2004sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2005全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2005’]},
                    {data: dataMap.dataFinancial[‘2005’]},
                    {data: dataMap.dataEstate[‘2005’]},
                    {data: dataMap.dataPI[‘2005’]},
                    {data: dataMap.dataSI[‘2005’]},
                    {data: dataMap.dataTI[‘2005’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2005sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2005sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2005sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2006全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2006’]},
                    {data: dataMap.dataFinancial[‘2006’]},
                    {data: dataMap.dataEstate[‘2006’]},
                    {data: dataMap.dataPI[‘2006’]},
                    {data: dataMap.dataSI[‘2006’]},
                    {data: dataMap.dataTI[‘2006’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2006sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2006sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2006sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2007全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2007’]},
                    {data: dataMap.dataFinancial[‘2007’]},
                    {data: dataMap.dataEstate[‘2007’]},
                    {data: dataMap.dataPI[‘2007’]},
                    {data: dataMap.dataSI[‘2007’]},
                    {data: dataMap.dataTI[‘2007’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2007sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2007sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2007sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2008全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2008’]},
                    {data: dataMap.dataFinancial[‘2008’]},
                    {data: dataMap.dataEstate[‘2008’]},
                    {data: dataMap.dataPI[‘2008’]},
                    {data: dataMap.dataSI[‘2008’]},
                    {data: dataMap.dataTI[‘2008’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2008sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2008sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2008sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2009全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2009’]},
                    {data: dataMap.dataFinancial[‘2009’]},
                    {data: dataMap.dataEstate[‘2009’]},
                    {data: dataMap.dataPI[‘2009’]},
                    {data: dataMap.dataSI[‘2009’]},
                    {data: dataMap.dataTI[‘2009’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2009sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2009sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2009sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2010全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2010’]},
                    {data: dataMap.dataFinancial[‘2010’]},
                    {data: dataMap.dataEstate[‘2010’]},
                    {data: dataMap.dataPI[‘2010’]},
                    {data: dataMap.dataSI[‘2010’]},
                    {data: dataMap.dataTI[‘2010’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2010sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2010sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2010sum’]}
                    ]}
                ]
            },
            {
                title : {text: ‘2011全国宏观经济指标’},
                series : [
                    {data: dataMap.dataGDP[‘2011’]},
                    {data: dataMap.dataFinancial[‘2011’]},
                    {data: dataMap.dataEstate[‘2011’]},
                    {data: dataMap.dataPI[‘2011’]},
                    {data: dataMap.dataSI[‘2011’]},
                    {data: dataMap.dataTI[‘2011’]},
                    {data: [
                        {name: ‘第一产业’, value: dataMap.dataPI[‘2011sum’]},
                        {name: ‘第二产业’, value: dataMap.dataSI[‘2011sum’]},
                        {name: ‘第三产业’, value: dataMap.dataTI[‘2011sum’]}
                    ]}
                ]
            }
        ]
    };

    myChart.setOption(option);

});

尝试一下 »


本文来源于互联网:ECharts 响应式

Linux gpasswd 命令

Linux gpasswd 命令

Linux gpasswd 命令 Linux 命令大全

Linux passwd 是 Linux 下工作组文件 /etc/group 和 /etc/gshadow 管理工具,用于将一个用户添加到组或者从组中删除。

语法

gpasswd [可选项] 组名

可选项参数

  • -a:添加用户到组;
  • -d:从组删除用户;
  • -A:指定管理员;
  • -M:指定组成员和-A的用途差不多;
  • -r:删除密码;
  • -R:限制用户登入组,只有组中的成员才可以用newgrp加入该组。

实例

如系统有个 peter 账户,该账户本身不是 groupname 群组的成员,使用 newgrp 需要输入密码即可。

gpasswd groupname

让使用者暂时加入成为该组成员,之后 peter 建立的文件 group 也会是 groupname。所以该方式可以暂时让 peter 建立文件时使用其他的组,而不是 peter 本身所在的组。

所以使用 gpasswd groupname 设定密码,就是让知道该群组密码的人可以暂时切换具备 groupname 群组功能的。

gpasswd -A peter users

这样 peter 就是 users 群组的管理员,就可以执行下面的操作:

gpasswd -a mary users
gpasswd -a allen users

注意:添加用户到某一个组 可以使用 usermod -G group_name user_name 这个命令可以添加一个用户到指定的组,但是以前添加的组就会清空掉。

所以想要添加一个用户到一个组,同时保留以前添加的组时,请使用 gpasswd 这个命令来添加操作用户:

gpasswd -a user_name group_name

Linux gpasswd 命令 Linux 命令大全


本文来源于互联网:Linux gpasswd 命令

Linux 云服务器

Linux 云服务器

自己安装服务器还是麻烦了些,现在一般都推荐大家使用云服务器,比较方便,价格也不贵。

目前市场上的云服务器很多,这边比较下腾讯云跟阿里云的服务器优惠活动,现在看来腾讯云性价比会高一些。


腾讯云

年末腾讯云活动已开始,以下几款性价比非常高,有几款是需要抢购的,大家看好时间基本能拿到。

  • 1、1核2G 128/年,可以用来学习,Linux 知识对技术人员的成才非常重要。
  • 2、2核4G 368/年。
  • 3、另外还有香港的服务器,如果做网站不想去备案,可以考虑,香港速度还是很快的。

每个时间点都有不同的配置跟价格,具体信息,可以点击下面的图片:

Linux 云服务器

另外企业用户还有更高配置的,价格也很实惠:

Linux 云服务器


腾讯云服务器使用

本章节以腾讯云服务器为例。

1、首先点击下图购买(更多服务器的配置信息见下文):

Linux 云服务器

2、登陆腾讯云控制台,查看已购买的服务器:

Linux 云服务器

3、在使用腾讯云服务器前,我们需要先创建一个 SSH 密钥,点击左侧的 SSH 密钥 (使用密钥登录比密码更安全):

Linux 云服务器

输入密钥名称,然后点击确定,就会自动生成一个密钥,密钥会自动下载到本地,请保存好下载的密钥,密钥文件名就是你输入的密钥名称。

4、接着我们勾选已经创建的密钥,点击 绑定/解绑实例 按钮,弹窗中会出现我们的 ECS 服务器,将其绑定到这个密钥即可:

Linux 云服务器

5、返回实例列表,点击实例右侧的 登录 按钮,弹窗中点击立即登录,这是会弹出一个新的浏览器窗口,我们选择密钥登录,密钥文件就是在第三个步骤创建的:

Linux 云服务器

Linux 云服务器

Linux 云服务器

当然你可以选择第三方客户端登录(如:SecureCRT),用户名为 ubuntu,其他系统估计略有不同,然后导入对应的 key 即可。


本文来源于互联网:Linux 云服务器

HTML main 标签

HTML main 标签

实例

使用 main 标签来展示文档的主体部分:

<main>
<h1>Web 浏览器</h1>
<p>Google Chrome、Firefox 以及 Internet Explorer 是目前最流行的浏览器。</p>

<article>
<h1>Google Chrome 浏览器</h1>
<p>Google Chrome 浏览器是由 Google 开发的一款免费的开源 web 浏览器,于 2008 年发布。</p>
</article>

<article>
<h1>Internet Explorer 浏览器</h1>
<p>Internet Explorer 浏览器由微软开发的一款免费的 web 浏览器,发布于 1995 年。</p>
</article>

<article>
<h1>Mozilla Firefox 浏览器</h1>
<p>Firefox 浏览器是一款来自 Mozilla 的免费开源 web 浏览器,发布于 2004 年。</p>
</article>
</main>

尝试一下 »


定义和用法

<main> 标签用于指定文档的主体内容。

<main> 标签中的内容在文档中是唯一的。它不应包含在文档中重复出现的内容,比如侧栏、导航栏、版权信息、站点标志或搜索表单。

注意在一个文档中,<main> 元素是唯一的,所以不能出现一个以上的 <main> 元素。<main> 元素不能是以下元素的后代:<article>、<aside>、<footer>、<header> 或 <nav>。


浏览器支持

表格中的数字表示支持该元素的第一个浏览器版本号。

元素
<main> 6.0 12.0 4.0 5.0 11.1

HTML 4.01 与 HTML5之间的差异

<main> 标签是 HTML5 中新增加的。


本文来源于互联网:HTML main 标签

HTML main 标签

HTML main 标签

实例

使用 main 标签来展示文档的主体部分:

<main>
<h1>Web 浏览器</h1>
<p>Google Chrome、Firefox 以及 Internet Explorer 是目前最流行的浏览器。</p>

<article>
<h1>Google Chrome 浏览器</h1>
<p>Google Chrome 浏览器是由 Google 开发的一款免费的开源 web 浏览器,于 2008 年发布。</p>
</article>

<article>
<h1>Internet Explorer 浏览器</h1>
<p>Internet Explorer 浏览器由微软开发的一款免费的 web 浏览器,发布于 1995 年。</p>
</article>

<article>
<h1>Mozilla Firefox 浏览器</h1>
<p>Firefox 浏览器是一款来自 Mozilla 的免费开源 web 浏览器,发布于 2004 年。</p>
</article>
</main>

尝试一下 »


定义和用法

<main> 标签用于指定文档的主体内容。

<main> 标签中的内容在文档中是唯一的。它不应包含在文档中重复出现的内容,比如侧栏、导航栏、版权信息、站点标志或搜索表单。

注意在一个文档中,<main> 元素是唯一的,所以不能出现一个以上的 <main> 元素。<main> 元素不能是以下元素的后代:<article>、<aside>、<footer>、<header> 或 <nav>。


浏览器支持

表格中的数字表示支持该元素的第一个浏览器版本号。

元素
<main> 6.0 12.0 4.0 5.0 11.1

HTML 4.01 与 HTML5之间的差异

<main> 标签是 HTML5 中新增加的。


本文来源于互联网:HTML main 标签

JSON vs XML

JSON vs XML

JSON 和 XML 都用于接收 web 服务端的数据。

JSON 和 XML在写法上有所不同,如下所示:

JSON 实例

{
sites: [
{ name:菜鸟教程 , url:www.runoob.com },
{ name:google , url:www.google.com },
{ name:微博 , url:www.weibo.com }
]
}

XML 实例

<sites>
<site>
<name>菜鸟教程</name> <url>www.runoob.com</url>
</site>
<site>
<name>google</name> <url>www.google.com</url>
</site>
<site>
<name>微博</name> <url>www.weibo.com</url>
</site>
</sites>

JSON 与 XML 的相同之处:

  • JSON 和 XML 数据都是 “自我描述” ,都易于理解。
  • JSON 和 XML 数据都是有层次的结构
  • JSON 和 XML 数据可以被大多数编程语言使用

JSON 与 XML 的不同之处:

  • JSON 不需要结束标签
  • JSON 更加简短
  • JSON 读写速度更快
  • JSON 可以使用数组

最大的不同是:XML 需要使用 XML 解析器来解析,JSON 可以使用标准的 JavaScript 函数来解析。


为什么 JSON 比 XML 更好?

XML 比 JSON 更难解析。

JSON 可以直接使用现有的 JavaScript 对象解析。

针对 AJAX 应用,JSON 比 XML 数据加载更快,而且更简单:

使用 XML

  • 获取 XML 文档
  • 使用 XML DOM 迭代循环文档
  • 接数据解析出来复制给变量

使用 JSON

  • 获取 JSON 字符串
  • JSON.Parse 解析 JSON 字符串

相关文章


本文来源于互联网:JSON vs XML

JSON vs XML

JSON vs XML

JSON 和 XML 都用于接收 web 服务端的数据。

JSON 和 XML在写法上有所不同,如下所示:

JSON 实例

{
sites: [
{ name:菜鸟教程 , url:www.runoob.com },
{ name:google , url:www.google.com },
{ name:微博 , url:www.weibo.com }
]
}

XML 实例

<sites>
<site>
<name>菜鸟教程</name> <url>www.runoob.com</url>
</site>
<site>
<name>google</name> <url>www.google.com</url>
</site>
<site>
<name>微博</name> <url>www.weibo.com</url>
</site>
</sites>

JSON 与 XML 的相同之处:

  • JSON 和 XML 数据都是 “自我描述” ,都易于理解。
  • JSON 和 XML 数据都是有层次的结构
  • JSON 和 XML 数据可以被大多数编程语言使用

JSON 与 XML 的不同之处:

  • JSON 不需要结束标签
  • JSON 更加简短
  • JSON 读写速度更快
  • JSON 可以使用数组

最大的不同是:XML 需要使用 XML 解析器来解析,JSON 可以使用标准的 JavaScript 函数来解析。


为什么 JSON 比 XML 更好?

XML 比 JSON 更难解析。

JSON 可以直接使用现有的 JavaScript 对象解析。

针对 AJAX 应用,JSON 比 XML 数据加载更快,而且更简单:

使用 XML

  • 获取 XML 文档
  • 使用 XML DOM 迭代循环文档
  • 接数据解析出来复制给变量

使用 JSON

  • 获取 JSON 字符串
  • JSON.Parse 解析 JSON 字符串

相关文章


本文来源于互联网:JSON vs XML

SQL EXISTS 运算符

SQL EXISTS 运算符


EXISTS 运算符

EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。

SQL EXISTS 语法

SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);


演示数据库

在本教程中,我们将使用 RUNOOB 样本数据库。

下面是选自 “Websites” 表的数据:

+----+--------------+---------------------------+-------+---------+
| id | name         | url                       | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1  | Google       | https://www.google.cm/    | 1     | USA     |
| 2  | 淘宝       | https://www.taobao.com/   | 13    | CN      |
| 3  | 菜鸟教程 | http://www.runoob.com/    | 4689  | CN      |
| 4  | 微博       | http://weibo.com/         | 20    | CN      |
| 5  | Facebook     | https://www.facebook.com/ | 3     | USA     |
+----+--------------+---------------------------+-------+---------+

下面是 “access_log” 网站访问记录表的数据:

mysql> SELECT * FROM access_log;
+-----+---------+-------+------------+
| aid | site_id | count | date       |
+-----+---------+-------+------------+
|   1 |       1 |    45 | 2016-05-10 |
|   2 |       3 |   100 | 2016-05-13 |
|   3 |       1 |   230 | 2016-05-14 |
|   4 |       2 |    10 | 2016-05-14 |
|   5 |       5 |   205 | 2016-05-14 |
|   6 |       4 |    13 | 2016-05-15 |
|   7 |       3 |   220 | 2016-05-15 |
|   8 |       5 |   545 | 2016-05-16 |
|   9 |       3 |   201 | 2016-05-17 |
+-----+---------+-------+------------+
9 rows in set (0.00 sec)


SQL EXISTS 实例

现在我们想要查找总访问量大于 200 的网站是否存在。

我们使用下面的 SQL 语句:

实例

SELECT Websites.name, Websites.url
FROM Websites
WHERE EXISTS (SELECT count FROM access_log WHERE Websites.id = access_log.site_id AND count > 200);

执行以上 SQL 输出结果如下:

SQL EXISTS 运算符

EXISTS 可以与 NOT 一同使用,查找出不符合查询语句的记录:

实例

SELECT Websites.name, Websites.url
FROM Websites
WHERE NOT EXISTS (SELECT count FROM access_log WHERE Websites.id = access_log.site_id AND count > 200);

执行以上 SQL 输出结果如下:

SQL EXISTS 运算符


本文来源于互联网:SQL EXISTS 运算符

MassDNS:一款功能强大的高性能DNS子域名查询枚举侦察工具

MassDNS:一款功能强大的高性能DNS子域名查询枚举侦察工具

MassDNS是一款功能强大的高性能DNS stub解析工具,它可以帮助研究人员解析数百万甚至上亿个域名。在没有特殊配置的情况下,MassDNS可以利用公共可用的解析器每秒钟解析超过350000个域名。

项目编译

首先,使用下列命令将MassDNS源码克隆至本地目录中:

git clone https://github.com/blechschmidt/massdns.git

使用cd命令切换到本地项目目录中:

cd massdns

接下来,运行”make”命令构建源码。

如果你使用的不是Linux操作系统,那么则需要运行下列命令:

make nolinux

在Windows平台下,你还需要安装Cygwin包、gcc-core、git和make。

工具使用

Usage: ./bin/massdns [options] [domainlist]

  -b  --bindto           Bind to IP address and port. (Default: 0.0.0.0:0)

      --busy-poll        Use busy-wait polling instead of epoll.

  -c  --resolve-count    Number of resolves for a name before giving up. (Default: 50)

      --drop-group       Group to drop privileges to when running as root. (Default: nogroup)

      --drop-user        User to drop privileges to when running as root. (Default: nobody)

      --flush            Flush the output file whenever a response was received.

  -h  --help             Show this help.

  -i  --interval         Interval in milliseconds to wait between multiple resolves of the same

                         domain. (Default: 500)

  -l  --error-log        Error log file path. (Default: /dev/stderr)

      --norecurse        Use non-recursive queries. Useful for DNS cache snooping.

  -o  --output           Flags for output formatting.

      --predictable      Use resolvers incrementally. Useful for resolver tests.

      --processes        Number of processes to be used for resolving. (Default: 1)

  -q  --quiet            Quiet mode.

      --rcvbuf           Size of the receive buffer in bytes.

      --retry            Unacceptable DNS response codes. (Default: REFUSED)

  -r  --resolvers        Text file containing DNS resolvers.

      --root             Do not drop privileges when running as root. Not recommended.

  -s  --hashmap-size     Number of concurrent lookups. (Default: 10000)

      --sndbuf           Size of the send buffer in bytes.

      --sticky           Do not switch the resolver when retrying.

      --socket-count     Socket count per process. (Default: 1)

  -t  --type             Record type to be resolved. (Default: A)

      --verify-ip        Verify IP addresses of incoming replies.

  -w  --outfile          Write to the specified output file instead of standard output.

Output flags:

  S - simple text output

  F - full text output

  B - binary output

  J - ndjson output

如果你需要查看更详细的操作选项以及帮助手册(尤其是输出格式),你可以使用“–help”命令。

工具使用样例

解析目标域名(位于lists的resolvers.txt中)的AAAA记录,并将结果存储至result.txt中:

$ ./bin/massdns -r lists/resolvers.txt -t AAAA domains.txt > results.txt

或者运行下列命令:

$ ./bin/massdns -r lists/resolvers.txt -t AAAA -w results.txt domains.txt

样本输出

默认配置下,MassDNS将会输出响应数据包,格式为文本格式,输出样例如下:

;; Server: 77.41.229.2:53

;; Size: 93

;; Unix time: 1513458347

;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 51298

;; flags: qr rd ra ; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 0

;; QUESTION SECTION:

example.com. IN A

;; ANSWER SECTION:

example.com. 45929 IN A 93.184.216.34

;; AUTHORITY SECTION:

example.com. 24852 IN NS b.iana-servers.net.

example.com. 24852 IN NS a.iana-servers.net.

输出结果包含了解析的IP地址,可以帮助我们轻松对输出结果进行过滤。

数据解析

代码库中包含了一个名为resolvers.txt的文件,其中包含了一套有subbrute项目提供的已过滤的解析器子集。请注意,MassDNS的使用可能会提升系统/网络负载,因为需要加载大量解析器,具体将取决于你的ISP。

MassDNS的DNS解析实现目前还不完整,只支持最常见的一些记录类型。欢迎您通过代码贡献来帮助改变这种状况。

PTR记录

MassDNS包含了一个Python脚本,允许我们解析所有的IPv4 PTR记录:

$ ./scripts/ptr.py | ./bin/massdns -r lists/resolvers.txt -t PTR -w ptr.txt

请注意,in-addr.arpa中的标签会被反转。为了解析域名为1.2.3.4的地址,MassDNS将需要以“4.3.2.1.in-addr.arpa”的方式来作为输入查询名称。此时,Python脚本并不会按升序解析记录,这样可以避免在IP v4子网的域名服务器上突然出现的负载激增。

网络侦察&爆破子域名

注意:请不要随意使用该工具,适当调整-s参数以避免给权威域名服务器造成负载压力。

subbrute类似,MassDNS允许我们使用subbrute.py脚本来对子域名进行爆破枚举:

$ ./scripts/subbrute.py lists/names.txt example.com | ./bin/massdns -r lists/resolvers.txt -t A -o S -w results.txt

作为一种额外的网络侦察手段,ct.py脚本可以从crt.sh中抓取数据,并从证书透明日志中提取子域名:

$ ./scripts/ct.py example.com | ./bin/massdns -r lists/resolvers.txt -t A -o S -w results.txt

工具运行截图

MassDNS:一款功能强大的高性能DNS子域名查询枚举侦察工具

安全性

MassDNS的运行不需要Root权限, 我们建议用户以非特权用户的身份运行MassDNS。除此之外,我们不建议大家使用“–root”参数来运行。另外,除了Master以外的其他分支不适用于生产环境。

项目地址

MassDNS:【GitHub传送门

* 参考来源:blechschmidt,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

本文来源于互联网:MassDNS:一款功能强大的高性能DNS子域名查询枚举侦察工具

See-SURF:一款基于Python的潜在SSRF参数扫描工具

See-SURF:一款基于Python的潜在SSRF参数扫描工具

See-SURF

See-SURF是一款基于Python开发的扫描工具,它可以帮助安全研究人员查找并发现目标Web应用程序中潜在的SSRF参数。

SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF是要目标网站的内部系统。(因为他是从内部系统访问的,所有可以通过它攻击外网无法访问的内部系统,也就是把目标网站当中间人)

SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,文档,等等。

在Web安全领域中,SSRF毫无疑问已经成为了一种严重的安全漏洞,但是行业内貌似我没看到有工具能够自动查找这种类型漏洞参数的工具。因此,See-SURF便应运而生,它可以帮助我们在进行漏洞搜索或Web安全测试时,提供很大的帮助。

工具依赖

Python 3

功能介绍

1、可以接收Burp的sitemap作为输入,并使用强大的正则表达式匹配语句来解析文件,并匹配任何包含了潜在SSRF漏洞关键词的GET/POST URL参数,比如说URL或站点信息等等。除此之外,它还可以检测任意URL或IP地址中的参数值。下面给出的是可分析的样本GET请求:

google.com/url=https://yahoo.com

google.com/q=https://yahoo.com

FORMS –

<input type="text" name="url" value="https://google.com" placeholder="https://msn.com">

2、内置多线程网络爬虫,能够尽可能多地收集数据,并解析和识别潜在的SSRF参数。

3、提供了cookie以便支持认证扫描。

4、默认配置下,工具已常规模式运行,开启Verbose模式后,我们将能够查看到不同终端节点的各种漏洞参数。样例如下:

https://google.com/path/1/urlToConnect=https://yahoo.com

https://google.com/differentpath/urlToConnect=https://yahoo.com

5、漏洞利用:向Burp Collaboraor或其他HTTP服务器发送包含漏洞参数的外部请求,以确认SSRF漏洞的有效性。

工具安装

git clonehttps://github.com/In3tinct/See-SURF.git

cd See-SURF/

pip3 install BeautifulSoup4

pip3 install requests

工具使用

下面这条命令将以默认线程=10的配置运行See-SURF,未开启cookie/session,未开启Verbose模式:

python3 see-surf.py -H https://www.google.com

提供Cookie,以空格隔开,实现认证会话爬取:

python3 see-surf.py -H https://www.google.com -c cookie_name1=value1 cookie_name2=value2

开启Verbose模式,设置Cookie:

python3 see-surf.py -H https://www.google.com -c cookie_name1=value1 cookie_name2=value2 -t 20 -v

其他使用样例:

https://google.com/abc/1/urlToConnect=https://yahoo.com

https://google.com/123/urlToConnect=https://yahoo.com

Burp使用样例

Burp Sitemap(-b和-p)

完整的命令样例:

python3 see-surf.py -H https://www.google.com -c cookie_name1=value1 cookie_name2=value2 -b burp_file.xml -p http://72.72.72.72:8000

-b参数可以提供Burp Sitemap文件,以便更好地发现潜在的SSRF参数。这个脚本首先回解析Burp文件,并尝试查找潜在的参数,然后针对目标运行内置的爬虫。

在BurpSuite中查看待分析目标,发送某些GET/POST请求,数量越多越好。然后点击“Target”标签,右键点击“Save selected Items”,然后保存。提供的脚本运行参数如下:

python3 see-surf.py -H https://www.google.com -c cookie_name1=value1 cookie_name2=value2 -b burp_file.xml

See-SURF:一款基于Python的潜在SSRF参数扫描工具

-p参数将会开启BurpSuite Collaborator,并向主机传递-p参数,或者开启一个Python Http服务器,并等待漏洞参数以执行请求。此时,Payload将会带参数执行,参考样例如下:

python3 see-surf.py -H https://www.google.com -c cookie_name1=value1 cookie_name2=value2 -p http://72.72.72.72:8000

See-SURF:一款基于Python的潜在SSRF参数扫描工具

工具运行截图

See-SURF:一款基于Python的潜在SSRF参数扫描工具

许可证协议

See-SURF的开发与发布遵循GNU v3开源许可证协议。

项目地址

See-SURF:【GitHub传送门

* 参考来源:In3tinct,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM

本文来源于互联网:See-SURF:一款基于Python的潜在SSRF参数扫描工具