一个OpenResty里OAuth 2认证的轮子(上)

写在前面:本文只水水地讨论如何去登陆一个OAuth平台并获取用户信息,并没有涉及如何实现一个OAuth平台


更新:
本系列中篇
本系列下篇
本系列补遗


OpenResty一直是我很看好的后端技术栈:在Nginx的高性能Web服务器基础上,用Lua这个精巧的语言来扩展业务逻辑的编写能力;工具的封装也非常干净好用,看上去挺符合我对“小而美”的理解。

之前用过OpenResty写了一些不太复杂的东西,主要还是偏向业务相关为主。但长久以来我一直想用OpenResty做些更偏基础设施、或者更基础协议方面的东西。一年多前在网上找了一阵子,发现好像没有一个相对精简而独立的OAuth 2库(嗯是的其实是我眼瞎,这个库在两年前就挂在Github上了),便萌生了自己做一个的想法——显然已经被磨磨叽叽地拖延了一年多——一半是因为自己的拖延症一半是因为自己的水平菜。

最近终于不能忍受如此没有效率的自己,擦亮屏幕读文档撸起袖管写代码,还真搞得差不多了。多说无益,放码过来吧!

首先,我们先建一个文件夹来放项目的所有东西:

$ mkdir -p demo/resty/{conf,logs}
$ cd demo

要做一个良心demo,最重要的是大家都跑得起来。所以我这里用Docker来隔离平台上的区别。为了节省大家宝贵的带宽,我贴一个简单的Dockerfile,这个是基于OpenResty官方Alpine版本(原维护人Evan Wies evan@neomantra.net),又扩展了一些我们会需要用到的东西,去掉了几个我们用不到的模块的编译来节省时间。但求能用,不求Dockerfile编写的最佳实践,把下面东西扔进项目根目录的Dockerfile里就好:

# Dockerfile
FROM alpine:latest

# Docker Build Arguments
ARG RESTY_VERSION="1.11.2.3"
ARG RESTY_OPENSSL_VERSION="1.0.2k"
ARG RESTY_PCRE_VERSION="8.39"
ARG RESTY_J="1"
ARG RESTY_CONFIG_OPTIONS="\
    --with-http_addition_module \
    --with-pcre-jit \
    "

# These are not intended to be user-specified
ARG _RESTY_CONFIG_DEPS="--with-openssl=/tmp/openssl-${RESTY_OPENSSL_VERSION} --with-pcre=/tmp/pcre-${RESTY_PCRE_VERSION}"


# 1) Install apk dependencies
# 2) Download and untar OpenSSL, PCRE, and OpenResty
# 3) Build OpenResty
# 4) Cleanup

RUN \
    apk add --no-cache --virtual .build-deps \
        build-base \
        gd-dev \
        geoip-dev \
        libxslt-dev \
        linux-headers \
        make \
        perl-dev \
        readline-dev \
        zlib-dev \
    && apk add --no-cache \
        gd \
        geoip \
        libgcc \
        libxslt \
        zlib \
        curl \
        perl \
    && cd /tmp \
    && curl -fSL https://www.openssl.org/source/openssl-${RESTY_OPENSSL_VERSION}.tar.gz -o openssl-${RESTY_OPENSSL_VERSION}.tar.gz \
    && tar xzf openssl-${RESTY_OPENSSL_VERSION}.tar.gz \
    && curl -fSL https://ftp.pcre.org/pub/pcre/pcre-${RESTY_PCRE_VERSION}.tar.gz -o pcre-${RESTY_PCRE_VERSION}.tar.gz \
    && tar xzf pcre-${RESTY_PCRE_VERSION}.tar.gz \
    && curl -fSL https://openresty.org/download/openresty-${RESTY_VERSION}.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \
    && tar xzf openresty-${RESTY_VERSION}.tar.gz \
    && cd /tmp/openresty-${RESTY_VERSION} \
    && ./configure -j${RESTY_J} ${_RESTY_CONFIG_DEPS} ${RESTY_CONFIG_OPTIONS} \
    && make -j${RESTY_J} \
    && make -j${RESTY_J} install \
    && cd /tmp \
    && rm -rf \
        openssl-${RESTY_OPENSSL_VERSION} \
        openssl-${RESTY_OPENSSL_VERSION}.tar.gz \
        openresty-${RESTY_VERSION}.tar.gz openresty-${RESTY_VERSION} \
        pcre-${RESTY_PCRE_VERSION}.tar.gz pcre-${RESTY_PCRE_VERSION} \
    && apk del .build-deps \
    && ln -sf /dev/stdout /usr/local/openresty/nginx/logs/access.log \
    && ln -sf /dev/stderr /usr/local/openresty/nginx/logs/error.log

# Add additional binaries into PATH for convenience
ENV PATH=$PATH:/usr/local/openresty/luajit/bin/:/usr/local/openresty/nginx/sbin/:/usr/local/openresty/bin/

RUN opm get bungle/lua-resty-session && opm get pintsized/lua-resty-http

如果要图方便,还可以再搞一个docker-compose的配置,不然直接用Docker的原生命令也可以(command里跑的东西后面会提到):

# docker-compose.yml
web:
  build: .
  ports:
    - "80:80"
  volumes:
    - .:/var/www/demo
  command: "sh -c 'openresty -p /var/www/demo/resty && tail -f /var/www/demo/resty/logs/error.log'"

接下来就到了愉快的写(tie)代(pei)码(zhi)时间!把下面的东西扔进 resty/conf/nginx.conf 文件里:

worker_processes  1;
error_log logs/error.log debug;
events { worker_connections 1024; }

http {
  server {
    listen 80;

    location / {
      content_by_lua_block {
        ngx.say('hello world')
      }
    }
  }
}

现在我们项目文件夹里的东西应该有这些:

$ tree
.
├── Dockerfile
├── docker-compose.yml
└── resty
    ├── conf
    │   └── nginx.conf
    └── logs

3 directories, 3 files

激动人心的时刻到了!轻敲 docker-compose up,整个屏幕就会布满酷炫的容器构建信息。构建完之后,简单测试一下:

$ curl -v localhost
* Rebuilt URL to: localhost/
*   Trying ::1...
* connect to ::1 port 80 failed: Connection refused
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty/1.11.2.3
< Date: Fri, 30 Jun 2017 02:51:34 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Connection: keep-alive
<
hello world
* Connection #0 to host localhost left intact

俗话说,良好的Hello World是成功的一半,现在Demo里Nginx和OpenResty相关的部分都很直接,大家应该都能读懂,唯一稍微解释一下的就是compose配置里的那句 openresty -p /var/www/demo:OpenResty有一个命令 openresty,和Nginx的 nginx 命令几乎一样,所以说 -p 所做的就是指定启动路径啦:

$ openresty -h
nginx version: openresty/1.11.2.3
Usage: nginx [-?hvVtTq] [-s signal] [-c filename] [-p prefix] [-g directives]

Options:
  -?,-h         : this help
  -v            : show version and exit
  -V            : show version and configure options then exit
  -t            : test configuration and exit
  -T            : test configuration, dump it and exit
  -q            : suppress non-error messages during configuration testing
  -s signal     : send signal to a master process: stop, quit, reopen, reload
  -p prefix     : set prefix path (default: /usr/local/openresty/nginx/)
  -c filename   : set configuration file (default: conf/nginx.conf)
  -g directives : set global directives out of configuration file

现在趁自己还在一种兴奋和喜悦之中——赶紧把一些无聊的事情做了:注册一个OAuth App。我在这个项目中会用世界最大的码农交友社区Github的登录来做例子,大家可以翻一下它的新App注册流程,非常简单直观,注册完就会得到对应的Client ID和Client Secret(马赛克部分):

我的测试App

截图最下面的那个URL,是OAuth验证的回调,到时候我们还会用得上。

上部就先写到这里,主要搭建了一个能在Docker里跑起来的OpenResty实例,注册了一个Github的App,剩下还有一个准备工作,就是需要阅读并理解OAuth 2的登录流程,这块大家可以参考阮一峰的一篇旧博客——我知道他在微博上被喷得很厉害,但是这篇博客作为OAuth 2的流程入门还是不错的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,881评论 4 368
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,052评论 1 301
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,598评论 0 250
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,407评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,823评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,872评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,037评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,778评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,505评论 1 247
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,745评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,233评论 1 264
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,568评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,231评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,141评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,939评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,954评论 2 283
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,784评论 2 275

推荐阅读更多精彩内容