一个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 [email protected]),又扩展了一些我们会需要用到的东西,去掉了几个我们用不到的模块的编译来节省时间。但求能用,不求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(马赛克部分):

一个OpenResty里OAuth 2认证的轮子(上)_第1张图片
我的测试App

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

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

你可能感兴趣的:(一个OpenResty里OAuth 2认证的轮子(上))