在前面两篇文章中详细介绍了pptp vpn的安装与使用,以及如何配置用户认证存入mysql数据库。本文将在前面两篇文章的基础上介绍如何对用户的流量做限制,同时限制相同账号的用户,同一时刻的在线数为1。

前文传送门地址:

PPTP-VPN部署与简单使用   http://ylw6006.blog.51cto.com/470441/1794577

PPTP-VPN使用mysql进行用户登录认证 http://ylw6006.blog.51cto.com/470441/1795201

一、向mysql库表中插入基础数据

1
2
3
4
5
6
7
8
mysql> use radius
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Auth-Type',':=','Local'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Service-Type',':=','Framed-User'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Address',':=','255.255.255.255'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Framed-IP-Netmask',':=','255.255.255.0'); 
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Acct-Interim-Interval',':=','600');
mysql> INSERT INTO radgroupreply (groupname,attribute,op,VALUE) VALUES ('user','Max-Monthly-Traffic',':=','20480'); 
mysql> INSERT INTO radgroupcheck (groupname,attribute,op,VALUE) VALUES ('user','Simultaneous-Use',':=','1');

acct-interim-interval是计算流量的间隔(600秒),意味着每隔10分钟记录当前流量;

Max-Monthly-Traffic是每月最大流量,这里是20G(单位是M);

radgroupcheck表的Simultaneous-Use表示单个用户的同时连接数目;

这里要格外注意的是,许多网络上的文章介绍Max-Monthly-Traffic单位为字节,数值为5368709102,换算一下大概5G左右,而如果我们也精确到字节,数值设为20G,也就是21474836480,则用户拨入进行身份验证的时候将会报错。因而此次我们将流量限制的精度单位修改为M。详细可参考如下链接介绍:http://www.xj123.info/2856.html

二、修改配置文件

1、修改/etc/raddb/sites-enabled/default文件,添加流量限制的reject条件

1
2
3
4
5
6
7
8
# vi  /etc/raddb/sites-enabled/default 
#找到authorize一节插入如下内容:
update request { 
    Group-Name := "%{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority}" 
    
    if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") { 
    reject 
    }

2、由于使用了非内置的attribute Max-Monthly-Traffic,所以需要在/etc/raddb/dictionary里面定义

1
2
# tail -1 /etc/raddb/dictionary 
ATTRIBUTE       Max-Monthly-Traffic     3003    integer

3、修改/etc/raddb/sql/mysql/dialup.conf文件,开启在线用户数检查

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# vi  /etc/raddb/sql/mysql/dialup.conf 
sql_user_name = "%{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}}"
#sql_user_name = "%{User-Name}"  #注释掉这行
  
# Uncomment simul_count_query to enable simultaneous use checking 
        simul_count_query = "SELECT COUNT(*) \
                             FROM ${acct_table1} \
                             WHERE username = '%{SQL-User-Name}' \
                             AND acctstoptime IS NULL"
  
        simul_verify_query  = "SELECT radacctid, acctsessionid, username, \
                               nasipaddress, nasportid, framedipaddress, \
                               callingstationid, framedprotocol \
                               FROM ${acct_table1} \
                               WHERE username = '%{SQL-User-Name}' \
                               AND acctstoptime IS NULL"

三、重启服务

# /etc/init.d/radiusd stop

# /etc/init.d/pptpd restart

四、测试

1、将rediusd服务运行在debug模式下,进行拨号测试,主要测试流量控制!

#radiusd -X

通过上面可以看到当前的用户流量消耗为2M,限制流量的值为20480M。

因而在/etc/raddb/sites-enabled/default文件,判断流量限制的reject条件的结果为false,用户可以通过验证,完成拨号!下面是详细的拨号日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
rad_recv: Access-Request packet from host 127.0.0.1 port 49226, id=94, length=150
        Service-Type = Framed-User
        Framed-Protocol = PPP
        User-Name = "ptest1"
        MS-CHAP-Challenge = 0x6716c32940f1c84ad213d2d52df1712d
        MS-CHAP2-Response = 0x2400c77c090296803fb3c0822b8c679547f000000000000000001eb41fe8e518c1f756fb5d9d5904ddb8dc1fe271e98aa055
        Calling-Station-Id = "27.151.123.121"
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 0
# Executing section authorize from file /etc/raddb/sites-enabled/default
+group authorize {
++update request {
sql_xlat
        expand: %{Stripped-User-Name} -> 
        ... expanding second conditional
        expand: %{User-Name} -> ptest1
        expand: %{%{User-Name}:-DEFAULT} -> ptest1
        expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
sql_set_user escaped user --> 'ptest1'
        expand: SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority -> SELECT groupname FROM radusergroup WHERE username='ptest1' ORDER BY priority
rlm_sql (sql): Reserving sql socket id: 30
sql_xlat finished
rlm_sql (sql): Released sql socket id: 30
        expand: %{sql:SELECT groupname FROM radusergroup WHERE username='%{User-Name}' ORDER BY priority} -> user
++} # update request = noop
++? if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}")
sql_xlat
        expand: %{Stripped-User-Name} -> 
        ... expanding second conditional
        expand: %{User-Name} -> ptest1
        expand: %{%{User-Name}:-DEFAULT} -> ptest1
        expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
sql_set_user escaped user --> 'ptest1'
        expand:  SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now()); ->  SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='ptest1' AND date_format(acctstarttime, '2016-06-30') >= date_format(now(),'2016-06-01') AND date_format(acctstoptime, '2016-06-30') <= last_day(now());
rlm_sql (sql): Reserving sql socket id: 29
sql_xlat finished
rlm_sql (sql): Released sql socket id: 29
        expand: %{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());} -> 2
sql_xlat
        expand: %{Stripped-User-Name} -> 
        ... expanding second conditional
        expand: %{User-Name} -> ptest1
        expand: %{%{User-Name}:-DEFAULT} -> ptest1
        expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
sql_set_user escaped user --> 'ptest1'
        expand:  SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic'; ->  SELECT value FROM radgroupreply WHERE groupname='user' AND attribute='Max-Monthly-Traffic';
rlm_sql (sql): Reserving sql socket id: 28
sql_xlat finished
rlm_sql (sql): Released sql socket id: 28
        expand: %{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';} -> 20480
? Evaluating ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") -> FALSE
++? if ("%{sql: SELECT SUM(acctinputoctets+acctoutputoctets) div 1048576 FROM radacct WHERE username='%{User-Name}' AND date_format(acctstarttime, '%Y-%m-%d') >= date_format(now(),'%Y-%m-01') AND date_format(acctstoptime, '%Y-%m-%d') <= last_day(now());}" >= "%{sql: SELECT value FROM radgroupreply WHERE groupname='%{Group-Name}' AND attribute='Max-Monthly-Traffic';}") -> FALSE
++[preprocess] = ok
++[chap] = noop
[mschap] Found MS-CHAP attributes.  Setting 'Auth-Type  = mschap'
++[mschap] = ok
++[digest] = noop
[suffix] No '@' in User-Name = "ptest1", looking up realm NULL
[suffix] No such realm "NULL"
++[suffix] = noop
[eap] No EAP-Message, not doing EAP
++[eap] = noop
[sql]   expand: %{Stripped-User-Name} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{User-Name} -> ptest1
[sql]   expand: %{%{User-Name}:-DEFAULT} -> ptest1
[sql]   expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
[sql] sql_set_user escaped user --> 'ptest1'
rlm_sql (sql): Reserving sql socket id: 27
[sql]   expand: SELECT id, username, attribute, value, op           FROM radcheck           WHERE username = '%{SQL-User-Name}'           ORDER BY id -> SELECT id, username, attribute, value, op           FROM radcheck           WHERE username = 'ptest1'           ORDER BY id
WARNING: Found User-Password == "...".
WARNING: Are you sure you don't mean Cleartext-Password?
WARNING: See "man rlm_pap" for more information.
[sql] User found in radcheck table
[sql]   expand: SELECT id, username, attribute, value, op           FROM radreply           WHERE username = '%{SQL-User-Name}'           ORDER BY id -> SELECT id, username, attribute, value, op           FROM radreply           WHERE username = 'ptest1'           ORDER BY id
[sql]   expand: SELECT groupname           FROM radusergroup           WHERE username = '%{SQL-User-Name}'           ORDER BY priority -> SELECT groupname           FROM radusergroup           WHERE username = 'ptest1'           ORDER BY priority
[sql]   expand: SELECT id, groupname, attribute,           Value, op           FROM radgroupcheck           WHERE groupname = '%{Sql-Group}'           ORDER BY id -> SELECT id, groupname, attribute,           Value, op           FROM radgroupcheck           WHERE groupname = 'user'           ORDER BY id
[sql] User found in group user
[sql]   expand: SELECT id, groupname, attribute,           value, op           FROM radgroupreply           WHERE groupname = '%{Sql-Group}'           ORDER BY id -> SELECT id, groupname, attribute,           value, op           FROM radgroupreply           WHERE groupname = 'user'           ORDER BY id
rlm_sql (sql): Released sql socket id: 27
++[sql] = ok
++[expiration] = noop
++[logintime] = noop
[pap] WARNING: Auth-Type already set.  Not setting to PAP
++[pap] = noop
+} # group authorize = ok
Found Auth-Type = MSCHAP
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!    Replacing User-Password in config items with Cleartext-Password.     !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! Please update your configuration so that the "known good"               !!!
!!! clear text password is in Cleartext-Password, and not in User-Password. !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# Executing group from file /etc/raddb/sites-enabled/default
+group MS-CHAP {
[mschap] Creating challenge hash with username: ptest1
[mschap] Client is using MS-CHAPv2 for ptest1, we need NT-Password
[mschap] adding MS-CHAPv2 MPPE keys
++[mschap] = ok
+} # group MS-CHAP = ok
# Executing section session from file /etc/raddb/sites-enabled/default
+group session {
[radutmp]       expand: /var/log/radius/radutmp -> /var/log/radius/radutmp
++[radutmp] = ok
+} # group session = ok
# Executing section post-auth from file /etc/raddb/sites-enabled/default
+group post-auth {
[sql]   expand: %{Stripped-User-Name} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{User-Name} -> ptest1
[sql]   expand: %{%{User-Name}:-DEFAULT} -> ptest1
[sql]   expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
[sql] sql_set_user escaped user --> 'ptest1'
[sql]   expand: %{User-Password} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{Chap-Password} -> 
[sql]   expand: INSERT INTO radpostauth                           (username, pass, reply, authdate)                           VALUES (                           '%{User-Name}',                           '%{%{User-Password}:-%{Chap-Password}}',                           '%{reply:Packet-Type}', '%S') -> INSERT INTO radpostauth                           (username, pass, reply, authdate)                           VALUES (                           'ptest1',                           '',                           'Access-Accept', '2016-06-30 13:05:14')
rlm_sql (sql) in sql_postauth: query is INSERT INTO radpostauth                           (username, pass, reply, authdate)                           VALUES (                           'ptest1',                           '',                           'Access-Accept', '2016-06-30 13:05:14')
rlm_sql (sql): Reserving sql socket id: 26
rlm_sql (sql): Released sql socket id: 26
++[sql] = ok
++[exec] = noop
+} # group post-auth = ok
Sending Access-Accept of id 94 to 127.0.0.1 port 49226
        Service-Type := Framed-User
        Framed-IP-Address := 255.255.255.255
        Framed-IP-Netmask := 255.255.255.0
        Acct-Interim-Interval := 600
        MS-CHAP2-Success = 0x24533d46303044303641413737333432343231363234364143413245333041373133433531344439353037
        MS-MPPE-Recv-Key = 0x3373da01475488084e5f82abae7cbda8
        MS-MPPE-Send-Key = 0xdb408d5d7f18d9fd38e6c1888b8c0b13
        MS-MPPE-Encryption-Policy = 0x00000001
        MS-MPPE-Encryption-Types = 0x00000006
Finished request 0.
Going to the next request
Waking up in 4.9 seconds.
Cleaning up request 0 ID 94 with timestamp +88
Ready to process requests.
rad_recv: Accounting-Request packet from host 127.0.0.1 port 58801, id=95, length=114
        Acct-Session-Id = "5774A890092400"
        User-Name = "ptest1"
        Acct-Status-Type = Start
        Service-Type = Framed-User
        Framed-Protocol = PPP
        Calling-Station-Id = "27.151.123.121"
        Acct-Authentic = RADIUS
        NAS-Port-Type = Async
        Framed-IP-Address = 192.168.222.10
        NAS-IP-Address = 127.0.0.1
        NAS-Port = 0
        Acct-Delay-Time = 0
