使用Rails构建一个TO-DO应用的JSON API (Part II)

在第一部分中,我们创建了基于JSON API的Rails应用,搭建了Rspec测试框架,也介绍了简单的测试驱动的开发。在第二部分中,我们要建立JWT认证(JSON Web Token),包换注册和登录,当然还是使用TDD。认证原理的外链

认证涉及到用户,那先创建用户

建立model的测试,spec/models/user_spec.rb

添加固件,spec/factories/users.rb

添加model的约束,app/models/user.rb

has_secure_password,rails5会自动添加相关属性password_digest,经过信息摘要处理的password,总不能在数据库里存储明文密码吧。检查gemfile确认存在

接下去要做的几件事情:
1. JsonWebToken: Encode & decode jwt tokens
2. AuthorizeApiRequest: 每一个API请求的认证
3. AuthenticateUser:  认证用户
4. AuthenticationController:认证流程

JsonWebToken

什么是基于token的认证,外链,确认Gemfile里面有

然后我们会把生成jwt token的class放在lib目录下,因为这不是领域特定的。但是lib目录下的所有内容是自动加载的。但是Rails 5中因为线程问题,取消了自动加载,关于这个问题的讨论,外链

定义这个单例,app/lib/json_web_token.rb

这是标准写法😄,包含encode和decode两个方法。encode方法负责生产token,使用payload,这里是user id,还有确定失效时间。因为每个Rails应用都有一个唯一的secret key, 干脆就依据它来产生token。能看到decode是一个相反的过程,使用了相同的secret key。如果token过期或者无法decode,那么所有错误我们在Exception Handler中统一处理

每一个Request的认证

用户认证以后,每次请求当中都会带一个token表示当前用户。现在创建认证服务

编辑spec/auth/authorize_api_request_spec.rb

简单解释下,call方法是入口,先要一个认证的用户,登陆也好,注册也好,结果就是有一个用户被server认证了。看到两个方法还没有被定义,token_generator和expired_token_generator

创建并编辑它

这太明显了,看字面意思就是了,不多解释。然后要把这个module包含在rails helper中,我们才能使用。编辑rails_helper.rb,全局有效,不只是request

接下去,编辑app/auth/authorize_api_request.rb,生成对应的路由和方法

看到Message.missing_token对吧,我们对所有的详消息做一个封装,app/lib/message.rb

认证用户

就是登陆注册的功能

先写测试,看到authenticate_user_spec.rb

AuthenticateUser入口是call方法,注释已经说明一切,编辑authenticate_user.rb

收到email和password,检查如果是有效的就返回一个依据userid产生的token

测试下

应该都是通过的

认证流程

要建立controller

先写测试,看到spec/requests/authentication_spec.rb

编辑对应的控制器,app/controllers/authentication_controller.rb

最后增加路径,编辑config/routes.rb

在认证用户之前,这个用户总得注册对吧,这属于user的行为,放到User Controller 中解决,建立控制器和对应的request测试文件

还是先写测试,看到spec/requests/users_spec.rb

编辑路由,config/routes.rb,增加

编辑控制器

嗯,还差一件事情,就是直接访问的API的时候,必须要有token,在基类控制器中可以做一个全局的限制。先写测试,spec/controllers/application_controller_spec.rb

修改控制器基类,app/controllers/application_controller.rb

现在是对所有的request做限制,但是我在注册和登录操作中是没有token的,所以再加一句话

还有user controller,app/controllers/users_controller.rb

如果现在运行测试,肯定不通过,要更新测试用例,现在加了认证,编辑spec/requests/todos_spec.rb

还要更新todos_controller.rb,增加user和todo的关联

同样的,我们更新spec/requests/items_spec.rb

现在运行测试用例,应该是全部通过的,如果有异常,看提示自行处理。没问题的话,自己在本地用Postman或者httpie手动测试下



发表评论

电子邮件地址不会被公开。 必填项已用*标注