polenum,可以获取哪些信息

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了polenum,可以获取哪些信息相关的知识,希望对你有一定的参考价值。

目前,帐号仍然是最主要的用户身份认证方式,但由于安全意识的淡漠,很多人仍在使用弱口令。而一旦泄漏,所有安全防范机制都将形同虚设。
本课程《用户口令审计》是『Kali Linux工具大全』技术系列的第5部分。向大家详述Kali Linux中全部在线/离线弱口令审计工具的用法,以此来帮助大家提前发现自己系统中的弱口令问题。



用户口令审计工具介绍

1、crunch
在面对妥善保护的系统时,我们可能很难发现其漏洞和可渗透的突破口。作为渗透测试人员,此时应尝试对目标系统进行弱密码的检测。密码**成败的关键在于字典的质量,crunch是一个密码字典生成器,它可以灵活的按照规则生成定制的密码字典,为了方便使用,其内建了常用的字符集文件,并支持自定义密码构成元素。
2、wordlists / SecLists
在面对妥善保护的系统时,我们可能很难发现其漏洞和可渗透的突破口。作为渗透测试人员,此时应尝试对目标系统进行弱密码的检测,密码**成败的关键在于字典的质量。为了方便使用,Kali中已默认包含了大量通用密码字典,它们分别存放在wordlists、seclists两个目录之中。除密码字典之外,以上目录中还包含大量漏洞挖掘和Fuzz用途的字典文件。 hashid / hash-identifier
单向加密算法是将可变长度输入数据,加密生成固定长度的密文输出值,即所谓的HASH值。此加密算法通常被认为是不可逆的。但我们可以提前计算常见数据的HASH值,并利用其进行反查匹对应的明文,实现HASH**。由于HASH算法种类众多,因此需要hashid、hash-identifier来提前判断生成密文的HASH算法,以便查询对应明文。 findmyhash
单向加密算法是将可变长度数据,加密生成固定长度的密文输出值,即所谓的HASH值。此加密算法通常被认为是不可逆的。但有众多网站会提前计算常见数据的HASH值,并利用其进行反查匹对应的明文,以此实现HASH值**。findmyhash可在线查询多个站点的HASH值数据库,批量完成HASH值匹配的**,其新版本查询效果更佳。
3、 fcrackzip
存有机密数据的文件,经常会被其所有者加密压缩保存。而作为数据安全审计者,则应对加密文件进行弱口令检查,以确保数据安全性。fcrackzip是一款快速的ZIP压缩文件密码**工具,其支持基于字典和**的两种工作模式,同时其内建了字符集和密码规则指定功能,免去了使用者提前准备和保存密码字典文件的繁琐。
4、cupp3 / cewl / fab-cewl
由于人性与生俱来的弱点,使得弱口令成为很多系统都存在的安全问题,即使是那些安全防护较好的站点也不例外。作为渗透测试者,如果能够获得目标系统的密码,则无需繁琐的漏洞挖掘,即可直接接管目标系统。密码**的关键在于字典的命中率,cupp3可依据个人信息生成专属字典,cewl则通过收集企业信息生成专属字典。使用这些有针对性的字典,使得密码**的成功率更高。
5、 pwdump / samdump2
出于安全性的考虑,windows系统并不会保存用户账号的明文密码,而是以加密的形式存储于本机的SAM数据库中。不过密码虽为密文保存,但如果密码过于简单,仍然存在被**的可能性。在可以物理接触电脑的情况下,我们可以利用pwdump、samdump2来读取SAM数据库文件中的密文密码,然后再使用其他工具进行密码**。
6、chntpw
我有一个同事曾经受到电脑勒索,攻击者修改了他的系统账号密码,并要求他支付赎金。众所周知,出于安全性的考虑,windows系统并不会保存用户账号的明文密码,而是以加密的形式存储于本机的SAM数据库中。因此我们可以通过chntpw工具本地读取并修改SAM数据库,将账号密码清空,从而避免受到坏人的勒索。
7、 hydra
密码**可以分为在线**和离线**两种。所谓在线**,就是使用不同的密码向目标服务器发起重复的身份验证请求,然后根据服务器的反馈信息判断登陆是否成功。hydra是开源世界在线密码**工具中的王者,它不但支持常见的所有协议类型,同时也支持不同形式的WEB表单认证**。它功能强大,使用灵活简洁。
8、 pw-inspector
由于人性与生俱来的弱点,弱口令成为很多系统都存在的安全问题,即使是很多安全防护较好的站点也不例外。密码**的关键在于字典的命中率,如果你知道密码的字符构成规则,可以使用pw-inspector对已有密码字典进行过滤筛选,以便提高密码**的效率。pw-inspector不能凭空生成字典,它只是对现有字典的过滤筛选工具。
9、medusa
密码**分为在线**和离线**两种。所谓在线**,就是使用不同的账号密码重复向目标服务器提交身份验证请求,然后根据服务器的反馈信息判断登陆是否成功。medusa是开源世界在线密码**工具中的又一王者(与hydra齐名),它支持常见的所有协议类型,同时超高的稳定性是其最大的优势,是密码**领域的必备工具。
10、cmospwd
计算机开机后运行的第一个程序是POST,即加电自检程序。其检测到的硬件参数和使用者的设置参数都存储于cmos内存芯片中,这些配置参数中也包括cmos密码。在你不小心忘记了密码而无法修改硬件参数时,我们可以使用debug命令或comspwd工具清空或找回密cmos密码,其中cmospwd工具兼容众多Bios生产厂商的产品,同时对某些品牌机的BIOS还有自动解锁的功能,是一个优秀的跨平台解密工具。
11、 gpp-decrypt
从windows server 2008开始,微软为其活动目录域新增加了20多项组策略首选项(gpp)设置,其中包括通过GPO统一修改客户端账号密码的功能。出于安全的考略,微软使用了强**的AES算法来加密下发的密码,但乌龙事件使得微软在其开发者网站上直接公布了该**,因此使得安全目标完全破灭。gpp-decrypt既是一个基于泄漏**,对加密密码进行解密还原的工具。
12、dbpwaudit
dbpwaudit是一个由java语言编写的数据库在线密码**工具,它只支持MSSQL、mysql、DB2、Oracle等四种数据库类型。直到授课前我才发现,最新版的Kali Linux中已经不再包含此工具,因此现在我们必须手动下载才能使用这款工具。在审计不同数据库时,我们还需要单独下载相应数据库的JDBC驱动,才能使其正常工作。
13、 crowbar
crowbar是一个在线的密码**工具,与同为密码**工具的hydra、medusa相比,crowbar支持的协议类型十分有限(只有四种),但却个性十足。crowbar支持的认证**方式可以很好的弥补hydra、medusa的不足,它支持Openv*n以及基于**方式身份认证的SSH、VNC服务,可作为其他强大密码**工具的重要补充。
14、brutespray
渗透测试初期,我们总是会通过nmap进行主机发现、端口发现、服务发现等几个步骤,来确认可进行密码**的服务类型,然后再放出hydra、medusa等工具来实施**。过程中如果相关端口数量众多的话,我们就不得不笨拙的一个一个进行输入。brutespray可以自动读取和解析nmap的扫描报告,并从中识别出可进行密码**的服务类型,让后再自动调用medusa实施**,这将大大提高我们的工作效率。
15、polenum
为了保护信息安全,企业网络通常会制定密码策略,强制要求员工设置足够安全的系统账号密码。但人永远都是安全中最薄弱的环节,由于人性中与生俱来怕麻烦和懒惰等特性,大家总是趋向于给自己设置简单的弱口令。作为企业中的安全和审计人员,有责任发现并纠正密码策略失效的情况,polenum是一个正向的安全检查工具,它能够帮助我们高效快捷的进行操作系统的密码策略审计。
16、rsmangler
与通过挖掘漏洞来进行渗透相比,通过密码**来渗透目标的技术门槛相对较低,而且一旦成功其渗透行为也更加隐秘,因此密码**成为了渗透过程中不可缺少的重要步骤。密码**的成功关键在于密码字典的命中率,基于大多数人构造密码的习惯(姓名-生日-爱好等),rsmangler可以基于有限的个人信息,变形生成数量巨大的针对性专属密码字典,从而大大提高密码**的成功率。
17、 cachedump / lsadump
creddump工具集中包含了三个关于windows系统密码的**工具。cachedump针对域账号在本地计算机中的缓存身分验证信息,它可以还原这些缓存的认证信息,并结合其他离线**工具进行密码**。运气好的话,你可能会得到域管理员的密码!!lsadump则可以直接还原那些由操作系统记住的密码,比如登陆网络驱动器的密码、v*n密码、拨号密码、系统自动登陆密码等,由于可以还原出明文密码,因此lsadump被视为安全从业人员的必备工具。
18、pack
如果你认为自己学会了几个密码**软件,就可以自称专业人士的话,那只能说明你还是个小白。众所周知,根据目前计算机的运算能力,实现全键盘空间字符的密码**是不可能的。但如果能准确的分析密码构成规则,则完全可以在可接受的时间范围内,完成半数以上的密码**。Pack全称是密码分析**工具包,他通过分析已有字典的密码构成规则,使我们可以在最短的时间里最大限度的完成**密码。这是你成为密码**专业人士的必备一课。
19、ophcrack
众所周知,windows系统会将用户帐号的密码,经过单向加密之后保存在用户帐号数据库中。但由于加密算法公开通用,因此明文密码加密之后的密永远不变,这直接导致了密码碰撞**思路的产生,即攻击者先计算出全部明文对应的密文,再通过比对密文来**明文。ophcrack是一个基于彩虹表的windows密码**工具,同时其官网提供了大量现成的彩虹表下载,从而大大提高了密码的**效率。
20、 rainbowcrack
虽然单向加密算法通常被认为是不可能被**的,但黑客却找到了碰撞**的思路。即先计算出全部明文对应的密文,然后再通过比对密文来倒推明文的方式。在碰撞**的过程中计算明文对应密文的过程最耗时,因此有人提出了彩虹表的概念,将明文加密后对应的密文结果保存下来,以便日后重复使用,即彩虹表。rainbowcrack内含一套彩虹表的生成、优化、**工具,并支持众多加密算法,更可利用GPU提高运算速度。
21、 ncrack
ncrack是由nmap项目共同维护的在线密码**工具,因此其命令格式和参数的用法都与nmap命令非常相似,这无疑会大大降低新用户的学习成本,同时其模块化的架构使其可以满足更多应用场景的需求。虽然其名气并不很大,但从密码**能力方面来看,ncrack毫不逊色于同类的hydra、medusa等著名在线密码**工具,而且在速度和稳定性方面还有更加优异的表现。
22、maskprocessor
众所周知,根据目前计算机的运算能力,要实现全键盘空间字符的密码**是不可能实现的。因此更多情况下,我们都会采用基于字典的密码**方式,而此时字典的命中率则成为密码**成败的关键。为了构成命中率更高、更有针对性的密码字典,maskprocessor给我们提供了众多的规则选择,是我们自定义密码字典的首选利器。
23、sucrack
通常渗透测试者在通过应用程序漏洞获得系统shell之后,会发现自己拥有的只是普通用户帐号的权限,因此需要进一步的提权操作,将自己提升为root权限。su是所有linux系统都支持的用户切换命令,而切换过程中需要提供目标帐号的密码,因此我们可以利用此功能,使用不同的密码重复向系统进行身份验证,以此来实现密码的暴力**,sucrack即是自动实现这一过程的首选工具。
24、thc-pptp-bruter
为防止内部系统暴露在公网之上,很多公司会采用v*n的解决方式,而微软的MSChapV2则是v*n最广泛被采用的身份验证方法。不幸的是,微软系统的早期版本在实现身份验证的过程中存在漏洞,微软虽然为此发布了补丁,但并未彻底修复该漏洞,使得所有采用该身份验证方式的v*n都会遭受到密码的暴力**攻击。thc-pptp-bruter即是利用此漏洞,专门针对PPTP v*n进行密码**的工具之一。
24、patator
虽然hydra、medusa、ncrack等工具都是优秀的在线密码**工具,但仍然无法满足所有场景的**需求,因此在厌倦了以上所有工具之后,作者开发了patator。这是一款高度定制化的密码**工具,使用者可以按照当前实际场景,灵活定义**成功与否的判断依据,但也同时使其学习成本明显高于其他工具。同时patator还包涵部分在线枚举和离线密码**功能,使其成为一个综合型的密码**工具。
25、 hashcat
如果上天只允许我选择一个离线密码**工具的话,那么我的选择一定是hashcat。hashcat不但开源免费,而且它还是世界上速度最快的离线密码**工具。它提供多系统、多算法、多硬件平台、分布式等几乎全特性的功能支持,同时还支持OpenCL、CUDA等编程标准。目前hashcat已经实现了所有版本的合并统一,使得初学者无需再迷茫的寻找适合自己的软件版本,现在hashcat会自动检测你的CPU和GPU,从而最大限度的发挥你的计算能力。
26、sipcrack
利用廉价共享带宽的IP网络承载实时语音通话的技术称为VoIP,SIP则是目前使用最广且接受度最高的VoIP信令协议。SIP是一种基于文本的信号控制协议,主要负责在客户端与服务期(PBX)间进行身份认证、会话建立和会话管理等工作。如果攻击者可以嗅探身份认证的通信过程,则可以利用sipcrack基于字典**其中的加密摘要信息。
27、oclGaussCrack
2009年震网病毒的出现,标志着***背景的武器化攻击程序已经走入现实。随后出现的火焰病毒再次证明,网络空间的战争其实每天都在我们身边悄悄的进行。2011年出现的高斯病毒使用了与震网、火焰病毒相同的基础代码、软件建构以及与CC服务器的通信方式,种种迹象表明它们全部出自同一开发队伍。由于采用了高级加密方式,最初高斯病毒的payload无法解密,直到ocalgausscrack工具的出现。
28、mimikatz
最近安全社区的一篇文章评出了黑客最经常使用的5个工具,其中就包括本课的mimikatz,此工具堪称windows系统凭据收集领域的瑞士军刀,即在统一框架下集成了众多身材小巧且功能强大的工具集合。凭据包括账号密码、HASH、证书、令牌、cookie等众多类型的信息,一旦获取将可能完全控制目标系统。但由于该工具涉及过多的背景知识,因此几乎没有人能发挥其全部功能(一般只用两条命令),本课我竭尽所能向大家展示这个神一样的存在。
29、 PtH / WCE / xfreerdp
密码**是个耗时耗资源的事情,如果可以不必忍受这个煎熬的过程,相信每个渗透测试者都会兴奋不已。在密码**领域有一种称为Pass the Hash的攻击思路,即在已经获得密码密文的情况下,并不进行**,而是直接提交密文从而实现身份认证。其最典型的应用场景就是攻击Windows操作系统,windows早期版本的密码加密过程不加盐,因此很容易遭受PtH攻击。本课为大家介绍的PtH工具包共包含10个具体工具,分别适合在不同需求环境下使用。
30、Statsprocessor / hcstatgen
依靠现代计算机的运算能力,并不足以在可接受的时间范围内完成全键盘字符空间的密码**任务,这正是现代密码学仍然可以提供安全性的前提,因此纯暴力的密码**是不现实的,同样也使得基于密码字典的**方式成为普遍的选择。如何减小字典的体积,同时提高命中率是所有**者的共同目标。本课我重点向大家介绍“马尔科夫链”在密码**领域的实际应用,同时利用本课的两个工具,我们可以轻松生成接近真实的密码字典。
31、 John / Johnny / unshadow
John the Ripper是你必须掌握的一个离线密码**工具,它可以自动识别并解密200多种加密算法和应用。其功能之丰富强大,已经达到了令人震惊的程度,为了降低使用者的难度,John通过配置文件保存大部分常用参数,因此使用者并不会觉得太过复杂。它支持4种**模式,可以满足所有用户和场景的需要,强大的掩码和规则更可对现有密码字典进行丰富的变形,最大程度提高密码**成功率。Johnny是图形化界面的John。
参考技术A polenum 为了保护信息安全,企业网络通常会制定密码策略,强制要求员工设置足够安全的系统账号密码。

通过jdbc获取数据库中的表结构

通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类

 

  1、JDBC中通过MetaData来获取具体的表的相关信息。可以查询数据库中的有哪些表,表有哪些字段,字段的属性等等。MetaData中通过一系列getXXX函数,将这些信息存放到ResultSet里面,然后返回给用户。关于MetaData的说明网上也有不少,这里我只是从我自身学习的角度来记录一下简单使用JDBC以及获取数据表相关信息的方法。 

DatabaseMetaData dbmd = con.getMetaData(); 
rs = dbmd.getColumns(con.getCatalog(), schema, tableName, null); 
rs.getString(DATA_TYPE) // java.sql.Types 的 SQL 类型 
rs.getString(COLUMN_SIZE) //列的大小。对于 char 或 date 类型,列的大小是最大字符数,对于 numeric 和 decimal 类型,列的大小就是精度。 
rs.getString(DECIMAL_DIGITS) //小数部分的位数

  2、下面就是我的JDBC下的获取表信息的代码了。我是以MySQL 5.0作为测试平台的。可以通过下面四个步骤来实现:

复制代码
//1. JDBC连接MYSQL的代码很标准。 
class.forName("com.mysql.jdbc.Driver").newInstance(); 
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test?user=root&password=123456");

//2. 下面就是获取表的信息。 
m_DBMetaData = m_Connection.getMetaData(); 
ResultSet tableRet = m_DBMetaData.getTables(null, "%",m_TableName,new String[]{"TABLE"}); 
/*其中"%"就是表示*的意思,也就是任意所有的意思。其中m_TableName就是要获取的数据表的名字,如果想获取所有的表的名字,就可以使用"%"来作为参数了。*/

//3. 提取表的名字。 
while(tableRet.next) System.out.println(tableRet.getString("TABLE_NAME"));

/*通过getString("TABLE_NAME"),就可以获取表的名字了。 
从这里可以看出,前面通过getTables的接口的返回,JDBC是将其所有的结果,保存在一个类似table的内存结构中,而其中TABLE_NAME这个名字的字段就是每个表的名字。*/

//4. 提取表内的字段的名字和类型 
String columnName; 
String columnType; 
ResultSet colRet = m_DBMetaData.getColumns(null,"%", m_TableName,"%"); 
while(colRet.next()) { 
  columnName = colRet.getString("COLUMN_NAME"); 
  columnType = colRet.getString("TYPE_NAME"); 
  int datasize = colRet.getInt("COLUMN_SIZE"); 
  int digits = colRet.getInt("DECIMAL_DIGITS"); 
  int nullable = colRet.getInt("NULLABLE"); 
  System.out.println(columnName+" "+columnType+" "+datasize+" "+digits+" "+ nullable); 
}

/*JDBC里面通过getColumns的接口,实现对字段的查询。跟getTables一样,"%"表示所有任意的(字段),而m_TableName就是数据表的名字。

getColumns的返回也是将所有的字段放到一个类似的内存中的表,而COLUMN_NAME就是字段的名字,TYPE_NAME就是数据类型,比如"int","int unsigned"等等,COLUMN_SIZE返回整数,就是字段的长度,比如定义的int(8)的字段,返回就是8,最后NULLABLE,返回1就表示可以是Null,而0就表示Not Null。*/
复制代码
复制代码
每个列描述都有以下列: 

