GraphQL與認(rèn)證

GraphQL與認(rèn)證

很多人會(huì)問GraphQL怎么認(rèn)證和授權(quán)深浮。最終的答案是GraphQL只是一個(gè)查詢語言和認(rèn)證之類的沒什么關(guān)系压怠,每一個(gè)應(yīng)用都可以有自己的實(shí)現(xiàn)方法。但是飞苇,我們還是來深入聊聊這個(gè)問題菌瘫。

大局上看

基本上,有三種情況會(huì)發(fā)生:

  1. 已經(jīng)登錄的用戶發(fā)出GraphQL查詢布卡,未登錄的用戶不可以雨让。認(rèn)證在非GraphQL節(jié)點(diǎn)完成。
  2. 所有用戶都可以發(fā)出GraphQL查詢忿等,未登錄用戶可以使用其中的一個(gè)子集栖忠。認(rèn)證在非GraphQL節(jié)點(diǎn)完成。
  3. 所有用戶都可以發(fā)出GraphQL查詢贸街,認(rèn)證就由GraphQL節(jié)點(diǎn)完成庵寞。

第一種情況可能是普遍存在的。你已經(jīng)有一個(gè)REST或者RPC節(jié)點(diǎn)薛匪,只有認(rèn)證成功的用戶可以訪問捐川,添加/graphql非常的簡單。不好的地方是逸尖,你的客戶端不得不處理GraphQL和非GraphQL兩種情況古沥。這可能是一筆技術(shù)債。

第二種情況是第一種項(xiàng)目進(jìn)化以后的結(jié)果娇跟。最終前端代碼只使用GraphQL岩齿,只不過久經(jīng)考驗(yàn)的認(rèn)證節(jié)點(diǎn)還會(huì)留著。

第三種情況一般是一個(gè)全新的后端會(huì)有的形態(tài)逞频,盡量避免處理非GraphQL節(jié)點(diǎn)纯衍。我(作者)還沒有見過這樣形態(tài)的服務(wù)端。

非GraphQL節(jié)點(diǎn)的處理機(jī)制

非GraphQL節(jié)點(diǎn)苗胀,我是指cookies襟诸、JSON和web tokens,或者HTTP基本認(rèn)證基协「枨祝基本上無論何種方式,你的server都可以通過認(rèn)證一個(gè)用戶澜驮、一個(gè)請(qǐng)求并最終把數(shù)據(jù)傳輸給你的resolver陷揪。

這里是一個(gè)使用express-graphql和cookies是例子(從他們的例子里結(jié)果來的):

var session = require('express-session');
var graphqlHTTP = require('express-graphql');
var MySchema = require('./MySchema');
var app = express();

app.use(session({ secret: 'secret', cookie: { maxAge: 60000 }}));

app.use('/graphql', graphqlHTTP((request) => ({
  schema: MySchema,
  rootValue: { session: request.session },
  graphiql: truem
})));

在express里,請(qǐng)求在一個(gè)比GraphQL路由更早的中間件處理了。之后悍缠,請(qǐng)求才會(huì)到達(dá)GraphQL代碼卦绣。我們知道請(qǐng)求是從哪里來的。我們甚至都可以在請(qǐng)求到達(dá)GraphQL代碼以前飞蚓,把請(qǐng)求重定向到登錄頁面滤港。

下面的例子使用了express-session,但是處理的原則和express-jwt差不多趴拧。在GraphQL層面上溅漾,你的schema代碼會(huì)是這樣的:

new GraphQLObjectType({
  name: 'Secrets',
  fields: {
    bigSecret: {
      type: GraphQLString,
      resolve(parentValue, _, { rootValue: { session } }) {
        return getBigSecret(session);
      }
    }
  }
});

只要能取到session,那么用戶就可以訪問其他相關(guān)的資源了著榴√砺模或者,如果session不存在脑又,那么你按照你的設(shè)計(jì)拋出錯(cuò)誤或者實(shí)現(xiàn)其他的處理暮胧。

關(guān)鍵是rootValue并沒有在我們的GraphQL模式中定義為一個(gè)公開的字段或者參數(shù),我們不信任客戶端直接發(fā)送過來的數(shù)據(jù)问麸,所以它是由server的其他代碼注入的叔壤。

使用GraphQL時(shí)的實(shí)現(xiàn)機(jī)制

但是我們要完全的使用GraphQL呢?以上的方法可以在使用了express-graphql的時(shí)候使用口叙。但是無法遷移到其他的實(shí)現(xiàn)里。

在少數(shù)的例子里嗅战,F(xiàn)acebook談到了 concept of a viewer field妄田。主要的思想是你的應(yīng)用的數(shù)據(jù)和誰訪問相關(guān),所以全部的其他字段的數(shù)據(jù)都嵌入到里面驮捍。實(shí)際情況是疟呐,不可能所有的數(shù)據(jù)都和訪問者相關(guān)。但是這么做的話东且,你可以有改變的余地启具。

{
  viewer {
    name
    friends {
      name
    }
    getProfile(id: String!) {
      name
    }
  }
}

注意即使和訪問者無關(guān)的getProfile字段也放在了viewer字段里,為了以防萬一哪天要限制訪問者可以訪問的數(shù)據(jù)的時(shí)候處理起來就簡單了珊泳。

一個(gè)像Facebook一樣的APP為了保護(hù)隱私鲁冯,有很多什么人可以查看什么數(shù)據(jù)的邏輯處理。即使是一個(gè)簡單的APP也不會(huì)讓用戶查看他沒有創(chuàng)建的數(shù)據(jù)色查。一個(gè)常用的方法是修改URL里的userID來查看一些私有數(shù)據(jù)薯演,如果server不檢查用戶所有權(quán)的話。使用一個(gè)單一的viewer字段就讓所有權(quán)檢查簡單了很多秧了。

上面的schema也可以和非GraphQL節(jié)點(diǎn)的認(rèn)證方法一起使用跨扮。但是如果我們這么干的話呢:

{
  viewer(token: String) {
    name
  }
}

如果不是用header或者查詢參數(shù)(比如:JWT、OAuth、等)衡创,我們可以把它放在GraphQL的查詢里帝嗡。你的schema的代碼可以使用JWT庫等工具直接解析傳過來的token

**注意**:永遠(yuǎn)使用HTTPS來傳輸敏感數(shù)據(jù)璃氢。

要發(fā)出新的token哟玷,mutation就可以使用了:

mutation {
  createToken(username: String!, password: String!) {
    token
    error
  }
}

我們可以認(rèn)證放在mutation里,要么返回一個(gè)token要么返回一個(gè)錯(cuò)誤拔莱。這樣前端就可以把token存起來在之后的請(qǐng)求里使用了碗降。

譯自:https://medium.com/the-graphqlhub/graphql-and-authentication-b73aed34bbeb#.8sif1n1lj

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市塘秦,隨后出現(xiàn)的幾起案子讼渊,更是在濱河造成了極大的恐慌,老刑警劉巖尊剔,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件爪幻,死亡現(xiàn)場離奇詭異,居然都是意外死亡须误,警方通過查閱死者的電腦和手機(jī)挨稿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來京痢,“玉大人奶甘,你說我怎么就攤上這事〖酪” “怎么了臭家?”我有些...
    開封第一講書人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長方淤。 經(jīng)常有香客問我钉赁,道長,這世上最難降的妖魔是什么携茂? 我笑而不...
    開封第一講書人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任你踩,我火速辦了婚禮,結(jié)果婚禮上讳苦,老公的妹妹穿的比我還像新娘带膜。我一直安慰自己,他們只是感情好鸳谜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開白布钱慢。 她就那樣靜靜地躺著,像睡著了一般卿堂。 火紅的嫁衣襯著肌膚如雪束莫。 梳的紋絲不亂的頭發(fā)上懒棉,一...
    開封第一講書人閱讀 51,258評(píng)論 1 300
  • 那天,我揣著相機(jī)與錄音览绿,去河邊找鬼策严。 笑死,一個(gè)胖子當(dāng)著我的面吹牛饿敲,可吹牛的內(nèi)容都是我干的妻导。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怀各,長吁一口氣:“原來是場噩夢啊……” “哼倔韭!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瓢对,我...
    開封第一講書人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤寿酌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后硕蛹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體醇疼,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年法焰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秧荆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡埃仪,死狀恐怖乙濒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情卵蛉,我是刑警寧澤琉兜,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站毙玻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏廊散。R本人自食惡果不足惜桑滩,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望允睹。 院中可真熱鬧运准,春花似錦、人聲如沸缭受。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽米者。三九已至韭畸,卻和暖如春宇智,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背胰丁。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來泰國打工随橘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锦庸。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓机蔗,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甘萧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子萝嘁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)扬卷,斷路器牙言,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,092評(píng)論 25 707
  • 第一章 Nginx簡介 Nginx是什么 沒有聽過Nginx?那么一定聽過它的“同行”Apache吧邀泉!Ngi...
    JokerW閱讀 32,670評(píng)論 24 1,002
  • 原文標(biāo)題:GraphQL vs. REST Two ways to send data over HTTP: W...
    iamfanny閱讀 19,171評(píng)論 4 29
  • 我們從虛無中來嬉挡,又要回到虛無中去泉手,虛無才是我們的家邓了,可是以虛無為家,不正是無家可歸了嗎褪尝?從虛無到虛無因谎,人類經(jīng)過一段...
    六月雨JuneRain閱讀 265評(píng)論 0 0