百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

无密码验证服务器

toyiye 2024-06-21 12:23 14 浏览 0 评论

无密码验证可以让你只输入一个 email 而无需输入密码即可登入系统。这是一种比传统的电子邮件/密码验证方式登入更安全的方法。

下面我将为你展示,如何在 Go 中实现一个 HTTP API 去提供这种服务。

流程

  • 用户输入他的电子邮件地址。
  • 服务器创建一个临时的一次性使用的代码(就像一个临时密码一样)关联到用户,然后给用户邮箱中发送一个“魔法链接”。
  • 用户点击魔法链接。
  • 服务器提取魔法链接中的代码,获取关联的用户,并且使用一个新的 JWT 重定向到客户端。
  • 在每次有新请求时,客户端使用 JWT 去验证用户。

必需条件

  • 数据库:我们为这个服务使用了一个叫 CockroachDB 的 SQL 数据库。它非常像 postgres,但它是用 Go 写的。
  • SMTP 服务器:我们将使用一个第三方的邮件服务器去发送邮件。开发的时我们使用 mailtrap。Mailtrap 发送所有的邮件到它的收件箱,因此,你在测试时不需要创建多个假邮件帐户。

从 Go 的主页 上安装它,然后使用 go version(1.10.1 atm)命令去检查它能否正常工作。

从 CockroachDB 的主页 上下载它,展开它并添加到你的 PATH 变量中。使用 cockroach version(2.0 atm)命令检查它能否正常工作。

数据库模式

现在,我们在 GOPATH 目录下为这个项目创建一个目录,然后使用 cockroach start 启动一个新的 CockroachDB 节点:

cockroach start --insecure --host 127.0.0.1

它会输出一些内容,找到 SQL 地址行,它将显示像 postgresql://root@127.0.0.1:26257?sslmode=disable 这样的内容。稍后我们将使用它去连接到数据库。

使用如下的内容去创建一个 schema.sql 文件。

DROP DATABASE IF EXISTS passwordless_demo CASCADE;
CREATE DATABASE IF NOT EXISTS passwordless_demo;
SET DATABASE = passwordless_demo;

CREATE TABLE IF NOT EXISTS users (
 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
 email STRING UNIQUE,
 username STRING UNIQUE
);