TABLE_CAT String => 表类别(可为 null) 
TABLE_SCHEM String => 表模式(可为 null) 
TABLE_NAME String => 表名称 
COLUMN_NAME String => 列名称 
DATA_TYPE int => 来自 java.sql.Types 的 SQL 类型 
TYPE_NAME String => 数据源依赖的类型名称,对于 UDT,该类型名称是完全限定的 
COLUMN_SIZE int => 列的大小。 
BUFFER_LENGTH 未被使用。 
DECIMAL_DIGITS int => 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型,则返回 Null。 
NUM_PREC_RADIX int => 基数(通常为 10 或 2) 
NULLABLE int => 是否允许使用 NULL。 
columnNoNulls - 可能不允许使用 NULL 值 
columnNullable - 明确允许使用 NULL 值 
columnNullableUnknown - 不知道是否可使用 null 
REMARKS String => 描述列的注释(可为 null) 
COLUMN_DEF String => 该列的默认值,当值在单引号内时应被解释为一个字符串(可为 null) 
SQL_DATA_TYPE int => 未使用 
SQL_DATETIME_SUB int => 未使用 
CHAR_OCTET_LENGTH int => 对于 char 类型,该长度是列中的最大字节数 
ORDINAL_POSITION int => 表中的列的索引(从 1 开始) 
IS_NULLABLE String => ISO 规则用于确定列是否包括 null。 
YES --- 如果参数可以包括 NULL 
NO --- 如果参数不可以包括 NULL 
空字符串 --- 如果不知道参数是否可以包括 null 
SCOPE_CATLOG String => 表的类别,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null) 
SCOPE_SCHEMA String => 表的模式,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null) 
SCOPE_TABLE String => 表名称,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null) 
SOURCE_DATA_TYPE short => 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型(如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF,则为 null) 
IS_AUTOINCREMENT String => 指示此列是否自动增加 
YES --- 如果该列自动增加 
NO --- 如果该列不自动增加 
空字符串 --- 如果不能确定该列是否是自动增加参数 
COLUMN_SIZE 列表示给定列的指定列大小。对于数值数据,这是最大精度。对于字符数据,这是字符长度。对于日期时间数据类型,这是 String 表示形式的字符长度(假定允许的最大小数秒组件的精度)。对于二进制数据,这是字节长度。对于 ROWID 数据类型,这是字节长度。对于列大小不适用的数据类型,则返回 Null。 


