在互联网高速发展的今天,想要浏览各种各样的网页,或者使用各种各样的应用,都需要注册账号,为了安全起见,不同的账号往往设置不同的密码,大量的密码很难完全记住,如果每次都靠"找回密码",那上网效率也太低了。。。
算了编不下去了,总之由于偶然想起学Python时写过一个类似的脚本,想尝试通过java实现,并进一步完善其功能,功能介绍及代码如下:
功能介绍
账户管理器可以保存任意账号和密码,和与之对应的 “键” ,例如我的steam账号就可以保存为
键:steam
账号:abc
密码:123
键的作用就是在大量账号密码对中,找到需要的那一对
这里提供了以下指令:
li/export 列出所有保存的用户名和密码对 / 导出账户信息到当前目录
pw/un/uap/del 键 通过键得到密码 / 账号 / 账号和密码 / 删除对应账号和密码
add 键 账号 密码 添加新的账户信息
add excel文件路径 通过excel文件添加新的账户信息
注:这里的pw时passWord的缩写,un是userName的缩写,uap是userNameAndPassword的缩写,excel表格要求有三列,分别为key、username、password
这里保存信息是通过将Map对象保存成一个account文件,后续使用时通过读写该文件实现
main方法
public static void main(String[] args) {
try{
//用于保存账户信息的文件名
File accountFile=new File("account");
Map<String, User> account;
if (!accountFile.exists()){
//第一次使用,创建一个空对象保存到这个文件
account=new HashMap<>();
ObjectOutputStream outputStream =new ObjectOutputStream(new FileOutputStream(accountFile));
outputStream.writeObject(account);
outputStream.close();
}else {
//文件已存在,不是第一次使用,直接读取
ObjectInputStream inputStream =new ObjectInputStream(new FileInputStream(accountFile));
account = (HashMap)inputStream.readObject();
inputStream.close();
}
//判断用户输入指令部分
if (args.length==2 && "pw".equals(args[0])){
//获取密码并拷贝到剪贴板
getPassWord(account,args[1]);
}
else if (args.length==2 && "un".equals(args[0])) {
//获取用户名并拷贝到剪贴板
getUserName(account,args[1]);
}
else if (args.length==2 && "uap".equals(args[0])) {
//获取用户名和密码信息
getUserNameAndPassWord(account,args[1]);
}
else if (args.length==1 && "li".equals(args[0])) {
//列出所有保存的用户名和密码信息
listUserNameAndPassWord(account);
}
else if (args.length==4 && "add".equals(args[0])) {
//添加用户名和密码信息
addUserNameAndPassWord(account,accountFile,args);
}
else if (args.length==2 && "add".equals(args[0])){
//根据excel文件添加用户名和密码信息
addUserNameAndPassWordByFile(account,accountFile,args);
}
else if ((args.length==2 ||args.length==1) && "export".equals(args[0])){
//根据给定路径导出用户信息到excel文件
exportUserNameAndPassWordToFile(account,args);
}
else if (args.length==2 && "del".equals(args[0])) {
//删除用户名和密码信息
delUserNameAndPassWord(account,args[1]);
}
else {
System.out.println("语法错误,正确语法为:");
System.out.println("li/export");
System.out.println("export 路径");
System.out.println("pw/un/uap/del 键");
System.out.println("add 键 用户名 密码");
System.out.println("add .xlsx文件路径");
}
System.out.println("account文件所在位置:"+accountFile.getAbsolutePath());
}
catch (Exception e)
{
System.out.println("出现异常:"+ e.getMessage());
System.out.println("可能的原因是:");
System.out.println("1、保存账户信息的文件损坏,请删除重试");
System.out.println("2、指定的路径错误");
}
}
public static void getPassWord(Map account, String key){
//得到剪贴板
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(new StringSelection(((User)account.get(key)).getPassWord()),null);
System.out.println("已复制到剪贴板");
}
public static void getUserName(Map account, String key){
//得到剪贴板
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(new StringSelection(((User)account.get(key)).getUserName()),null);
System.out.println("已复制到剪贴板");
}
public static void getUserNameAndPassWord(Map account, String key){
System.out.println("userName: "+((User)account.get(key)).getUserName());
System.out.println("passWord: "+((User)account.get(key)).getPassWord());
System.out.println("请手动复制");
}
public static void listUserNameAndPassWord(Map account){
Set<String > keys = account.keySet();
for (String key :keys){
System.out.println(key+":"+((User)account.get(key)).getUserName()+":"+((User)account.get(key)).getPassWord());
}
}
public static void addUserNameAndPassWord(Map account, File accountFile, String args[]) throws IOException {
if (account.containsKey(args[1])){
System.out.println("指定的键(key)已存在");
return;
}
User user=new User(args[2],args[3]);
account.put(args[1],user);
ObjectOutputStream outputStream =new ObjectOutputStream(new FileOutputStream(accountFile));
outputStream.writeObject(account);
outputStream.close();
}
/**
* 通过excel表格导入用户账户信息
* @param account
* @param accountFile
* @param args
* @throws IOException
* @throws InvalidFormatException
*/
public static void addUserNameAndPassWordByFile(Map account, File accountFile, String args[]) throws IOException, InvalidFormatException {
if(args[1].endsWith("xlsx")){
XSSFWorkbook excelFile=new XSSFWorkbook(new File(args[1]));
XSSFSheet firstSheet = excelFile.getSheetAt(0);
//保存数据的第一行和最后一行
int firstRowNum = firstSheet.getFirstRowNum();
int lastRowNum = firstSheet.getLastRowNum();
XSSFRow firstRow = firstSheet.getRow(firstRowNum);
//保存数据的第一列和最后一列
short firstCellNum = firstRow.getFirstCellNum();
short lastCellNum = firstRow.getLastCellNum();
int keyColNum=-1;
int userNameColNum=-1;
int passWordColNum=-1;
for (int i= firstCellNum;i<lastCellNum;i++){
if ("key".equals(firstRow.getCell(i).getStringCellValue().trim().toLowerCase())){
keyColNum=i;
}else if("username".equals(firstRow.getCell(i).getStringCellValue().trim().toLowerCase())){
userNameColNum=i;
}else if("password".equals(firstRow.getCell(i).getStringCellValue().trim().toLowerCase())){
passWordColNum=i;
}
}
if (keyColNum == -1||userNameColNum==-1||passWordColNum==-1){
System.out.println("读取失败,格式错误");
return;
}
for (int i=firstRowNum+1;i<=lastRowNum;i++){
XSSFRow currentRow = firstSheet.getRow(i);
currentRow.getCell(keyColNum).setCellType(CellType.STRING);
currentRow.getCell(userNameColNum).setCellType(CellType.STRING);
currentRow.getCell(passWordColNum).setCellType(CellType.STRING);
User user=new User(currentRow.getCell(userNameColNum).getStringCellValue(),currentRow.getCell(passWordColNum).getStringCellValue());
account.put(currentRow.getCell(keyColNum).getStringCellValue(),user);
}
excelFile.close();
ObjectOutputStream outputStream =new ObjectOutputStream(new FileOutputStream(accountFile));
outputStream.writeObject(account);
outputStream.close();
}
else {
System.out.println("文件格式不支持");
}
}
/**
* 将账户信息导出到excel表格
* @param account
* @param args
*/
public static void exportUserNameAndPassWordToFile(Map account,String args[]) throws IOException {
XSSFWorkbook excel = new XSSFWorkbook();
XSSFSheet sheet = excel.createSheet();
XSSFRow firstRow = sheet.createRow(0);
firstRow.createCell(0).setCellValue("key");
firstRow.createCell(1).setCellValue("userName");
firstRow.createCell(2).setCellValue("passWord");
int curIndex =1;
for (Object key:account.keySet()){
XSSFRow curRow = sheet.createRow(curIndex++);
curRow.createCell(0).setCellValue((String) key);
curRow.createCell(1).setCellValue(((User)account.get(key)).getUserName());
curRow.createCell(2).setCellValue(((User)account.get(key)).getPassWord());
}
String xlsxFilePath = ".\\account.xlsx";
if (args.length==2){
xlsxFilePath=args[1] + File.separator+ "account.xlsx";
}
OutputStream outputStream = new FileOutputStream(new File(xlsxFilePath));
excel.write(outputStream);
outputStream.close();
excel.close();
}
public static void delUserNameAndPassWord(Map account, String key){
if (!account.containsKey(key))
{
System.out.println("指定的键(key)不存在");
}
account.remove(key);
}
User类
这里还创建了一个User类,有两个String类型的属性userName和passWord,创建了对应的getter和setter、无参和有参构造、重写了toString、equals、hashCode方法(好像用不上?),这里也把代码附上
public class User implements Serializable {
private static final long serialVersionUID = -7690676590515933732L;
String userName;
String passWord;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWord() {
return passWord;
}
public void setPassWord(String passWord) {
this.passWord = passWord;
}
public User() {
}
public User(String userName, String passWord) {
this.userName = userName;
this.passWord = passWord;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(userName, user.userName) && Objects.equals(passWord, user.passWord);
}
@Override
public int hashCode() {
return Objects.hash(userName, passWord);
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", passWord='" + passWord + '\'' +
'}';
}
}
批处理程序
直接 java -jar 用起来就太麻烦了,还必须和jar包在同一个目录下,这里可以利用批处理程序加环境变量的方法,在任何地方都能快速使用,这里以 java -jar jar包名 pw 键 为例,同时也是由于这个最常用
新建 pw.bat,输入以下内容:
@java -jar D:\path\accountManager.jar pw %*
@pause
注意:这里的路径只用于演示,不要完全拷贝,改成对应jar包所在路径
然后把当前bat文件所在路径加入环境变量中的Path中
以上步骤完成后,就能在任意位置打开控制台,或者直接 win + R 输入 pw 键 将对应的密码复制到剪贴板,相比于输入完整的java -jar...方便很多
这里的pw代表的是pw这个批处理文件,如果想使用 password 键 的方式,将批处理文件名改为password.bat即可
如果想增加其他快捷指令,例如un,只需额外创建一个un.bat,把上面代码中的pw改成un即可
account文件位置问题
如果在jar包所在路径使用控制台输入了完整的java -jar ...,生成的account文件就在jar包所在目录,如果使用win+R的方式,生成的account文件是在 C:\Users\用户名 目录下,这是因为try内第一句代码在执行时受工作路径影响。
如果想让account文件在一个固定的位置,把第一行代码改为绝对路径就行了。
最后
先提供一下打包好的jar包,由于批处理文件中的路径不固定,这里就不提供了
链接:https://pan.baidu.com/s/1fjqnFlYvXGGZW1cqRbWJBA
提取码:pw86
项目的依赖:后两个是由于在使用的时候总是提示ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console…才加上的
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.23.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.23.1</version>
</dependency>
</dependencies>
以及,这里并不讨论安全性的问题,如果密码保存在电子设备上,还是建议多备份。
24/12/2 更新,增加了读取excel表格和导出到excel表格