CREATE TABLE IF NOT EXISTS verification_codes (
 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
 user_id UUID NOT NULL REFERENCES users ON DELETE CASCADE,
 created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

INSERT INTO users (email, username) VALUES
 ('john@passwordless.local', 'john_doe');

这个脚本创建了一个名为 passwordless_demo 的数据库、两个名为 users 和 verification_codes 的表,以及为了稍后测试而插入的一些假用户。每个验证代码都与用户关联并保存创建时间,以用于去检查验证代码是否过期。

在另外的终端中使用 cockroach sql 命令去运行这个脚本:

cat schema.sql | cockroach sql --insecure

环境配置

需要配置两个环境变量:SMTP_USERNAME 和 SMTP_PASSWORD,你可以从你的 mailtrap 帐户中获得它们。将在我们的程序中用到它们。

Go 依赖

我们需要下列的 Go 包:

  • github.com/lib/pq:它是 CockroachDB 使用的 postgres 驱动
  • github.com/matryer/way: 路由器
  • github.com/dgrijalva/jwt-go: JWT 实现
go get -u github.com/lib/pq
go get -u github.com/matryer/way
go get -u github.com/dgrijalva/jwt-go

代码

初始化函数

创建 main.go 并且通过 init 函数里的环境变量中取得一些配置来启动。

var config struct {
 port int
 appURL *url.URL
 databaseURL string
 jwtKey []byte
 smtpAddr string
 smtpAuth smtp.Auth
}

func init() {
 config.port, _ = strconv.Atoi(env("PORT", "80"))
 config.appURL, _ = url.Parse(env("APP_URL", "http://localhost:"+strconv.Itoa(config.port)+"/"))
 config.databaseURL = env("DATABASE_URL", "postgresql://root@127.0.0.1:26257/passwordless_demo?sslmode=disable")
 config.jwtKey = []byte(env("JWT_KEY", "super-duper-secret-key"))
 smtpHost := env("SMTP_HOST", "smtp.mailtrap.io")
 config.smtpAddr = net.JoinHostPort(smtpHost, env("SMTP_PORT", "25"))
 smtpUsername, ok := os.LookupEnv("SMTP_USERNAME")
 if !ok {
 log.Fatalln("could not find SMTP_USERNAME on environment variables")
 }
 smtpPassword, ok := os.LookupEnv("SMTP_PASSWORD")
 if !ok {
 log.Fatalln("could not find SMTP_PASSWORD on environment variables")
 }
 config.smtpAuth = smtp.PlainAuth("", smtpUsername, smtpPassword, smtpHost)
}

func env(key, fallbackValue string) string {
 v, ok := os.LookupEnv(key)
 if !ok {
 return fallbackValue
 }
 return v
}

  • appURL 将去构建我们的 “魔法链接”。
  • port 将要启动的 HTTP 服务器。
  • databaseURL 是 CockroachDB 地址,我添加 /passwordless_demo 前面的数据库地址去表示数据库名字。
  • jwtKey 用于签名 JWT。
  • smtpAddr 是 SMTP_HOST + SMTP_PORT 的联合;我们将使用它去发送邮件。
  • smtpUsername 和 smtpPassword 是两个必需的变量。
  • smtpAuth 也是用于发送邮件。

env 函数允许我们去获得环境变量,不存在时返回一个回退值。

主函数

var db *sql.DB

func main() {
 var err error
 if db, err = sql.Open("postgres", config.databaseURL); err != nil {
 log.Fatalf("could not open database connection: %v\n", err)
 }
 defer db.Close()
 if err = db.Ping(); err != nil {
 log.Fatalf("could not ping to database: %v\n", err)
 }

 router := way.NewRouter()
 router.HandleFunc("POST", "/api/users", jsonRequired(createUser))
 router.HandleFunc("POST", "/api/passwordless/start", jsonRequired(passwordlessStart))
 router.HandleFunc("GET", "/api/passwordless/verify_redirect", passwordlessVerifyRedirect)
 router.Handle("GET", "/api/auth_user", authRequired(getAuthUser))

 addr := fmt.Sprintf(":%d", config.port)
 log.Printf("starting server at %s 

相关推荐

「2022 年」崔庆才 Python3 爬虫教程 - 代理的使用方法

前面我们介绍了多种请求库,如urllib、requests、Selenium、Playwright等用法,但是没有统一梳理代理的设置方法,本节我们来针对这些库来梳理下代理的设置方法。1.准备工作...

Python 3 基础教程 - 函数(python基础函数大全)

函数是一组有组织的、可重用的代码,用于执行单个相关操作。函数为应用程序提供更好的模块化和高度的代码重用。Python提供了许多内置函数,如print()等。也可以创建自己的函数。这些函数称为用户...

Python3.7.4图文安装教程(python3.7详细安装教程)

Python更新的很快,一转眼Python2已经过时了,本文为大家详细说明Python最新版本3.7.4的安装过程,跟着步骤一步一步操作,轻松搞定安装。没有软件可以关注我头条私信我1、下载好后是一个压...

非程序员的其他从业者,三天可入门Python编程,附教程与相应工具

这是一种应用十分广泛的编程语言Python,它打破了只有程序员才能编程的“戒律”,尤其是近年来国家予以Python编程的支持,让这门语言几乎应用到各种工作中。那么对于并不是职业程序员的人,该如何才能快...

008 - 匿名函数lambda-python3-cookbook中文教程

有名函数通过def来定义有一个有名字的函数。defmyfun():return1,2,3...

花了3万多买的python教程全套,现在分享给大家(python全栈)

花了3万多买的Python教程全套,现在分享给大家(Python全栈)文末惊喜记得看完哦。...

花来3万多买的python教程全套,现在分享给大家(python全栈)

花了3万多买的Python教程全套,现在分享给大家(Python全栈)文末惊喜记得看完哦。...

Python3最新版安装教程(Windows)(python3.7.0安装教程win10)

接下来给大家讲解一下python最新安装包的安装教程。·首先大家可以去这里搜索一下我的笔记,大概讲了一下,然后找到它的官网,下载的是windows,可以看一下最新的版本。·选择64位,点击下载就即可了...

笨办法学python3》再笨的人都能学会python,附PDF,拿走不谢

《笨办法学python3》这本书的最终目标是让你起步python编程,虽然说是用“笨办法”学习写程序,但是其实并不是这样的。所谓的“笨办法”就是指这本书的教学方式,也就是“指令式”的教学,在这个过程中...

python3 (1)(python312)

Python3Introduction:LearnthebasicsofPython3programming,withitskeyfeatures,andprovideyo...

Python3 教程-- 3、解释器(python3菜鸟教程官网)

Python3解释器Python解释器Linux/Unix的系统上,Python解释器通常被安装在/usr/local/bin/python3.4这样的有效路径(目录)里。我们可以将路径/us...

《笨办法学python3》再笨的人都能学会python,附PDF,拿走不谢

《笨办法学python3》这本书的最终目标是让你起步python编程,虽然说是用“笨办法”学习写程序,但是其实并不是这样的。所谓的“笨办法”就是指这本书的教学方式,也就是“指令式”的教学,在这个过程中...

入门经典!《Python 3程序开发指南》python学习教程赠送!

《Python3程序开发指南》(????)??嗨!你们的小可爱又来辣,小编自学python时用到的视频学习教程分享给大家~都是非常系统性、非常详细的教程哦,希望能帮助到你!转发文章+私信小编“资料”...

Python3.7最新安装教程,一看就会

一、博主自言随着人工智能的快速发展,python语言越来越受大家的欢迎,博主前段时间先自学了一次,这次再次巩固,顺便分享给大家我遇到的坑。帮助大家学习的时候少走弯路。希望会对大家有所帮助,欢迎留言...

# Python 3 # Python 3 教程(#python3.10教程)

Python3教程Python的3.0版本,常被称为Python3000,或简称Py3k。相对于Python的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python3....

取消回复欢迎 发表评论:

请填写验证码