参数:
catalog - 类别名称;它必须与存储在数据库中的类别名称匹配;该参数为 "" 表示获取没有类别的那些描述;为 null 则表示该类别名称不应该用于缩小搜索范围
schemaPattern - 模式名称的模式;它必须与存储在数据库中的模式名称匹配;该参数为 "" 表示获取没有模式的那些描述;为 null 则表示该模式名称不应该用于缩小搜索范围
tableNamePattern - 表名称模式;它必须与存储在数据库中的表名称匹配
columnNamePattern - 列名称模式;它必须与存储在数据库中的列名称匹配 
复制代码

  3、获取所有表 

String catalog = conn.getCatalog(); //catalog 其实也就是数据库名  
ResultSet tablesResultSet = dbMetaData.getTables(catalog,null,null,new String[]{"TABLE"});  
while(tablesResultSet.next()){  
    String tableName = tablesResultSet.getString("TABLE_NAME");  
}  

tablesResultSet 中有以下列: 

复制代码
TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
TABLE_TYPE String => 表类型。典型的类型是 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。
REMARKS String => 表的解释性注释
TYPE_CAT String => 类型的类别(可为 null)
TYPE_SCHEM String => 类型模式(可为 null)
TYPE_NAME String => 类型名称(可为 null)
SELF_REFERENCING_COL_NAME String => 有类型表的指定 "identifier" 列的名称(可为 null)
REF_GENERATION String => 指定在 SELF_REFERENCING_COL_NAME 中创建值的方式。这些值为 "SYSTEM"、"USER" 和 "DERIVED"。(可能为 null)
复制代码

  4、某个表的主键 

String tableName = ...;  
ResultSet primaryKeyResultSet = dbMetaData.getPrimaryKeys(catalog,null,tableName);  
while(primaryKeyResultSet.next()){  
    String primaryKeyColumnName = primaryKeyResultSet.getString("COLUMN_NAME");  
}  
复制代码
primayKeyResultSet 有以下几列: 

TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
COLUMN_NAME String => 列名称
KEY_SEQ short => 主键中的序列号(值 1 表示主键中的第一列,值 2 表示主键中的第二列)。
PK_NAME String => 主键的名称(可为 null)
复制代码

  5、某个表的外键 

 
ResultSet foreignKeyResultSet = dbMetaData.getImportedKeys(catalog,null,tableName);  
while(foreignKeyResultSet.next()){  
    String fkColumnName = foreignKeyResultSet.getString("FKCOLUMN_NAM");  
    String pkTablenName = foreignKeyResultSet.getString("PKTABLE_NAME");  
    String pkColumnName = foreignKeyResultSet.getString("PKCOLUMN_NAME");  
}  
复制代码
foreignKeyResultSet 有以下几列: 

PKTABLE_CAT String => 被导入的主键表类别(可为 null)
PKTABLE_SCHEM String => 被导入的主键表模式(可为 null)
PKTABLE_NAME String => 被导入的主键表名称
PKCOLUMN_NAME String => 被导入的主键列名称
FKTABLE_CAT String => 外键表类别(可为 null)
FKTABLE_SCHEM String => 外键表模式(可为 null)
FKTABLE_NAME String => 外键表名称
FKCOLUMN_NAME String => 外键列名称
KEY_SEQ short => 外键中的序列号(值 1 表示外键中的第一列,值 2 表示外键中的第二列)
UPDATE_RULE short => 更新主键时外键发生的变化
DELETE_RULE short => 删除主键时外键发生的变化
PK_NAME String => 主键的名称(可为 null)
FK_NAME String => 外键的名称(可为 null)
DEFERRABILITY short => 是否可以将对外键约束的评估延迟到提交时间
复制代码

  6、应用:

  大多数数据库有许多主键,但是在一个表中不允许两条记录的同一个主键具有相同的值。可以使用Java Database Connectivity(JDBC)来判断一个数据表的主键。 JDBC具有强大的元数据处理能力。java.sql.Connection类和java.sql.ResultSet类可以通过调用其getMetaData方法进行反射。可以通过下面两个方法:

//这两个方法都可以获取主外键信息,只是参照物不同
metaData.getExportedKeys("数据库名称", "schema", "表名");
metaData.getImportedKeys(catalog, null, tablename);
//Sql Server
 private static String url = "jdbc:sqlserver://192.168.1.220:1433;User=admin;Password=123456;DatabaseName=Person";
复制代码
package cn.test;

