相關閱讀:
完爆Facebook/GraphQL,APIJSON全方位對比解析(一)-基礎功能
完爆Facebook/GraphQL,APIJSON全方位對比解析(三)-表關聯查詢
自APIJSON釋出以來,不斷有網友拿來和Facebook的GraphQL對比,
甚至有不少人聲稱“完爆”APIJSON。
然而事實正好相反,本系列部落格將以大量真實依據來證明,
APIJSON“完爆”GraphQL!
APIJSON的口號是:
後端介面和文件自動化,前端(客戶端) 定製返回JSON的資料和結構!
APIJSON的簡介:APIJSON是一種為API而生的JSON網路傳輸協議。
為 簡單的增刪改查、複雜的查詢、簡單的事務操作 提供了完全自動化的API。
能大幅降低開發和溝通成本,簡化開發流程,縮短開發週期。
適合中小型前後端分離的專案,尤其是網際網路創業專案和企業自用專案。
通過自動化API,前端可以定製任何資料、任何結構!
大部分HTTP請求後端再也不用寫介面了,更不用寫文件了!
前端再也不用和後端溝通介面或文件問題了!再也不會被文件各種錯誤坑了!
後端再也不用為了相容舊介面寫新版介面和文件了!再也不會被前端隨時隨地沒完沒了地煩了!
特點功能
線上解析
- 自動生成文件,清晰可讀永遠最新
- 自動生成請求程式碼,支援Android和iOS
- 自動生成JavaBean檔案,一鍵下載
- 自動管理與測試介面用例,一鍵共享
- 自動校驗與格式化JSON,支援高亮和收展
對於前端
- 不用再向後端催介面、求文件
- 資料和結構完全定製,要啥有啥
- 看請求知結果,所求即所得
- 可一次獲取任何資料、任何結構
- 能去除重複資料,節省流量提高速度
對於後端
- 提供通用介面,大部分API不用再寫
- 自動生成文件,不用再編寫和維護
- 自動校驗許可權、自動管理版本
- 開放API無需劃分版本,始終保持相容
- 支援增刪改查、模糊搜尋、正則匹配、遠端函式等
視訊演示:i.youku.com/apijson
專案主頁: github.com/TommyLemon/…
完爆Facebook/GraphQL,APIJSON全方位對比解析(二)-許可權控制
自動化許可權控制(APIJSON特有):
GraphQL【沒有】提供許可權控制的功能,甚至在官方文件和原始碼裡連如何實現的教程也幾乎沒有,
而僅僅提及瞭如何在你的【業務程式碼】裡去【手動】實現一個【所屬人】角色的許可權控制。
高亮的這行程式碼
if (context.user && (context.user.id === post.authorId))
複製程式碼
就是在後端手動寫的postType中,手動加的resolve函式裡,加上這麼一個userId關係判斷。
也就只能實現當查詢postType對應的表時,只有post裡的authorId和來訪user的id相等時,才返回查到的結果。
下文中善意地提示了你,不要寫死在某個Type的resolver函式中,
而是應該封裝到一個postReponsitory,裡面放一個getBody的函式,內部再實現這個判斷並return。
這樣不僅邏輯清晰,還能在別的Type中用到postType時(例如userType巢狀postType)可以複用。(PS: 這個文件中沒說,我幫它說了)
但即便你花了時間去新寫一個類、再新寫一個函式,做了這個封裝,那也只是postType能複用而已,
其它的humanType,droidType,queryType等一大堆Type不都還是得一個個寫?
https://github.com/graphql/graphql-js/blob/master/src/__tests__/starWarsSchema.js
而且當今的網際網路應用中,不管是網站,還是移動端App,稍微複雜一點的都不只是【所屬人】這麼一個角色,
其中大部分,尤其是社交應用,都包含 【聯絡人】、【朋友圈】這兩個角色。
當然,所有具有賬戶登入的應用,都可以分【已登入】、【未登入】這兩種角色。
既然GraphQL不提供許可權控制功能,那就只能自己根據每種角色一個個寫了。
按照以上唯一一個官方示例,我們對應所有角色的判斷應該是:
未登入:
if (context.user == null || context.user.id == null || context.user.id <= 0) {
return post.body;
}
return null;
複製程式碼
已登入:
if (context.user && context.user.id && context.user.id > 0) {
return post.body;
}
return null;
複製程式碼
朋友圈:
var userId = context.user == null ? null : context.user.id;
var contactIdList = context.user == null ? null : context.user.contactIdList; //聯絡人id列表
if ((userId && userId === post.authorId) || (contactIdList && contactIdList.indexOf(post.authorId) >= 0)) {
return post.body;
}
return null;
複製程式碼
聯絡人:
var contactIdList = context.user == null ? null : context.user.contactIdList; //聯絡人id列表
if (contactIdList && contactIdList.indexOf(post.authorId) >= 0) {
return post.body;
}
return null;
複製程式碼
所屬人:
if (context.user && (context.user.id === post.authorId)) {
return post.body;
}
return null;
複製程式碼
僅僅用GraphQL實現查詢postType這一個Type對應的角色許可權控制,居然就要寫這麼多判斷程式碼!
假設我們資料庫有20張表(實際很輕量級的應用才只有這麼少的表),對應寫了20個Type,那就是 20*5 = 100 個判斷!!!
僅僅是判斷角色許可權的程式碼就至少有 20*(4 + 4 + 6 + 5 + 4) = 460 行!!!
而APJSON提供了自動化的許可權控制,可以細分到 每張表、每行記錄、每種角色、每種操作 的控制粒度!
而且每張表只需要寫3行程式碼就能配置各種角色的增刪改查的許可權!
我們用APIJSON來操作一張表,例如使用者表User,程式碼寫3行就夠了:
//登錄檔並新增許可權,用預設配置
@MethodAccess
public class User {
//內容一般僅供表欄位說明及Android App開發使用,服務端不用的可不寫。
}
//DemoVerifier內新增許可權
ACCESS_MAP.put(User.class.getSimpleName(), getAccessMap(User.class.getAnnotation(MethodAccess.class)));
複製程式碼
或者可以再定製下POST請求的角色許可權:
@MethodAccess(
POST = {UNKNOWN, ADMIN} //只允許未登入角色和管理員角色新增User,預設配置是 {LOGIN, ADMIN}
)
public class User {}
複製程式碼
然後執行下Server工程就可以請求了:
URL:http://apijson.cn:8080/get
請求:
{
"User": {
"id": 82001
}
}
複製程式碼
返回:
{
"User": {
"id": 82001,
"sex": 0,
"name": "Test",
"tag": "APIJSON User",
"head": "http://static.oschina.net/uploads/user/19/39085_50.jpg",
"contactIdList": [
82004,
82021,
70793
],
"pictureList": [
"http://common.cnblogs.com/images/icon_weibo_24.png"
],
"date": "2017-02-01 19:21:50.0"
},
"code": 200,
"msg": "success"
}
複製程式碼
複製程式碼
我們再試試APIJSON的自動化許可權控制到底 能不能達到期望、會不會被繞過 吧。
查詢使用者開放資訊User:
/get/{"User":{"id":38710}}
請求成功:
{
"User": {
"id": 38710,
"sex": 0,
"name": "TommyLemon",
"tag": "Android&Java",
"head": "http://static.oschina.net/uploads/user/1218/2437072_100.jpg?t=1461076033000",
"contactIdList": [
82003,
82005,
90814,
82004,
82009,
82002,
82044,
93793,
70793
],
"pictureList": [
"http://static.oschina.net/uploads/user/1218/2437072_100.jpg?t=1461076033000",
"http://common.cnblogs.com/images/icon_weibo_24.png"
],
"date": "2017-02-01 19:21:50.0"
},
"code": 200,
"msg": "success"
}
複製程式碼
查詢使用者隱私資訊Privacy:
/get/{"Privacy":{"id":38710}}
請求失敗,無GET許可權:
{
"Privacy": {
"id": 38710
},
"code": 401,
"msg": "Privacy 不允許 UNKNOWN 使用者的 GET 請求!"
}
複製程式碼
看下原始碼:
@MethodAccess(
GET = {},
GETS = {OWNER, ADMIN}
)
public class Privacy {}
複製程式碼
很明顯,get是不允許的,可以用gets,但也必須是OWNER, ADMIN這2種角色中的一個。
URL: http://apijson.cn:8080/gets/
請求:
{
"Privacy": {
"id": 38710
},
"tag": "Privacy"
}
複製程式碼
仍然失敗,因為沒登入,未登入是UNKNOWN使用者,這裡自動補全為OWNER:
{
"Privacy": {
"id": 38710
},
"tag": "Privacy",
"code": 407,
"msg": "未登入,請登入後再操作!"
}
複製程式碼
那我們能不能偽造一下角色騙過APIJSON呢?試試看:
{
"Privacy": {
"id": 38710,
"@role": "circle"
},
"tag": "Privacy"
}
複製程式碼
還是一樣的報錯:未登入。
{
"Privacy": {
"id": 38710,
"@role": "circle"
},
"tag": "Privacy",
"code": 407,
"msg": "未登入,請登入後再操作!"
}
複製程式碼
好吧,我登入後再試,新的報錯:
{
"Privacy": {
"id": 38710,
"@role": "circle"
},
"code": 401,
"msg": "Privacy 不允許 CIRCLE 使用者的 GETS 請求!"
}
複製程式碼
為什麼呢?角色不符合OWNER, ADMIN這2種角色中的一個。
那換成OWNER角色呢?
{
"Privacy": {
"id": 38710,
"@role": "owner"
},
"tag": "Privacy"
}
複製程式碼
繼續報錯:
{
"Privacy": {
"id": 38710,
"@role": "owner"
},
"code": 401,
"msg": "id = 38710 的 Privacy 不允許 OWNER 使用者的 GETS 請求!"
}
複製程式碼
換成後端沒有的角色呢?
{
"Privacy": {
"id": 38710,
"@role": "test"
},
"tag": "Privacy"
}
複製程式碼
報錯,角色不存在:
{
"Privacy": {
"id": 38710 ,
"@role": "test"
},
"code": 406 ,
"msg": "角色 test 不存在!只能是[UNKNOWN,LOGIN,CONTACT,CIRCLE,OWNER,ADMIN]中的一種!"
}
複製程式碼
再試試 "@role": "admin" :
{
"Privacy": {
"id": 38710,
"@role": "admin"
},
"tag": "Privacy"
}
複製程式碼
仍然報錯:
{
"Privacy": {
"id": 38710,
"@role": "admin"
},
"code": 406,
"msg": "角色設定錯誤!不允許在寫操作Request中傳 Privacy:{ @role:admin } !"
}
複製程式碼
管理員角色是隻能在伺服器內部設定的,不允許傳哦。
所以,按照Privacy的許可權配置,前端只有用OWNER角色去查當前已登入賬戶(id=82001)的Privacy:
{
"Privacy": {
"id": 82001,
"@role": "owner" //Request表中配置了自動補全,可不寫
},
"tag": "Privacy"
}
複製程式碼
才會返回正確的結果:
{
"Privacy": {
"id": 82001,
"certified": 1,
"phone": 13000082001,
"balance": 8781.46
},
"code": 200,
"msg": "success"
}
複製程式碼
注: 以上APIJSON請求都可以在 http://apijson.org 線上工具上測試
總結
GraphQL沒有提供許可權控制的功能,需要後端針對每張表對應的Type去對應各種角色一個個手寫大量判斷程式碼!
而APJSON提供了自動化的許可權控制,可以細分到 每張表、每行記錄、每種角色、每種操作 的控制粒度!
而且每張表只需要寫3行程式碼就能配置各種角色的增刪改查的許可權!以上測試用例也說明了它不但配置簡單還很可靠!
APIJSON,讓後端介面和文件自動化,前端(客戶端) 定製返回JSON的資料和結構!
創作不易,右上角點Star支援下吧,非常感謝^_^