Sevice Computing:简单 web 服务与客户端开发实战
1、项目概述
利用 web 客户端调用远端服务是服务开发本实验的重要内容。其中,要点建立 API First 的开发理念,实现前后端分离,使得团队协作变得更有效率。
任务目标
- 选择合适的 API 风格,实现从接口或资源(领域)建模,到 API 设计的过程
- 使用 API 工具,编制 API 描述文件,编译生成服务器、客户端原型
- 使用 Github 建立一个组织,通过 API 文档,实现 客户端项目 与 RESTful 服务项目同步开发
- 使用 API 设计工具提供 Mock 服务,两个团队独立测试 API
- 使用 travis 测试相关模块
2、我负责的部分
顶层设计:API设计及说明
首先对swapi原网页进行各种可能的操作,熟悉它所能够提供的API
3个页面:
注册页面,登录页面和查询页面。
这里我们设计了两种方式可以到达查询页面,一种是需要登录到用户界面,这就需要经过注册和登录两步,而另外一种是游客用户的形式,可以直接进到查询页面。
服务 API
我们设计的API可以实现如下内容:
1. 注册用户
/register POST
2. 用户登录
/login POST
3. 获取资源目录
/api/ GET
4. 获取films资源
/api/films/?page={id} GET
/api/films/pages GET
/api/films/{id} GET
5. 获取people资源
/api/people/?page={id} GET
/api/people/pages GET
/api/people/{id} GET
6. 获取planets资源
/api/planets/?page={id} GET
/api/planets/pages GET
/api/planets/{id} GET
7. 获取species资源
/api/species/?page={id} GET
/api/species/pages GET
/api/species/{id} GET
8. 获取starships资源
/api/starships/?page={id} GET
/api/starships/pages GET
/api/starships/{id} GET
9. 获取vehicles资源
/api/vehicles/?page={id} GET
/api/vehicles/pages GET
/api/vehicles/{id} GET
基于token的身份验证
基于 Token 的身份验证,比起传统的身份验证方法,Token 扩展性更强,也更安全点,非常适合用在 Web 应用或者移动应用上。Token 的中文有人翻译成 “令牌”,意思就是,你拿着这个令牌,才能过一些关卡。
传统身份验证的方法
HTTP 是一种没有状态的协议,也就是它并不知道是谁是访问应用。这里我们把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下回这个客户端再发送请求时候,还得再验证一下。
解决的方法就是 Session,当用户请求登录的时候,同时会在服务端生成一条记录,说明登录的用户是谁,并把这条记录的 ID 号发送给客户端,客户端收到以后把这个 ID 号存储在 Cookie 里,下次这个用户再向服务端发送请求的时候,可以带着这个 Cookie ,这样服务端会验证一个这个 Cookie 里的信息,看看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。我们需要在服务端存储为登录的用户生成的 Session ,这些 Session 可能会存储在内存,磁盘,或者数据库里。我们可能需要在服务端定期的去清理过期的 Session 。
基于 Token 的身份验证方法
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
- 客户端使用用户名跟密码请求登录
- 服务端收到请求,去验证用户名与密码
- 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
- 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
- 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
- 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
JWT
JWT是实施 Token 验证的一种标准方法。JWT 标准的 Token 有三个部分:
- header(头部)
- payload(数据)
- signature(签名)
token签发:
package models
import (
"fmt"
"net/http"
"github.com/dgrijalva/jwt-go"
"github.com/dgrijalva/jwt-go/request"
)
// 密钥
const secret = "WebDevelopingHW12"
type token struct {
Name string `json:"name"`
Exp string `json:"exp"`
}
func ValidateMid(w http.ResponseWriter, req *http.Request, next http.HandlerFunc) {
token, err := request.ParseFromRequest(req, request.AuthorizationHeaderExtractor,
func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
假设用户通过了某种身份验证,使用上面的签发 Token 的功能为用户签发一个 Token。一般在客户端那里会把它保存在 Cookie 或 LocalStorage 里面。
用户下次向我们的应用请求受保护的资源的时候,可以在请求里带着我们给它签发的这个 Token,后端应用收到请求,检查签名,如果验证通过确定这个 Token 是我们自己签发的,那就可以为用户响应回他需要的资源,把Token赋给Header的Authorization项。
token验证:
if err == nil {
if token.Valid {
next(w, req)
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Token is not valid")
}
} else {
w.WriteHeader(http.StatusUnauthorized)
fmt.Fprint(w, "Unauthorized access to this resource")
}
}
所有README.md的撰写,项目文档编写
这个部分主要是对整个项目进行整合,然后运行测试,以及根据安装、运行的过程给各个部分分别写一个说明性质的文档。