import java.io.File;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TestAll {
    private static String path = "D:\\\\tool\\\\project\\\\DynamicTable\\\\src\\\\cn\\\\test\\\\entity";
    private static String pkname = "com.mysql.jdbc.Driver";
    private static String url = "jdbc:mysql://192.168.1.220:3306/Person";
    private static String[] classNames = new String[] { "ShipStopping",
            "ArriveShip", "TBLUserType" };
    private static Map<String, String> fkTableNamesAndPk = new HashMap<String, String>();

    public static void main(String[] args) {
        test();
    }

    public static void test() {
        Connection conn = null;
        DatabaseMetaData metaData = null;
        ResultSet rs = null;
        ResultSet crs = null;
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            conn = DriverManager.getConnection(url, "admin", "123");
            String catalog = conn.getCatalog(); // catalog 其实也就是数据库名
            metaData = conn.getMetaData();
            File dirFile = new File(path);
            if (!dirFile.exists()) {
                dirFile.mkdirs();
            }
            // 获取表
            rs = metaData.getTables(null, "%", "%", new String[] { "TABLE" });
            while (rs.next()) {
                String tablename = rs.getString("TABLE_NAME");
                String classname = getClassNameByTableName(tablename);
                StringBuffer sb = new StringBuffer();
                StringBuffer sbpackage = new StringBuffer();
                sbpackage.append("package cn.test.entity;\\r\\n\\r\\n");
                sbpackage.append("import javax.persistence.Column;\\r\\n");
                sbpackage.append("import javax.persistence.Entity;\\r\\n");
                sbpackage.append("import javax.persistence.GeneratedValue;\\r\\n");
                sbpackage.append("import javax.persistence.Id;\\r\\n");
                sbpackage.append("import javax.persistence.Table;\\r\\n\\r\\n");
                sb.append("\\r\\n@Entity\\r\\n");
                sb.append("@Table(name = \\"" + tablename + "\\")\\r\\n");
                sb.append("public class " + classname
                        + " implements java.io.Serializable {\\r\\n");
                // 获取当前表的列
                crs = metaData.getColumns(null, "%", tablename, "%");
                // 获取被引用的表,它的主键就是当前表的外键 
                fkTableNamesAndPk.clear();
                ResultSet foreignKeyResultSet = metaData.getImportedKeys(catalog, null, tablename);
                while (foreignKeyResultSet.next()) {
                    String pkTablenName = foreignKeyResultSet.getString("PKTABLE_NAME"); // 外键表
                    String fkColumnName = foreignKeyResultSet.getString("FKCOLUMN_NAME"); // 外键
                    if (!fkTableNamesAndPk.containsKey(fkColumnName))
                        fkTableNamesAndPk.put(fkColumnName, pkTablenName);
                }
                // foreignKeyResultSet.close();
                while (crs.next()) {
                    String columnname = crs.getString("COLUMN_NAME");
                    String columntype = crs.getString("TYPE_NAME");
                    System.out.println("--------------------------"+ columntype);
                    if (existFKColumn(columnname)) {
                        String fkclassname = getClassNameByTableName(fkTableNamesAndPk.get(columnname));
                        sbpackage.append("import " + pkname + "." + fkclassname+ ";\\r\\n");
                        sb.append("\\t/**    */\\r\\n");
                        sb.append("\\tprivate " + fkclassname + " " + columnname+ ";\\r\\n");
                    } else {
                        sb.append("\\t/**    */\\r\\n");
                        sb.append("\\tprivate "+ getFieldType(columntype, sbpackage) + " "+ columnname + ";\\r\\n");
                    }
                }
                sb.append("}");
                File file = new File(dirFile, classname + ".java");
                if (file.exists()) {
                    file.delete();
                }
                getTitle(sbpackage, classname);
                FileOutputStream outputStream = new FileOutputStream(file);
                outputStream.write(sbpackage.toString().getBytes());
                outputStream.write(sb.toString().getBytes());
                outputStream.close();
                System.out.println(classname + " create success ... ");
            }
        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
            try {
                if (null != rs) {
                    rs.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (Exception e2) {
            }
        }
    }

    /**
     * 根据表名获取类名称
     * 
     * @param tablename
     * @return
     */
    private static String getClassNameByTableName(String tablename) {
        String classname = getClassName(tablename);
        for (String name : classNames) {
            if (name.toLowerCase().equals(tablename.toLowerCase())) {
                classname = name;
            }
        }
        return classname;
    }

    private static boolean existFKColumn(String columnname) {
        if (fkTableNamesAndPk != null) {
            if (fkTableNamesAndPk.containsKey(columnname))
                return true;
        }
        return false;
    }

    /**
     * 适合表名为单个单词, 例如:表名是TBLUSER 类名是TBLUser;当表名是USER 类名是User;当表面是USERTYPE(两个单词)
     * 时,类名是Usertype,如果要 UserType,将期望的类名添加到classNames字段中(与数据库表名一致 不区分大小写)。
     * 
     * @param tablename
     * @return
     */
    public static String getClassName(String tablename) {
        String res = tablename.toLowerCase();
        if (tablename.startsWith("TBL")) {
            return tablename.substring(0, 4) + res.substring(4);
        }
        return tablename.substring(0, 1).toUpperCase() + res.substring(1);
    }

    /**
     * 设置字段类型 MySql数据类型
     * 
     * @param columnType
     *            列类型字符串
     * @param sbpackage
     *            封装包信息
     * @return
     */
    public static String getFieldType(String columnType, StringBuffer sbpackage) {
        /*
         * tinyblob tinyblob byte[] 
            tinytext varchar java.lang.string 
            blob blob byte[] 
            text varchar java.lang.string 
            mediumblob mediumblob byte[] 
            mediumtext varchar java.lang.string 
            longblob longblob byte[] 
            longtext varchar java.lang.string 
            enum(\'value1\',\'value2\',...) char java.lang.string 
            set(\'value1\',\'value2\',...) char java.lang.string 
         */
        columnType = columnType.toLowerCase();
        if (columnType.equals("varchar") || columnType.equals("nvarchar")
                || columnType.equals("char") 
//                || columnType.equals("tinytext")
//                || columnType.equals("text") 
//                || columnType.equals("mediumtext")
//                || columnType.equals("longtext")
                ) {
            return "String";
        } else if (columnType.equals("tinyblob")
                ||columnType.equals("blob")
                ||columnType.equals("mediumblob")
                ||columnType.equals("longblob")) {
            return "byte[]1111";
        } else if (columnType.equals("datetime")
                ||columnType.equals("date")
                ||columnType.equals("timestamp")
                ||columnType.equals("time")
                ||columnType.equals("year")) {
            sbpackage.append("import java.util.Date;\\r\\n");
            return "Date";
        } else if (columnType.equals("bit")
                ||columnType.equals("int")        
                ||columnType.equals("tinyint")        
                ||columnType.equals("smallint")        
//                ||columnType.equals("bool")        
//                ||columnType.equals("mediumint")        
//                ||columnType.equals("bigint")
                ) {
            return "int";
        } else if (columnType.equals("float")) {
            return "Float";
        } else if (columnType.equals("double")) {
            return "Double";
        } else if (columnType.equals("decimal")) {
//            sbpackage.append("import java.math.BigDecimal;\\r\\n");
//            return "BigDecimal";
        }
        return "ErrorType";
    }

    /**
     * 设置类标题注释
     * 
     * @param sbpackage
     * @param className
     */
    public static void getTitle(StringBuffer sbpackage, String className) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
        sbpackage.append("\\r\\n/**\\r\\n");
        sbpackage.append("*\\r\\n");
        sbpackage.append("* 标题: " + className + "<br/>\\r\\n");
        sbpackage.append("* 说明: <br/>\\r\\n");
        sbpackage.append("*\\r\\n");
        sbpackage.append("* 作成信息: DATE: " + format.format(new Date())
                + " NAME: author\\r\\n");
        sbpackage.append("*\\r\\n");
        sbpackage.append("* 修改信息<br/>\\r\\n");
        sbpackage.append("* 修改日期 修改者 修改ID 修改内容<br/>\\r\\n");
        sbpackage.append("*\\r\\n");
        sbpackage.append("*/\\r\\n");
    }

}
复制代码

 

 单表实现:

  根据查询语句,获取表结构信息。

