Skip to main content

python+flask实现个人密码管理

SmartDeng...About 7 minpythonpythonflask

python+flask实现个人密码管理

​ 我是个重度互联网用户,手里头的各种账号简直数不胜数,各种不同的密码管理起来更是十分麻烦,若是每个网站用同一个密码,风险性极大,为了解决这个问题,自己参考网上生成密码的方式写了这个密码管理的flask程序。用这个程序,我可以只记住一个复杂的密码,就可以得到其他账号的密码,且过程不可逆。

​ 也即,只要你的主密码没有泄露,任何一个其他密码被破解,也无法得到你的主密码,这样就保证了其他账号密码的安全。

程序实现的功能

网站界面:

此程序是的目的是利用一个密钥管理其他所有的密码,再配合自己的记忆,或者记事本之类的,记住密码的简记名字。这样自己就只需要记住一个复杂的密钥,就可得到其他所有账号的密码。比如:我有一个test网站的账户,简记为test,密码位数是16位,自己再设置一个复杂的主密码,为了方便,这里设置为asdf。

只要输入的三个参数相同,最后得到的密码一定相同,且生成的密码较为复杂,无试探破解的可能。

从上面的例子,我可以只用记住asdf这个密钥,还有每个密码对应的简记名字和密码位数。这个密钥,就可以设置成一个只可能自己知道,别人无破解的可能(量子计算除外)的密钥。

点击生成后,就会得到由该程序生成的密码。

结果界面如下:

点击按钮可以将生成的密码复制到系统剪切板,支持手机端和电脑端的复制(都用的chrome,其他浏览器没试过,应该都支持)

下面简单介绍下这个程序设计的思路

Python核心代码

对输入的三个参数进行处理,生成最终密码的程序在generate.py文件中,其实代码也非常简单,就是用到了Python的伪随机和md5加密。

程序初始化参数

由上面截图可以看出,在该程序中用到了三个参数,分别为简记名(rem_name), 密码长度(length), 密钥(key)。初始化部分代码如下:

def __init__(self, rem_name, length, key):
        self.rem_name = rem_name
        self.length = int(length)
        self.key = key

除了上面三个需要自己输入的参数之外,在编写程序时,需要预先写好最终生成密码的范围,比如我设置的数组为:

base_str = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
            'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
            'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
            'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '~',
            '!', '@', '#', '$', '%', '^', '&', '*', ';', ':', '?']

这个数组的用途就是,在最后生成密码的时候,会从上面这个数组中伪随机的选择指定个数的字符组合成最终密码。

md5加密

关于md5加密的原理简单说一下就是,对任意的输入文本,经过md5加密之后,生成一定长度(本程序中为32位)的“随机”字符,且该过程不可逆。这个随机并不是真正的随机,因为,如果输入的文本完全相同,生成的md5字符串是相同的。之所以说它随机,是因为它可以说毫无规律,无法通过简单的暴力破解获取原输入文本,一般用于数字签名等。

这部分的代码如下:

def genhash(self):
        string = self.rem_name.join(self.key)
        hash_md5 = md5()  # MD5 hash object
        # MD5 encode
        h_md5 = hash_md5.copy()
        h_md5.update(string.encode('utf-8'))  # encode to utf8
        self.md5_str = h_md5.hexdigest()  # get the md5 string

利用伪随机生成最终密码

最后一个函数便是用上面生成的一串md5字符,用伪随机的方式选择base_str中的字符,最后将结果返回。代码很简单。

上面md5加密生成了32位的字符串,在本算法中,并不需要用到所有的32位字符,因为一般都不会设置这么长的密码。

算法的思路是,设定一个循环,记循环变量为i,每次循环,都选取md5字符串的前i个,作为random函数的随机数种子,再使用random.randint()函数生成一个整数,这个整数限定在(0, p-1)之间(其中p为base_str数组的长度),将所得到的这个整数作为数组索引,从base_str中选取对应索引的字符,得到最终密码的一个字符,循环相应的次数,便得到了最终密码。代码如下:

def random_choose(self):
        print(self.md5_str)
        result = []
        for i in range(self.length):
            random.seed(self.md5_str[:i])
            index = random.randint(0, len(base_str)-1)
            result.append(base_str[index])
        return result

下面是generate.py的完整代码:

#!/usr/bin/python
from hashlib import md5
import random

base_str = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
            'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
            'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
            'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
            'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ',', '.', '~',
            '!', '@', '#', '$', '%', '^', '&', '*', ';', ':', '?']


class passwd():

    def __init__(self, rem_name, length, key):
        self.rem_name = rem_name
        self.length = int(length)
        self.key = key

    def genhash(self):
        string = self.rem_name.join(self.key)
        hash_md5 = md5()  # MD5 hash object
        # MD5 encode
        h_md5 = hash_md5.copy()
        h_md5.update(string.encode('utf-8'))  # encode to utf8
        self.md5_str = h_md5.hexdigest()  # get the md5 string
        # print(md5_str)

    def random_choose(self):
        print(self.md5_str)
        result = []
        for i in range(self.length):
            random.seed(self.md5_str[:i])
            index = random.randint(0, len(base_str)-1)
            result.append(base_str[index])
        return result


if __name__ == "__main__":
    # change the keys to your own keys
    keys = 'customized keys'
    password = passwd('qq', 16, keys)
    password.genhash()
    result = password.random_choose()
    print(result)

由于是密码管理程序,如果只使用python,想在手机端查看自己密码的时候,就会很不妨方便,为此,创建一个flask应用,部署到自己的服务器,这样用手机打开自己的域名就可以访问,再配合bootstrap的响应式设计,手机端也有较好的使用体验。

下面是将该程序放进flask,并最终部署到服务器的过程。

flask创建

参考flask教程,创建好flask应用,这里不详细说明,python虚拟环境中需要安装的模块只有Flask。

创建完成后,将bootstrap和上面的generate.py放到flask目录中,代码结构如下:

.
├── app
│   ├── app.py
│   ├── generate.py
│   ├── static
│   └── templates
├── passwd.service
└── venv
    ├── bin
    ├── include
    ├── lib
    ├── lib64 -> lib
    └── pyvenv.cfg

其中passwd.service是后面会用到的,将flask设置开机启动的服务文件。

venv为Python虚拟环境的目录。app中存放flask的主要文件。

app.py内容如下:

from flask import Flask, jsonify, render_template, request, session, redirect, url_for
import random
import string
import math
import os
import generate
from flask import jsonify
app = Flask(__name__,static_url_path='')
app.config['SECRET_KEY']=os.urandom(24)


@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')


@app.route('/show_passwd/', methods=['GET', 'POST'])
def show_passwd():
    rem_name = request.form.get('rem_name')
    length = request.form.get('length')
    key = request.form.get('key')
    password = generate.passwd(rem_name, length, key)
    password.genhash()
    result = password.random_choose()
    result = ''.join(result)
    return render_template('result.html', result=result)
    # return ''.join(result)
    # return 'hello'

@app.route("/get_my_ip", methods=["GET"])
def get_my_ip():
    return jsonify({'ip': request.remote_addr}), 200


if __name__ == '__main__':
    app.run()

其他的文件就都是bootstrap的css和js,所有的文件都在我的githubopen in new window

uwsgi运行flask

在服务器端,为了稳定性和安全性,需要用uwsgi等程序运行flask.

passwd.service内容如下:

[Unit]
Description=flask for passwd
After=network.target
 
[Service]
User=git
Group=git
 
WorkingDirectory=/home/git/passwd/app
Environment="PATH=/home/git/passwd/venv/bin" 
ExecStart=/home/git/passwd/venv/bin/uwsgi --socket 0.0.0.0:8000 -p 3 -w app:app
PrivateTmp=true
 
[Install]
WantedBy=multi-user.target

User设置使用哪一个用户运行,group为用户所在的组,/home/git/passwd为该项目在linux服务器中存放的路径,将app这一级的所有文件和目录放置/home/git/passwd中即可,如果自己放在其他目录,对应修改即可。

将passwd.service放到/etc/systemd/system/, 再启动passwd.service并设置开机启动即可:

systemctl enable passwd.service
systemctl start passwd.service

nginx配置

添加nginx配置文件:

/etc/nginx/conf.d/flask.conf

添加以下内容:

server {
        listen 80;
	server_name www.yourdomain.com;
        location / {
            include uwsgi_params;
            uwsgi_pass 127.0.0.1:8000;
        }
}

其中,端口8000,与上述uwsgi设置成一样即可。可以自己修改。替换自己的域名。

最后重启nginx服务

systemctl restart nginx

配置ssl证书(可选)

使用Let‘s encript为网站配置ssl证书

Finally

最后,终于完成了整个过程,不出意外,在浏览器中输入自己设置的域名即可使用该程序了,手机端也可以。

Comments
  • Latest
  • Oldest
  • Hottest
Powered by Waline v3.1.3