3

通用密钥,无需密码,在无密码元年实现Passkeys通用密钥登录(基于Django4.2/Python3.10)...

 1 year ago
source link: https://www.cnblogs.com/v3ucn/p/17495992.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

毋庸讳言,密码是极其伟大的发明,但拜病毒和黑客所赐,一旦密码泄露,我们就得绞尽脑汁再想另外一个密码,但记忆力并不是一个靠谱的东西,一旦遗忘密码,也会造成严重的后果,2023年业界巨头Google已经率先支持了Passkeys登录方式,只须在设备上利用PIN码解锁、指纹或面部辨识等生物识别方式,即可验证身份,也就是说,可以和密码说拜拜了。

什么是PassKeys

Passkeys的原理很简单,就是在用户注册环节,可以选择生成一对密钥,分别是公钥和私钥,公钥存在服务器端,而私钥存在用户需要登录的设备上,包含但不限于电脑、手机、或者平板。

20230621110606_62967.png

只有在公钥和私钥配对,并且验签通过的情况下,系统才会判定用户登录成功,也就是说,就算黑客进入到了服务器,窃取到了用户的公钥,仍然无法伪造用户的身份。

另一方面,当我们在客户端登录账户的时候,可以选择安全性相对较高的PIN码解锁、指纹或面部辨识等生物识别方式解锁私钥,如此,就算设备不慎遗失,也可以确保私钥的安全性,不会被恶意使用。

以Google账户为例子,只需要登入Google的账号首页:

account.google.com

随后在右侧菜单选择安全性-》通行密钥,随后创建通行密钥即可,以后如果想登录Google账号的时候,直接使用通行密钥进行生物识别登录即可,当然,前提是当前设备需要支持指纹识别或者面部识别等功能,实在不行,也可以用pin码登录,比使用冗长的密码要方便多了。

如果需要通过多台设备进行登录,则可以在对应设备上创建不同的通行密钥,如此在任意设备登录账号都不需要输入密码了,需要注意的是,如果想把设备出售,可以在服务端直接删除公钥,这样设备中的私钥也会失效,确保账户的安全。

总的来说,Passkeys就是一种基于非对称加密算法的登录验证方式,只不过私钥和生物识别技术连结了起来,比传统私钥更加的安全,关于非对称加密算法,请移步:加密,各种加密,耙梳加密算法(Encryption)种类以及开发场景中的运用(Python3.10),这里不再赘述。

基于Django4.2实现

Google账户的Passkeys支持是极好的,那么如果我们想在自己的平台接入Passkeys功能, 该如何做呢?这里以基于Python3.10的Web框架Django4.2为例子进行演示。

首先安装Django4.2

pip3 install Django==4.2

接着安装相关的其他依赖:

cffi==1.15.1  
cryptography==38.0.1  
Django==4.2  
django-sslserver  
fido2==1.1.1  
pycparser==2.21  
pytz==2022.5  
sqlparse==0.4.3  
django-passkeys

可以放入requirements.txt进行批量安装。

随后在终端通过命令创建Django命令:

django-admin startproject test_app

需要注意的是,由于触发生物识别的接口只支持https协议,所以需要django-sslserver启动基于Https协议的后台服务,确保配置文件中已经进行配置:

# Application definition  
  
INSTALLED_APPS = [  
    'django.contrib.admin',  
    'django.contrib.auth',  
    'django.contrib.contenttypes',  
    'django.contrib.sessions',  
    'django.contrib.messages',  
    'django.contrib.staticfiles',  
    'test_app',  
    'passkeys',  
    'sslserver'  
]

随后,配置一下数据库:

DATABASES = {  
    'default': {  
        'ENGINE': 'django.db.backends.sqlite3',  
        'NAME': 'test_db',  
    }  
}

这里我们就使用默认的简易数据库sqlite3,当然换成Mysql也可以,原理都是一样的,数据库用来存储用户生成的公钥,存在服务端。

至此Django4.2就配置好了。

使用Openssl配置证书

想要启动基于Https协议的Django服务,需要单独配置SSL的证书,这里使用Openssl,下载地址是:

https://slproweb.com/products/Win32OpenSSL.html

下载后进行安装,别忘了配置环境变量,随后第一步,生成服务器私钥:

openssl genrsa -out server.key 2048

第二步,根据私钥和输入的信息生成证书请求文件:

openssl req -new -key server.key -out server.csr

第三步:用第一步的私钥和第二步的请求文件生成证书:

openssl x509 -req -in server.csr -out server.crt -signkey server.key -days 3650

这样我们就拿到了私钥server.key和证书server.crt。

在生产环境中,这些步骤对用户来说是不可见的,这里只是简单模拟,通常证书申请用户只需要将服务器的公钥(注意不是私钥)和服务器证书申请文件交给https证书厂商即可,之后https厂商会通过邮件回复一个服务器公钥证书,拿到这个证书和自己生成的服务器私钥就可以搭建https应用了。

需要注意的是,私钥长度必须大于1024,否则启动时会报密钥过短的错误,同时密钥如果过短,也会增加被破解的风险。

随后用证书启动Django服务:

python3 manage.py runsslserver --cert D:/Downloads/server.crt --key D:/Downloads/server.key  0.0.0.0:8000

程序返回:

Watching for file changes with StatReloader  
Validating models...  
  
System check identified some issues:  
  
WARNINGS:  
passkeys.UserPasskey: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.  
        HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.  
  
System check identified 1 issue (0 silenced).  
June 21, 2023 - 12:22:55  
Django version 4.2, using settings 'test_app.settings'  
Starting development server at https://0.0.0.0:8000/  
Using SSL certificate: D:/Downloads/server.crt  
Using SSL key: D:/Downloads/server.key  
Quit the server with CTRL-BREAK.

则代表没有问题,至此证书就配置好了。

使用Passkeys

现在,我们可以使用Passkeys功能了,首先迁移数据库:

python3 manage.py migrate

注意这一步并不需要model的支持,因为django-passkeys三方库会自动创建。

随后为Django-admin后台创建一个超级管理员:

python3 manage.py createsuperuser

程序返回:

System check identified some issues:  
  
WARNINGS:  
passkeys.UserPasskey: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.  
        HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.  
Username (leave blank to use 'zcxey'): admin  
Email address: [email protected]  
Password:  
Password (again):  
The password is too similar to the username.  
This password is too short. It must contain at least 8 characters.  
This password is too common.  
Bypass password validation and create user anyway? [y/N]: y  
Superuser created successfully.

这里创建了一个admin账号。

随后访问地址:https://localhost:8000 ,注意,必须是https协议。

随后在passkeys管理页面中创建私钥:

20230621120619_50222.png

由于笔者的电脑不支持生物识别,所以只能用pin码。

创建成功后,私钥会留在设备中,也就是客户端,通过生物识别来解锁。

而公钥则存在Django项目的Sqllite3数据库中,随时可以对用户的私钥进行验签操作。

下次登录的时候,只需要用私钥登录即可,把密码丢到九霄云外去吧:

20230621120657_11636.png

虽然这只是非对称加密算法的一次简单地落地实践,但却是用户登录体验的一次革命性的巨大提升,还在给1password软件付费?这笔开支可以省了,最后奉上Passkeys示例项目,与众乡亲同飨:

https://github.com/zcxey2911/Django4.2_Passkeys_Login_Demo

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK