在Next.js、graphQL、Apollo客户端中实现身份验证



我试图在前端使用NextJS和apollo客户端构建SSR应用程序,在后端使用(graphQLYoga(构建带有express的graphql。

我来自客户端渲染背景,在身份验证方面,那里的事情比SSR更简单,在常规客户端渲染中,我对用户进行身份验证的方法如下:

1-一旦用户在服务器验证后登录,用当前用户数据签署JWT,然后将其发送到客户端,并将其保存在本地存储或cookie等中。

2-实现一个loadUser()函数,并在(根(App组件的useEffect钩子中调用它,以在本地存储中的JWT有效的情况下加载每个组件(页面(中的用户。

3-如果JWT不存在或无效,只需将用户返回为null并重定向到登录页面。

所以在Next.js中,我知道我们无法访问localstorage,因为它在服务器端工作,所以我们只将令牌保存在cookie中,我实现的方法很痛苦,我想知道是否有更方便的方法,我的方法是:1-一旦用户登录,他就会调用登录突变,在req头中设置一个cookie,并返回一个用户和我想要的任何数据。2-在每个需要身份验证的页面中,我需要从cookie中获取令牌,然后将其发送回标头中,而我在getInitialProps()getServerSideProps()中这样做了,因为两者都运行服务器端,并可以访问标头中的请求cookie,如下所示:

export const getServerSideProps = async ctx => {
const apolloClient = initializeApollo();
// get the cookies from the headers in the request object
const token = ctx.req.headers.cookie ? ctx.req.headers.cookie : null;
return {
props: {
initialApolloState: apolloClient.cache.extract(),
token: token
}
};
};

现在我可以访问页面道具中的令牌,并且可以使用我的apollo客户端将令牌连同req头一起发送回,如下所示:

let getUserQuery = await apolloClient.query({
query: GET_USER_QUERY,
variables: { id: ctx.params.id },
context: { headers: { token: token } }
});

现在我可以访问服务器端请求中的令牌,如req.headers.token

我想要实现的目标:

1-有没有一种更简单的方法来实现loadUser(),它可以为用户加载我可以在next.js custom_app中实现的每个页面呈现,我找到了这个答案,但它并没有像他在回答中提到的那样在所有组件中返回auth对象或user。

2-我读到,如果我设置cookie httpOnly和credentials: "include",我可以在每个请求中访问cookie,但它似乎不适用于apollo客户端,如果有其他方法,那就太棒了。

3-有apollo团队提供的apollo-link-context,我可以使用setContext()在每个请求的头中发送一个令牌或任何值,如下所示:

const authLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem('token');
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
}
}
});

但由于我没有访问localstorage的权限,我无法实现它,因为下一次运行的是服务器端,所以如果有人对此有实现,请考虑共享。

PS。我在搜索和阅读了大约一个星期后写了这个帖子,这是我最后的机会问你们,提前谢谢。

通过存储获取令牌store.getState((..path.to.your.token

问题是,当盲更改时,令牌不会完全更新,我正在寻找解决方案。

最新更新