graphql-3

认证和中间件

控制具有权限的人去访问数据接口,需要借助于express的中间件来实现

中间件的本质实际上是一个function,它在接口执行之前首先拦截请求,然后决定是往下走还是返回错误消息

const express = require('express');
const {
  buildSchema
} = require('graphql');
const {
  graphqlHTTP
} = require('express-graphql');
// 定义schema,查询和类型
const schema = buildSchema(`
  input AccountInput {
    name: String
    age: Int
    gender: String
    department: String
  }
  type Account {
    name: String
    age: Int
    gender: String
    department: String
  }
  type Mutation {
    createAccount(input: AccountInput): Account
    updateAccount(id: ID, input: AccountInput): Account
  }
  type Query {
    accounts: [Account]
  }
`)
// 定义一个假的数据库
const fakeDb = {};

// 定义查询对应的解析器
const root = {
  accounts(){
    var arr = [];
    for(const i in fakeDb){
      arr.push(fakeDb[i]);
    }
    return arr;
  },
  // 这里的input相当于拿到的所有字段
  createAccount({ input }){
    // 相当于数据库的保存
    fakeDb[input.name] = input;
    // 返回保存的结果
    return fakeDb[input.name];
  },

  updateAccount({ id, input }){
    // 相当于数据库的更新
    // 从fakeDb中拿到需要的fakeDb[id],拿到之后将input新的属性覆盖到它身上
    const updatedAccount = Object.assign({}, fakeDb[id], input);
    // 将更新保存到数据库
    fakeDb[id] = updatedAccount;
    // 返回更新的结果
    return updatedAccount;
  }
}

const app = express();

// 中间件
const middleware = (req, res, next) => {
  // 判断访问地址中包含/graphql这个字样并且cookie中没有auth的时候
  if(req.url.indexOf('/graphql') !== -1 && req.headers.cookie.indexOf('auth') === -1){
    res.send(JSON.stringify({
      error: "当前没有权限访问该接口"
    }));
    return;
  }
  next();
};

// 中间件的注册
app.use(middleware);

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

app.listen(9000, () => {
  console.log("http://localhost:9000/graphql")
});

middleware中先检测访问的地址是不是/graphql,如果是这个地址,接着看一下cookie中是否包含auth这个字样,如果没有包含则抛出错误提示,否则就next()正常往下走

上面没有权限访问的原因是因为cookie中没有auth这个字段,可以在application中加一个之后刷新访问就可以

上面是通过一个小例子来说明中间件对权限验证,在真正的项目中是需要跟服务器端进行配合的:服务器端生成一个token,将token交给前端,前端在访问接口时将token带回来,拿到token之后对它进行一个检查

构造类型

之前的schema是通过buildSchema👇

const schema = buildSchema(`
// 定义类型
  type Account {
    name: String
    age: Int
    gender: String
    department: String
  }

// 定义Query
  type Query {
    accounts: [Account]
  }
`)

现在要说的是将类型的定义变成构造函数的形式进行,之前一步可以完成的现在需要三步,先定义type,然后定义Query,最后将Query转成schema👇

  • 使用GeaphQLObjectType定义type(类型)
var AccountType = new graphql.GraphQLObjectType({
  name: 'Account',
  fields: {
    name: { type: graphql.GraphQLString },
    age: { type: graphql.GraphQLInt },
    gender: { type: graphql.GraphQLString },
    department: { type: graphql.GraphQLString }
  }
});
  • 使用GeaphQLObjectType定义query(查询)
var queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    account: {
      type: AccountType,
      args: {
        username: {
          type: graphql.GraphQLString
        },
      },
      resolver: function (_, { username }) {
        const name = username;
        const age = 18;
        const gender = 'female';
        const department = 'xian';
        return {
          name,
          age,
          gender,
          department
        }
      }
    }
  }
});
  • 创建schema
var schema = new graphql.GraphQLSchema({ query: queryType });

const express = require('express');
const { graphql } = require('graphql');
const { buildSchema } = require('graphql');
const { graphqlHTTP } = require('express-graphql');

var AccountType = new graphql.GraphQLObjectType({
  name: 'Account',
  fields: {
    name: { type: graphql.GraphQLString },
    age: { type: graphql.GraphQLInt },
    gender: { type: graphql.GraphQLString },
    department: { type: graphql.GraphQLString }
  }
});

var queryType = new graphql.GraphQLObjectType({
  name: 'Query',
  fields: {
    account: {
      type: AccountType,
      args: {
        username: {
          type: graphql.GraphQLString
        },
      },
      resolver: function (_, { username }) {
        const name = username;
        const age = 18;
        const gender = 'female';
        const department = 'xian';
        return {
          name,
          age,
          gender,
          department
        }
      }
    }
  }
});


var schema = new graphql.GraphQLSchema({ query: queryType });





// 定义一个假的数据库
const fakeDb = {};

// 定义查询对应的解析器
const root = {
  accounts() {
    var arr = [];
    for (const i in fakeDb) {
      arr.push(fakeDb[i]);
    }
    return arr;
  },
  // 这里的input相当于拿到的所有字段
  createAccount({ input }) {
    // 相当于数据库的保存
    fakeDb[input.name] = input;
    // 返回保存的结果
    return fakeDb[input.name];
  },

  updateAccount({ id, input }) {
    // 相当于数据库的更新
    // 从fakeDb中拿到需要的fakeDb[id],拿到之后将input新的属性覆盖到它身上
    const updatedAccount = Object.assign({}, fakeDb[id], input);
    // 将更新保存到数据库
    fakeDb[id] = updatedAccount;
    // 返回更新的结果
    return updatedAccount;
  }
}

const app = express();

app.use('/graphql', graphqlHTTP({
  schema: schema,
  rootValue: root,
  graphiql: true
}));

app.listen(9000, () => {
  console.log("http://localhost:9000/graphql")
});

这样的变化带来的好处是比较好维护,哪块出错了之后就可以精确到出错的那个type

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值