复制代码
package cn.test;

import java.io.File;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Test {
    private static String path="D:\\\\tool\\\\project\\\\DynamicTable\\\\src\\\\cn\\\\test\\\\entity";
    private static String url = "jdbc:sqlserver://192.168.1.220:1433;User=cjtc;Password=cjtc;DatabaseName=Person";
    public static void main(String[] args) {
        test();
    }
    public static void test() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        StringBuffer sb=new StringBuffer();
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            conn = DriverManager.getConnection(url);
            String sql = "select * from TBLACCOUNT";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            sb.append("package cn.test.entity;\\r\\n");
            sb.append("public class TBLACCOUNT {\\r\\n");
            File dirFile = new File(path);
            if (!dirFile.exists()) {
                dirFile.mkdirs();
            }
            // 获取列名及类型
            int colunmCount = rs.getMetaData().getColumnCount();
            String[] colNameArr = new String[colunmCount];
            String[] colTypeArr = new String[colunmCount];
            for (int i = 0; i < colunmCount; i++) {
                colNameArr[i] = rs.getMetaData().getColumnName(i + 1);
                colTypeArr[i] = rs.getMetaData().getColumnTypeName(i + 1);
                System.out.println(colNameArr[i] + "(" + colTypeArr[i] + ")"+ " | ");
                if (colTypeArr[i].equals("varchar")||colTypeArr[i].equals("nvarchar")) {
                    sb.append("\\tprivate String "+colNameArr[i]+";\\r\\n");
                    
                }else if (colTypeArr[i].equals("datetime")) {

                } else if (colTypeArr[i].equals("int")) {

                }
            }
            sb.append("}");
            File file = new File(dirFile,"TBLACCOUNT.java");
            if(file.exists()){
                file.delete();
            }
            FileOutputStream outputStream = new FileOutputStream(file);
            outputStream.write(sb.toString().getBytes());
            outputStream.close();
            System.out.println(" success ... ");
        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
            try {
                if (null != rs) {
                    rs.close();
                }
                if (null != ps) {
                    ps.close();
                }
                if (null != conn) {
                    conn.close();
                }
            } catch (Exception e2) {
            }
        }
    }
}
复制代码

以上是关于polenum,可以获取哪些信息的主要内容,如果未能解决你的问题,请参考以下文章

PHP 可以获取客户端哪些访问信息

通过PackageInfo 能获取到哪些信息

获取就业信息的途径都有哪些

PHP 可以获取客户端哪些访问信息

获取信息的途径都有哪些

微信小程序获取用户信息