模拟业务场景
在 上一篇 我们已经做足了准备工作,并拟定了具体的业务场景:
- 用户登录成功,颁发 TOKEN
- 客户端每一次对 TODO 模型进行 CRUD 操作时,都会携带 TOKEN
- 服务端会校验 TOKEN 合法性,给予响应请求的返回及数据库操作
在接下来的具体编码中,不会有表单验证、注册那些逻辑,
因为本文只是用于描述如何将 CI 集成为一个 JWT RESTfull API Repo。
定义模型
User_model.php
User 模型中,一个简单的 login 方法用于对比账号密码是否正确,我们仅仅只是模拟一下 HTTP 请求进行了真实的数据库操作:
由于没有写注册逻辑,你应该在数据库中提前增加一条用户数据,如:
Todo_model.php
Todo 模型中,新增、删除、修改、查询单条记录、查询全部记录等操作:
Authorization 辅助类
由于颁发 、验证 TOKEN 来自 JWT 类中的方法,为了能更方便的使用 JWT 类,我们可以在 CI 中封装自己的“辅助类”,自定义的辅助类放在 application/helpers/ 中。
在这个辅助类中,引入 JWT,并且在 Authorization 类中封装了两个方法:
func validateToken
- 用于校验 TOKEN 的合法性func generateToken
- 用于颁发 TOKEN
Autoload 配置项
为了能更方便的使用数据库,不用反复写 $this->load>library('database')
,
在 CI 中,我们可以将需要自动加载的特定 library、helper 等直接配置进 autoload 中。
Auth 控制器
准备了这么多,是时候写第一个控制器了,完成我们的场景一:
客户端发送 POST 请求,服务端通过 username & password 参数,颁发 TOKEN 返回给客户端。
接下来,我们需要在客户端中模拟这个“获取TOKEN”的 POST 请求。
打开接口调试工具,例如 Postman,我这里用的 apizza,
和 上一篇 一样,我们使用 php -S localhost:8000
运行项目,
在 apizza 中模拟我们这次的请求:
如果客户端传入的账户密码不存在,按照 Restfull 约定,服务端应该返回状态码为 401 Unauthorized:
Todo 控制器
该控制器会给予针对 Todo 模型的 CURD 操作的 API,通常服务端的 API URL 看起来应该像是这样的:
http://example.com/api/
CI 升级至 3.*
版本后控制器便能支持多级目录结构,现在我们来创建 Todo 控制器:
四个方法名分别对应了 GET、POST、PUT、DELETE 这四种请求方式。
POST 请求
todo 表现在仍然是一张空表,因此,我们从 POST 请求开始,这个请求通常用来创建资源:
创建成功,接口将会返回 200 状态码,并将新创建的 todo 记录作为返回数据,
现在我们发出几次请求,让 API 为我们在数据库中插入 3 条记录:
GET 请求
现在表中有了 3 条记录,编写 GET 请求来进行获取资源:
- 服务端查看 URL 中是否有 id 参数,如果有则返回该 id 的单条数据
- 若没有,则返回全部数据,
当然这个示例并没有校验 id 的合法性,也没有处理 404 的错误,实际开发你应该补充这些逻辑:
单条记录
全部记录
PUT 请求
PUT 通常用来修改某个指定的资源:
DELETE 请求
DELETE 用于删除指定的资源:
钩子函数
至此,我们全部的 API 编写完毕,
接下来,也是最后一步,我们还需要加入钩子函数,校验令牌的合法性。
- 再次打开
application/config/config.php
开启hooks
- 指定 hooks
CI 总共有 7 种钩子,这里我们选择 post_controller_constructor
,
它会在你的控制器实例化之后立即执行,控制器的任何方法都还尚未调用
需要在钩子配置中指定我们将要使用的自定义钩子类以及执行的函数名称:
- 编写 ApiAuthHook
保护路由
当我们再次访问任意一个 API 请求时,服务端会回应一个 400 的 Error Code:
还记得第一个 POST /auth/token
吗?
这个请求服务端返回了 TOKEN,
在请求头中加入 { "Authorization": "bear TOKEN" }
接口正常返回了全部数据!
为什么 bear 设置为 lovchun.com?
前端需要通过 cookie
或者 localstorage
来存储 TOKEN,以此来保存调用接口的凭据,
试想一下,如果你的前端工程需要对接多个 API Server,
通过什么来标识 TOKEN 分别对应着哪个 Server ?
将 Authorization 的值用“唯一标识”+“一个英文空格”+“TOKEN”来存储,
服务端校验时,通过搜索该“唯一标识”的 Authorization 来获取 TOKEN。
当然这个标识你完全可以自定义
如果你是以 Apache 启动项目,Apache 会过滤掉请求头中的 Authorization 字段,
需要对根目录中的 .htaccess
进行修改才能让你的 Apache 正常接收 Authorization: