**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - [learn koa2--认证](#learn-koa2--%E8%AE%A4%E8%AF%81) - [session](#session) - [`session`](#session) - [`generic-session`](#generic-session) - [`session`加密](#session%E5%8A%A0%E5%AF%86) - [use session](#use-session) - [csrf](#csrf) - [附加--使用github作为第三方登录](#%E9%99%84%E5%8A%A0--%E4%BD%BF%E7%94%A8github%E4%BD%9C%E4%B8%BA%E7%AC%AC%E4%B8%89%E6%96%B9%E7%99%BB%E5%BD%95) - [准备](#%E5%87%86%E5%A4%87) - [实战](#%E5%AE%9E%E6%88%98) ## learn koa2--认证 > 本章涉及session,csrf ### session #### `session` - [`koa-session`](https://github.com/koajs/session) > 基于cookie的session中间件 ```bash $ npm install koa-session ``` `koa-session`本身是基于`koa1`的中间件,因此我们还需要`koa-convert` ```bash $ npm install koa-convert --save ``` ```javascript import Koa from 'koa'; import convert from 'koa-convert'; import session from 'koa-session'; const app = new Koa(); app.keys = ['keys']; // session app.use(convert(session(app))); ``` #### `generic-session` > 使用内存进行session的储存 我们使用`mongo`作为session的储存。需要安装一下两者: - [`koa-generic-session`](https://github.com/koajs/generic-session) - [`koa-generic-session-mongo`](https://github.com/pavelvlasov/koa-generic-session-mongo) ```bash $ npm install koa-generic-session koa-generic-session-mongo --save ``` 同样,`koa-generic-session`本身是基于`koa1`的中间件,需要`koa-convert` ```bash $ npm install koa-convert --save ``` ```javascript import Koa from 'koa'; import convert from 'koa-convert'; import session from 'koa-generic-session'; import MongoStore from 'koa-generic-session-mongo'; const app = new Koa(); app.keys = ['keys']; // session app.use(convert(session({ store: new MongoStore() }))); ``` #### `session`加密 注意到上面两种session在初始化的时候,都有`app.keys = ['keys'];`这句话吗?因为两者session在默认情况下都进行了加密配置(`signed`),必须用`app.keys`指定加密短语。 实际上在使用过程中,往往在生产环节下赋予`app.keys`一个独特的加密配置,对外不可见。 #### use session 举个栗子 ```javascript // ... app.use((ctx, next) => { let n = ctx.session.num || 0; console.log(n); ctx.session.num = n + 1; }); ``` ### csrf > 基本上是必装插件,防止跨域挟持 - [`koa-csrf`](https://github.com/koajs/csrf) ```bash # for koa2 $ npm install --save koa-csrf@3.x # csrf基于session,所以如果没有安装session则需要按照上文安装session ``` ```javascript import Koa from 'koa'; import csrf from 'koa-csrf'; import session from 'koa-session'; import convert from 'koa-convert'; const app = new Koa(); // 加密 app.keys = ['keys']; // session app.use(session(app)); // csrf // 必须放在session后面 app.use(new csrf()); // usage app.use(async (ctx, next) => { await ctx.render('home/index', { title: 'home page', content: 'this is home page', csrf: ctx.csrf }); }); ``` 在模板中: ```html
``` ### 附加--使用github作为第三方登录 使用github官方提供的`OAuth2`认证,可以快速的实现基于github的第三方登录 #### 准备 首先要[注册一个自己的应用](https://github.com/settings/applications/new): - `Homepage URL`:应用主页,本地测试时可填`localhost:XXXX` - `Authorization callback URL`:用户同意github授权之后的回调URL,会在这里通过`request body`拿到github提供的`code`,作为获取用户`token`的条件之一 我们创建完成之后,如下图所示:  因此之后必然会创建一个`/user/login/github/`的路由来处理回调。整个流程大致这样: 1. 用户要通过github进行第三方认证,点击链接跳转到`https://github.com/login/oauth/authorize?scope=XXX%20YYY&client_id=XXXXX`页面,其中,`scope`代表我们[要获取的权限](https://developer.github.com/v3/oauth/#scopes),`client_id`则是刚刚新建应用的id 2. 在用户同意认证之后,跳转到回调页面,但`request`带有参数`?code=XXXXX`,我们需要拿到这个`code` 3. 在服务端向`https://github.com/login/oauth/access_token`发出`POST`请求,并带上`client_id`,`client_secred`,`code`三个参数,从返回值中获取`access_token` 4. 在服务端发出`GET`请求,通过`https://api.github.com/user?access_token=XXX`请求,获取用户的个人公开信息(会根据第一步的`scope`有所不同),并将所需信息和`access_token`储存在`session`里 可以参考的官方资料: - [注册新应用](https://github.com/settings/applications/new) - [注册一个个人使用的`access_token`](https://github.com/settings/tokens/new) - `github OAuth2` - [关于`oauth`](https://developer.github.com/guides/getting-started/#oauth) - [流程梳理](https://developer.github.com/v3/oauth/#web-application-flow) - [用户权限列表](https://developer.github.com/v3/oauth/#scopes) - [常见错误](https://developer.github.com/v3/oauth/#common-errors-for-the-authorization-request) - [需要使用`user-agent`](https://developer.github.com/v3/#user-agent-required) - [一些第三方封装的`github api`请求库](https://developer.github.com/libraries) #### 实战 首先新建一个用户界面的view,在没有授权的情况下,展现github授权链接,否则显示退出登录链接: ```html {% extends "layouts/base.html" %} {% block body %}