sli*_*wp2 5 graphql apollo-server
我无法弄清楚如何在authMiddleware函数中处理auth错误。
这是我authMiddleware使用传统表达方式错误处理的功能。
const jwt = require('jsonwebtoken');
const { appConfig } = require('../config');
function authMiddleware(req, res, next) {
let token;
const parts = req.headers.authorization.split(' ');
if (parts.length === 2) {
const schema = parts[0];
const credentials = parts[1];
if (/^Bearer$/i.test(schema)) {
token = credentials;
} else {
// throw new Error();
next(new Error('credentials_bad_scheme: Format is Authorization: Bearer [token]'));
}
}
try {
const { user } = jwt.verify(token, appConfig.JWT_SCERET);
req.user = user;
} catch (error) {
// console.log(error);
next(error);
}
next();
}
exports.authMiddleware = authMiddleware;
Run Code Online (Sandbox Code Playgroud)
但是用apollo-server-express和graphql系统。在error传递到next功能不做工精细。这意味着express使用graphql工具堆栈时,错误处理方式似乎不再起作用。
该error中authMiddleware不会通过以下快递错误处理中间件
app.use((err, req, res) => {
console.log('error handler: ', err);
});
Run Code Online (Sandbox Code Playgroud)
如果我使用return res.status(401).json({code: 1001, msg: 'Authorization failed'})或身份验证失败时throw new Error('xxx')进入catch。该请求将永远在此处停止,这意味着永远不会停止graphqlExpressHandler。为了让请求下降到graphqlExpressHandler,我只能为错误做的事情是使用console.log打印它们。
而且没有办法使用express-jwt unless方法或credentialsRequired属性。因为当使用graphql时,只有一个名为'/ graphql'的路由。因此,除非/ graphql route
解决此问题的一种方法是:auth以传统方式处理静态api 并对其进行处理。使graphqlAPI进行数据查询。
迟到的回答,但可能会帮助面临同样问题的人。
我们是这样解决的:
graphql + apollo-server-express 仅公开路由/graphql,因此简单而好的方法是将身份验证端点公开为 graphql 突变,并在传递给实例的函数authMiddleware中进行令牌验证(您所做的)。contextApolloServer
token突变。// graphql.ts
import { gql } from 'apollo-server-express';
import AuthnHandler from './handlers/authn_handler';
export const typeDefs = gql`
type Mutation {
token(username: String, password: String): String
}
`
const authnHandler = new AuthnHandler();
export const resolvers = {
Mutation: {
token: authnHandler.tokenResolver
}
};
Run Code Online (Sandbox Code Playgroud)
// handlers/authn_handler.ts
import { AuthenticationError } from 'apollo-server-express';
export default class AuthnHandler {
public async tokenResolver(parent: any, args: any, context: any, info: any): Promise<any> {
const username = args.username;
const password = args.password;
// pseudo-code here, replace with your token issuing implementation.
// if credentials are valid, return Promise.resolve(token);
// else throw new AuthenticationError('Invalid credentials.');
}
}
Run Code Online (Sandbox Code Playgroud)
authMiddleware函数的作用)。// server.ts
import express from 'express';
import { ApolloServer, ApolloServerExpressConfig } from 'apollo-server-express';
import { typeDefs, resolvers } from './graphql';
import { authMiddleware } from './auth_middleware';
const expressApp = express();
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: authMiddleware
} as ApolloServerExpressConfig);
apolloServer.applyMiddleware({ app: expressApp });
expressApp.listen(3000, () => {
console.log('server listening on port 3000');
});
Run Code Online (Sandbox Code Playgroud)
您的authMiddleware函数签名根据context函数要求进行更改,在这种情况下,它会在成功时返回请求对象本身。
// auth_middleware.ts
const jwt = require('jsonwebtoken');
const { appConfig } = require('../config');
function authMiddleware({ req }) {
let token;
const parts = req.headers.authorization.split(' ');
if (parts.length === 2) {
const schema = parts[0];
const credentials = parts[1];
if (/^Bearer$/i.test(schema)) {
token = credentials;
} else {
throw new Error();
}
}
try {
const { user } = jwt.verify(token, appConfig.JWT_SCERET);
req.user = user;
} catch (error) {
throw new Error();
}
return { req };
}
exports.authMiddleware = authMiddleware;
Run Code Online (Sandbox Code Playgroud)
文档中的身份验证部分apollo-server提供了这种实现方式的详细说明。
| 归档时间: |
|
| 查看次数: |
727 次 |
| 最近记录: |