# Executing section preacct from file /etc/raddb/sites-enabled/default
+group preacct {
++[preprocess] = ok
[acct_unique] WARNING: Attribute NAS-Identifier was not found in request, unique ID MAY be inconsistent
[acct_unique] Hashing 'NAS-Port = 0,,NAS-IP-Address = 127.0.0.1,Acct-Session-Id = "5774A890092400",User-Name = "ptest1"'
[acct_unique] Acct-Unique-Session-ID = "413ac0cc5b5f4759".
++[acct_unique] = ok
[suffix] No '@' in User-Name = "ptest1", looking up realm NULL
[suffix] No such realm "NULL"
++[suffix] = noop
+} # group preacct = ok
# Executing section accounting from file /etc/raddb/sites-enabled/default
+group accounting {
[detail]        expand: %{Packet-Src-IP-Address} -> 127.0.0.1
[detail]        expand: /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d -> /var/log/radius/radacct/127.0.0.1/detail-20160630
[detail] /var/log/radius/radacct/%{%{Packet-Src-IP-Address}:-%{Packet-Src-IPv6-Address}}/detail-%Y%m%d expands to /var/log/radius/radacct/127.0.0.1/detail-20160630
[detail]        expand: %t -> Thu Jun 30 13:05:20 2016
++[detail] = ok
[sql]   expand: %{Stripped-User-Name} -> 
[sql]   ... expanding second conditional
[sql]   expand: %{User-Name} -> ptest1
[sql]   expand: %{%{User-Name}:-DEFAULT} -> ptest1
[sql]   expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-DEFAULT}} -> ptest1
[sql] sql_set_user escaped user --> 'ptest1'
[sql]   expand: %{Acct-Delay-Time} -> 0
[sql]   expand:            INSERT INTO radacct             (acctsessionid,    acctuniqueid,     username,              realm,            nasipaddress,     nasportid,              nasporttype,      acctstarttime,    acctstoptime,              acctsessiontime,  acctauthentic,    connectinfo_start,              connectinfo_stop, acctinputoctets,  acctoutputoctets,              calledstationid,  callingstationid, acctterminatecause,              servicetype,      framedprotocol,   framedipaddress,              acctstartdelay,   acctstopdelay,    xascendsessionsvrkey)           VALUES             ('%{Acct-Session-Id}', '%{Acct-Unique-Session-Id}',              '%{SQL-User-Name}',              '%{Realm}', '%{NAS-IP-Address}', '%{NAS-Port}',              '%{NAS-Port-Type}', '%S', NULL,              '0', '%{Acct-Authentic}', '%{Connect-Info}',              '', '0', '0',              '%{Called-Station-Id}', '%{Calling-Station-Id}', '',              '%{Service-Type}', '%{Framed-Protocol}', '%{Framed-IP-Address}',      
rlm_sql (sql): Reserving sql socket id: 25
rlm_sql (sql): Released sql socket id: 25
++[sql] = ok
++[exec] = noop
[attr_filter.accounting_response]       expand: %{User-Name} -> ptest1
attr_filter: Matched entry DEFAULT at line 12
++[attr_filter.accounting_response] = updated
+} # group accounting = updated
Sending Accounting-Response of id 95 to 127.0.0.1 port 58801
Finished request 1.
Cleaning up request 1 ID 95 with timestamp +94
Going to the next request
Ready to process requests.

2、测试同一个VPN账号,多终端登录

通过如下sql语句可以看到当前用户的拨号连接情况,很明显通过前面的配置,并没有起到限制的效果。

1
2
mysql> SELECT radacctid, acctsessionid, username,nasipaddress, nasportid, framedipaddress, callingstationid, framedprotocol FROM  radacct WHERE username ='yang' AND acctstoptime IS NULL;
mysql> SELECT COUNT(*) from radacct WHERE username ='yang' AND acctstoptime IS NULL;

通过修改/etc/raddb/sites-enabled/default文件,注释掉session节的radutmp配置,重启radiusd服务后测试,发现效果符合预期

# vi /etc/raddb/sites-enabled/default

同一个账号的第二个拨号连接就会直接提示验证失败!

