我正在处理一个需要实现身份验证和授权的项目。现在,我目前陷入了从一个普通的API授权,而不是为每个API编写公共代码。
例如,我正在获取一些数据,如下所示:
import prisma from '@/lib/prisma';
import { NextRequest, NextResponse } from 'next/server';
import { verifyJwt } from '../../../lib/jwt';
export async function GET(request: NextRequest) {
const accessToken = request.headers.get("authorization")?.split(' ')[1];
if (!accessToken || !verifyJwt(accessToken)) {
return NextResponse.json(
{
message: "Unauthorized",
},
{
status: 401,
}
);
}
try {
const posts = await prisma.post.findMany();
return NextResponse.json({ data: posts }, { status: 200 });
} catch (error: any) {
return NextResponse.json({ message: error.toString() }, { status: 500 });
}
}
正如你在上面的代码中看到的,在获取一些博客文章之前,我需要检查授权。那么,我如何从一个普通的API编写下面的代码呢?
const accessToken = request.headers.get("authorization")?.split(' ')[1];
if (!accessToken || !verifyJwt(accessToken)) {
return NextResponse.json(
{
message: "Unauthorized",
},
{
status: 401, // token not found
}
);
}
next-auth.ts
import { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
export const authConfig: NextAuthOptions = {
providers: [
CredentialsProvider({
id: 'credentials',
name: 'Credentials',
credentials: {
email: { label: "Email", type: "text", placeholder: "jsmith@email.com" },
password: { label: "Password", type: "password" }
},
async authorize(credentials, req) {
if (!credentials
|| !credentials.email
|| !credentials.password
) {
return null;
}
const res = await fetch("http://localhost:3000/api/auth/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: credentials?.email,
password: credentials?.password,
}),
});
const user = await res.json();
if (user && user?.data) {
return user.data;
} else {
return null;
}
}
}),
],
session: {
strategy: "jwt",
maxAge: 60 * 60 * 24 * 7, // 7 days
},
pages: {
signIn: '/login',
error: '/login',
},
callbacks: {
async jwt({ token, user }) {
if (user) {
return { ...token, ...user };
}
return token;
},
async session({ session, token }) {
if (token) {
session.user = token;
}
return session;
},
},
}
jwt.ts
import jwt, { JwtPayload } from "jsonwebtoken";
const secretKey = process.env.JWT_SECRET || "";
interface SignOption {
expiresIn?: string | number;
issuer?: string;
}
const ACCESS_TOKEN_SIGN_OPTION = {
expiresIn: "1h",
issuer: 'abcsoftware',
};
const REFRESH_TOKEN_SIGN_OPTION = {
expiresIn: "7d",
issuer: 'abcsoftware',
};
export function signJwtAccessToken(
payload: JwtPayload,
options: SignOption = ACCESS_TOKEN_SIGN_OPTION
) {
const token = jwt.sign(payload, secretKey, options);
return token;
}
export function signJwtRefreshToken(
payload: JwtPayload,
options: SignOption = REFRESH_TOKEN_SIGN_OPTION
) {
const token = jwt.sign(payload, secretKey, options);
return token;
}
// Verify authorization
export function verifyJwt(token: string) {
try {
const decoded = jwt.verify(token, secretKey!);
return decoded as JwtPayload;
} catch (error: any) {
console.log(error);
return null;
}
}
下一个版本是
13.4.6
下一个验证版本为
4.22.1
我用的是Next.js的App Router
先谢谢你了!
2条答案
按热度按时间hsgswve41#
要创建一个仔细检查授权令牌及其相关性的中间件,可以在Next.js和NextAuth.js中为API实现相互授权检查。下面是你可以修改代码的方法:
在项目目录中,可以生成一个名为apiMiddleware.ts(或任何名称)的新文件。
通过在apiMiddleware.ts中定义一个函数,使用中间件检查授权令牌。看看这个实现以供参考:
以下是如何在API路由文件中切换内容:使用apiMiddleware.ts中的checkAuthorization函数作为API路由的中间件。检查以下代码片段:导入checkAuthorization函数并将其集成到现有代码中。
根据您的项目结构,不要忘记更新apiMiddleware.ts文件中的导入路径。只需将中间件应用于每个需要授权的API路由,就可以使用此方法重用checkAuthorization中间件,而无需重复复制授权代码。
我假设jwt.ts中的verifyJwt函数正确地验证了JWT令牌,如果令牌有效,则返回解码后的有效负载。
wbgh16ku2#
对于服务器端授权,写入middleware
使用项目根目录中的文件middleware.ts(或.js)来定义Middleware。例如,与页面或应用程序处于同一级别,或者在src内部(如果适用)。
由于您使用的是
next-auth
,因此可以使用getToken
函数接受NextAuth.js请求(req)并返回NextAuth.js发出的JWT有效负载或原始JWT字符串。我们在cookie或Authorization头中查找JWT。