Kon*_*kit 13 jwt server-side-rendering next.js ssr
我是Next.js的新手,我正在使用jwt令牌与身份验证系统进行斗争.我想知道使用身份验证系统存储jwt令牌和路由的最佳/标准方法是什么.我一直在尝试不同的方法,从不同的教程/文章,但不太明白.这是我尝试过的.
当用户登录时,它会将用户名/密码发送到一个单独的 api服务器(例如处理后端内容的新项目),服务器将响应access-token,然后在Next.js项目中,我用接收到的令牌设置cookie.在Next.js项目中,受保护的路由将使用a withAuthhoc 进行包装,这将检查cookie中的令牌.这种方法的问题是它容易受到XSS的攻击,因为cookie没有httpOnly标志.
这类似于1.)但使用时localStorage,问题是access-token无法在第一次请求时发送到服务器.(这个我不确定,但根据我的理解,在每个http请求中,我必须access-token手动操作,那么我无法控制的请求呢?例如,首先请求或使用<a>标记).
我在Next.js服务器(自定义快速服务器)中编写了身份验证后端.用户登录时,服务器将对其进行验证,然后设置httpOnly cookie.然后问题是,使用客户端路由(使用Next.js路由器转到url),它无法检查令牌.例如,如果页面是使用withAuthhoc 包装的,但它无法使用javascript访问cookie中的令牌.
我见过很多人,在getInitialProps受保护的路由中,他们只检查cookie/localStorage中的存在令牌,然后如果令牌被撤销或列入黑名单,他们如何处理它,因为他们没有发送令牌给服务器?或者我是否必须在每个客户端页面更改时将令牌发送到服务器?
Yil*_*maz 27
由于我们正在隔离中,我有足够的时间来回答这个问题。这将是一个很长的答案。
Next.js 使用 App 组件来初始化页面。_app 页面负责呈现我们的页面。我们在 _app.js 上对用户进行身份验证,因为我们从 getInitialProps 返回的任何内容都可以被所有其他页面访问。我们在这里对用户进行身份验证,身份验证决定将传递给页面,从页面到页眉,因此每个页面都可以决定用户是否通过身份验证。(请注意,它可以在没有道具钻孔的情况下使用 redux 完成,但它会使答案更复杂)
static async getInitialProps({ Component, router, ctx }) {
let pageProps = {};
const user = process.browser
? await auth0.clientAuth()
: await auth0.serverAuth(ctx.req); // I explain down below
//this will be sent to all the components
const auth = { user, isAuthenticated: !!user };
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps, auth };
}
render() {
const { Component, pageProps, auth } = this.props;
return <Component {...pageProps} auth={auth} />;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们在浏览器上并且需要检查用户是否通过身份验证,我们只需从浏览器中检索 cookie,这很容易。但是我们总是要验证令牌。它与浏览器和服务器使用的过程相同。我将在下面解释。但是如果我们在服务器上。我们无法访问浏览器中的 cookie。但是我们可以从“req”对象中读取数据,因为 cookie 附加到req.header.cookie。这就是我们如何访问服务器上的 cookie。
async serverAuth(req) {
// console.log(req.headers.cookie) to check
if (req.headers.cookie) {
const token = getCookieFromReq(req, "jwt");
const verifiedToken = await this.verifyToken(token);
return verifiedToken;
}
return undefined;
}
Run Code Online (Sandbox Code Playgroud)
这是 getCookieFromReq()。请记住,我们必须考虑功能性。
const getCookieFromReq = (req, cookieKey) => {
const cookie = req.headers.cookie
.split(";")
.find((c) => c.trim().startsWith(`${cookieKey}=`));
if (!cookie) return undefined;
return cookie.split("=")[1];
};
Run Code Online (Sandbox Code Playgroud)
一旦我们得到了 cookie,我们就必须对其进行解码,提取过期时间以查看它是否有效。这部分很容易。我们必须检查的另一件事是 jwt 的签名是否有效。对称或非对称算法用于对 jwt 进行签名。您必须使用私钥来验证对称算法的签名。RS256 是 API 的默认非对称算法。使用 RS256 的服务器为您提供一个链接,让 jwt 使用密钥来验证签名。你可以使用 [jwks-rsa][1] 或者你可以自己做。您必须创建一个证书,然后验证令牌是否有效。
假设我们的用户现在已通过身份验证。你说,“我见过很多人,在受保护路由的 getInitialProps 中,他们只检查 cookie/localStorage 中的存在令牌,”。我们使用受保护的路由只允许授权用户访问。为了访问这些路由,用户必须显示他们的 jwt 令牌,并且 express.js 使用中间件来检查用户的令牌是否有效。由于您已经看过很多示例,因此我将跳过这一部分。
“那么如果令牌被撤销或列入黑名单,他们如何处理它,因为他们没有将令牌发送到服务器?或者我是否必须在每个客户端页面更改时将令牌发送到服务器?”
通过验证令牌过程,我们可以 100% 确定令牌是否有效。当客户端要求服务器访问一些秘密数据时,客户端必须将令牌发送到服务器。想象一下,当您挂载组件时,组件会要求服务器从受保护的路由中获取一些数据。服务器将提取req对象,获取 jwt 并使用它从受保护的路由中获取数据。浏览器和服务器获取数据的实现是不同的。如果浏览器发出请求,它只需要相对路径,而服务器需要绝对路径。您应该知道获取数据是通过组件的 getInitialProps() 完成的,并且该函数在客户端和服务器上都执行。这是您应该如何实施它。我刚刚附上了 getInitialProps() 部分。
MyComponent.getInitialProps = async (ctx) => {
const another = await getSecretData(ctx.req);
//reuslt of fetching data is passed to component as props
return { superValue: another };
};
const getCookieFromReq = (req, cookieKey) => {
const cookie = req.headers.cookie
.split(";")
.find((c) => c.trim().startsWith(`${cookieKey}=`));
if (!cookie) return undefined;
return cookie.split("=")[1];
};
const setAuthHeader = (req) => {
const token = req ? getCookieFromReq(req, "jwt") : Cookies.getJSON("jwt");
if (token) {
return {
headers: { authorization: `Bearer ${token}` },
};
}
return undefined;
};
export const getSecretData = async (req) => {
const url = req ? "http://localhost:3000/api/v1/secret" : "/api/v1/secret";
return await axios.get(url, setAuthHeader(req)).then((res) => res.data);
};
[1]: https://www.npmjs.com/package/jwks-rsa
Run Code Online (Sandbox Code Playgroud)
随着 Next.JS v8 的引入,NextJS 示例页面中放置了示例。要遵循的基本思想是:
智威汤逊
身份验证
| 归档时间: |
|
| 查看次数: |
3551 次 |
| 最近记录: |