PPTP-VPN第三章——用户流量与并发数限制的更多相关文章

  1. (转)iOS Wow体验 - 第三章 - 用户体验的差异化策略

    本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第三章译文精选,其余章节将陆续放出.上一篇:Wow ...

  2. Testlink1.9.17使用方法( 第三章 初始配置[配置用户、产品] )

    第三章 初始配置(配置用户.产品) 一. 设置用户 QQ交流群:585499566 在TestLink系统中,每个用户都可以维护自己的私有信息.admin可以创建用户,但不能看到其它用户的密码.在用户 ...

  3. Gradle2.0用户指南翻译——第三章. 教程

    翻译项目请关注Github上的地址:https://github.com/msdx/gradledoc本文翻译所在分支:https://github.com/msdx/gradledoc/tree/2 ...

  4. 2017.2.28 activiti实战--第五章--用户与组及部署管理(三)部署流程及资源读取

    学习资料:<Activiti实战> 第五章 用户与组及部署管理(三)部署流程及资源读取 内容概览:如何利用API读取已经部署的资源,比如读取流程定义的XML文件,或流程对应的图片文件. 以 ...

  5. CentOS 6.5搭建PPTP VPN服务器

    VPN是虚拟专用网络(Virtual Private Network)的缩写,VPN有多种分类方式,包括PPTP.L2TP.IPSec等,本文配置的VPN服务器是采用PPTP协议的,PPTP是在PPP ...

  6. 精通Web Analytics 2.0 (5) 第三章:点击流分析的奇妙世界:指标

    精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第三章:点击流分析的奇妙世界:指标 新的Web Analytics 2.0心态:搞定它.新的闪亮系列工具:是的.准备好了吗?当然 ...

  7. ubuntu 搭建PPTP VPN服务器

    上一篇文章介绍了如何在Ubuntu服务器上搭建IPSEC L2TP VPN服务器.继续介绍如何在Ubuntu服务器上搭建PPTP VPN服务器. 首先安装以下所需包 #apt-get install ...

  8. 转载 - Vultr VPS注册开通且一键快速安装PPTP VPN和电脑连接使用

    本文转载来自:https://www.vultrclub.com/139.html 从2014年Vultr VPS进入市场之后,作为有背景.实力的搅局者,是的最近两年VPS.服务器的用户成本降低.配置 ...

  9. SEO 第三章

    SEO第三章 本次课目标: 1.  掌握关键词的选取方法 2.  掌握关键词的竞争强度分析 3.  掌握关键词的拓展方法 一.关键词的选取 选择关键词的时候可以根据公司网站的定位,围绕公司的主营产品或 ...

随机推荐

  1. sqlServer 2008修改字段类型和重命名字段名称的sql语句

    sqlServer 2008修改字段类型和重命名字段名称的sql语句 //修改字段的类型 alter table fdi_news alter column c_author nvarchar(50) ...

  2. sencha touch打包成安装程序

    为了更好地向大家演示如何打包一个sencha touch的项目,我们用sencha cmd创建一个演示项目,如果你的sencha cmd环境还没有配置,请参照 sencha touch 入门系列 (二 ...

  3. qt 环境下mapx组件打包后编译产生c2248和c2512错误

    C:\Qt\Qt5.6.0\5.6\msvc2013\include\QtCore\qmetatype.h:760: error: C2248: “MapSpace::IRowCursor::IRow ...

  4. python模块之configparser

    configparser用于处理特定格式的文件,其本质上是利用open来操作文件. # 注释1 ; 注释2 [section1] # 节点 k1 = v1 # 值 k2:v2 # 值 [section ...

  5. mysql 复制表结构、表数据的方法

    From: http://blog.163.com/yaoyingying681@126/blog/static/109463675201191173221759/ MySQL 添加列,修改列,删除列 ...

  6. 移动端Viewport & 使用rem来开发移动端网站

    Viewport大神 无双 的精彩解释 具体参数各型号是否支持参见: http://www.cnblogs.com/2050/p/3877280.html#commentform 摘录: 移动设备上的 ...

  7. java学习第19天(异常)

    异常的体系 Throwable |--Error 严重问题 |--Exception |--RuntimeException 运行期异常,我们需要修正代码 |--非RuntimeException 编 ...

  8. flag--命令行参数解析之StringVar

    func StringVar func StringVar(p *string, name string, value string, usage string) StringVar定义了一个有指定名 ...

  9. .NET获取根目录方法

    1.取得控制台应用程序的根目录方法 方法1.Environment.CurrentDirectory 取得或设置当前工作目录的完整限定路径 方法2.AppDomain.CurrentDomain.Ba ...

  10. java上传xls文件

    using System; using System.Collections.Generic; using System.Web; using System.Web.UI; using System. ...