graphql实现(GraphQL (三) Authentication 和 Authorication)
本文介绍GraphQL中的Authenication和Authorication
参考:
https://graphql.org/learn/authorization/ https://www.apollographql.com/docs/apollo-server/security/authentication/Authenication和Authorication的区别
Authenication 和 Authorication 的概念十分容易混淆 ,两者的定义如下:
Authenication 指用户认证 ,即是否有用户登录,哪个用户登录 Authorication 指用户权限认证 ,再具体的操作中决定用户是否有权利使用查看数据或调用方法Authenication
提供用户的authenication有多种方式 ,包括HTTP header和JSON web token 。
下面给出一个创建Authenication的示例 创建用户组的schema分别创建一个用户信息的type ,并定义创建用户和登录的方法
type AuthPayload { token: String! name: String! } input UserCreateInput { name: String! password: String! } type Mutation { createUser(data: UserCreateInput): String login(data: UserCreateInput): AuthPayload logout(data: UserCreateInput, param: Int!): Int } 定义本地CreateUser和Login的Resolver通常情况下 ,用户在用前端创建用户时 ,会传入用户名和密码 ,后端不会直接保存用户密码 ,而是将用户信息加密为webtoken储存起来 ,而login的情况下 ,也是会将用户用户名和密码的信息与weebtoken进行比对 。
可以在context中,设置一个用户组缓存来储存数据 ,同样适用于将用户信息储存于数据库或云端 。 const resolver = { Mutation: { createUser: async (parent: any, args: any, ctx: any, info: any) => { if (args.data.password.length < 8) { throw new Error(Password must be 8 characters or longer.) } const password = await bcrypt.hash(args.data.password, 10); const id = uuidv4(); const token = jwt.sign({ userId: id }, password); ctx.users.push({ id, name: args.data.name, password, token }); return token; }, login: async (parent: any, args: any, ctx: any, info: any) => { const user = ctx.users.find(u => u.name === args.data.name); if (!user) throw Error(User not exist); const isMatch = await bcrypt.compare(args.data.password, user.password); if (!isMatch) throw new Error(Password mismatch); return { name: user.name, token: user.token ? user.token : jwt.sign({ userId: user.id }, password), } }, } }Authorization
用上述步骤执行完Authentication的操作以后 ,需要验证用户操作函数是否有权限只需要在相应方法的Resolver中进行验证即可,调用Query或Mutation可以在Header中添加一个由后端返回给前端的token ,示例如下:
后端:
const getUserId = (request) => { const token = request.headers.authorization; if (!token) { throw new Error(Authentication required) } const decoded = jwt.verify(token, password) return decoded.userId } const resolver = { Mutation: { callFunction: async (parent: any, args: any, ctx: any, info: any) => { const id = getUserId(ctx.request); if (!id) throw Error(ID not exist); // Do operation } } }在Apollo GraphQL中可以在前端的header加一个authorication的字段 ,输入token:
前端可以在创建Apollo GraohQL Module时,创建一个MidWare包含我们的header:
const authMiddleware = new ApolloLink((operation: any, forward: any) => { operation.setContext({ headers: new HttpHeaders().set( "Authorization", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." //Token ), }); return forward(operation); }); export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> { return { link: httpLink.create({uri}), cache: new InMemoryCache(), }; } export function createApolloWithAuth(httpLink: HttpLink): ApolloClientOptions<any> { return { link: from([ authMiddleware, httpLink.create({ uri, }), ]), cache: new InMemoryCache(), }; }创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!