GraphQL与认证
许多人会问GraphQL怎样认证和受权。终究的答案是GraphQL只是一个查询语言和认证之类的没什么关联,每个运用都能够有本身的完成要领。然则,我们照样来深切聊聊这个题目。
大局上看
基础上,有三种状况会发作:
已登录的用户发出GraphQL查询,未登录的用户不能够。认证在非GraphQL节点完成。
一切用户都能够发出GraphQL查询,未登录用户能够运用个中的一个子集。认证在非GraphQL节点完成。
一切用户都能够发出GraphQL查询,认证就由GraphQL节点完成。
第一种状况多是普遍存在的。你已有一个REST或许RPC节点,只需认证胜利的用户能够接见,增加/graphql异常的简朴。不好的处所是,你的客户端不能不处置惩罚GraphQL和非GraphQL两种状况。这多是一笔手艺债。
第二种状况是第一种项目进化今后的效果。终究前端代码只运用GraphQL,只不过久经考验的认证节点还会留着。
第三种状况平常是一个全新的后端会有的形状,只管防止处置惩罚非GraphQL节点。我(作者)还没有见过如许形状的服务端。
非GraphQL节点的处置惩罚机制
非GraphQL节点,我是指cookies、JSON和web tokens,或许HTTP基础认证。基础上不管何种体式格局,你的server都能够经由过程认证一个用户、一个要求并终究把数据传输给你的resolver。
这里是一个运用express-graphql
和cookies是例子(从他们的例子里效果来的):
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里,要求在一个比GraphQL路由更早的中间件处置惩罚了。以后,要求才会抵达GraphQL代码。我们晓得要求是从哪里来的。我们以至都能够在要求抵达GraphQL代码之前,把要求重定向到登录页面。
下面的例子运用了express-session
,然则处置惩罚的准绳和express-jwt
差不多。在GraphQL层面上,你的schema代码会是如许的:
new GraphQLObjectType({
name: 'Secrets',
fields: {
bigSecret: {
type: GraphQLString,
resolve(parentValue, _, { rootValue: { session } }) {
return getBigSecret(session);
}
}
}
});
只需能取到session,那末用户就能够接见其他相干的资本了。或许,假如session不存在,那末你根据你的设想抛出毛病或许完成其他的处置惩罚。
关键是rootValue
并没有在我们的GraphQL形式中定义为一个公然的字段或许参数,我们不信任客户端直接发送过来的数据,所以它是由server的其他代码注入的。
运用GraphQL时的完成机制
然则我们要完整的运用GraphQL呢?以上的要领能够在运用了express-graphql
的时刻运用。然则没法迁移到其他的完成里。
在少数的例子里,Facebook谈到了 concept of a viewer field。重要的头脑是你的运用的数据和谁接见相干,所以悉数的其他字段的数据都嵌入到内里。实际状况是,不可能一切的数据都和接见者相干。然则这么做的话,你能够有转变的余地。
{
viewer {
name
friends {
name
}
getProfile(id: String!) {
name
}
}
}
注重纵然和接见者无关的getProfile
字段也放在了viewer
字段里,为了以防万一哪天要限定接见者能够接见的数据的时刻处置惩罚起来就简朴了。
一个像Facebook一样的APP为了庇护隐私,有许多什么人能够检察什么数据的逻辑处置惩罚。纵然是一个简朴的APP也不会让用户检察他没有建立的数据。一个经常使用的要领是修正URL里的userID来检察一些私有数据,假如server不搜检用户一切权的话。运用一个单一的viewer
字段就让一切权搜检简朴了许多。
上面的schema
也能够和非GraphQL节点的认证要领一同运用。然则假如我们这么干的话呢:
{
viewer(token: String) {
name
}
}
假如不是用header或许查询参数(比方:JWT、OAuth、等),我们能够把它放在GraphQL的查询里。你的schema
的代码能够运用JWT库等东西直接剖析传过来的token。
**注重**:永久运用HTTPS来传输敏感数据。
要发出新的token,mutation就能够运用了:
mutation {
createToken(username: String!, password: String!) {
token
error
}
}
我们能够认证放在mutation里,要么返回一个token
要么返回一个毛病。如许前端就能够把token存起来在以后的要求里运用了。