🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 程序员开发指南 ## 服务端开发指南 ### API接口规范 ### 消息规范 系统使用统一的消息返回机制,所有的API返回JSON数据,格式一致。如果所请求的API需要授权,而用户没有获得授权,直接抛出HTTP:401错误,客户端检测到401状态直接跳转到登录页面进行授权。 ```json { errno: 1000, errmsg: '错误消息', data: {} } ``` | 字段 | 含义 | 说明 | | ------ | ------ | ------ | | errno | 错误代码 | 通常返回 0,表示请求正常返回接口数据;如果请求出错,返回具体的错误代码,并在data字段返回错误的附加信息 | | errmsg | 错误消息 | 返回数据的解释性描述文字 | | data | 返回的业务数据 | 一般返回对象格式 | > 错误代码 | 错误代码 | 含义 | 说明 | | ------ | ------ | ------ | | 0 | 正常返回 | 请求的接口正确的返回业务数据,非0表示请求出错 | | 1000 | 一般错误 | 通用的错误代码 | | 1001 | 请求接口参数校验错误 | 参数格式、类型不正确等 | ## 客户端开发指南 ### 发送请求 >所有的请求被封装成Promise 以下请求用户传递用户名和密码,返回通信的TOKEN ``` let userInfo = { username : 'admin', password : '123456' } ``` 发送请求到`/api/system/token/create`接口, 由于request集中处理请求,自动加上了请求的前缀`api`,所以客户端编写API的时候不需要再加上api前缀。 ## 前后端通信机制 ```javascript import request from '@/common/request' export default { create(userInfo) { return new Promise((resolve, reject) => { request.post('/system/token/create', userInfo).then(response => { resolve(response) }) }) } } ``` 前后端的通信使用TOKEN机制,TOKEN放在请求的header中。 用户通过读取vuex保存的token,发送给服务端 ``` const token = store.getters['token']; if (token) { //给所有请求添加自定义header request.headers["Authorization"] = token; } ``` 服务端首先通过framework中间件校验客户端发送的TOKEN是否合法,如果篡改了TOKEN或者TOKEN过期,则删除传递的用户信息,后续进一步判断请求的API是否需要检测用户身份。 ``` //分离请求用户的身份信息,业务上要求某些API只能用户自身才能访问,所以需要提取登录用户的信息 let userInfo = {}; //发起请求的用户基本信息 //读取请求用户的身份信息 const authorization = ctx.request.header.authorization;//解码客户端请求携带的用户信息 try { //将用户信息写入到context,这样每一个控制器都可以读到 userInfo = jsonwebtoken.verify(authorization, ctx.config('jwt')['secret']); delete userInfo.iat; //删除附上去的字段信息 delete userInfo.exp; //校验客户端传过来的TOKEN是否被改过 md5_old = userInfo.md5; let tmp = think.extend({}, userInfo); delete tmp.md5; let md5_new = think.service('utils').getVerifiedUserInfo(tmp) if (md5_new === md5_old) { ctx.userInfo = userInfo; } else { ctx.userInfo = {}; userInfo = {}; } } catch (err) { ctx.userInfo = {}; userInfo = {}; } ... // 检测登录的用户信息 // 必须登陆 if (think.isEmpty(userInfo) || think.isEmpty(userInfo.username)) { return ctx.throw(401, `请登录以后访问。`); } ```