Next.js 14 踩坑:处理API中的JWT登录认证问题


theme: condensed-night-purple

前言

在使用 Next.js14 开发登录登出功能时遇到一个问题:可以设置 cookie,但无法清除 cookie。

在开发这个功能时,借助了 Route Handler 的特性,关于 cookie 的处理,官网提到了 next/headers 的 cookies API;同样可以通过 Request、Response 和 NextRequest、NextResponse 提供的相关方法处理。NextRequest、NextResponse 来自 next/server,它们分别拓展了 Web Request APIWeb Response API 的功能。

登录功能

我的 JWT 来自 API 接口,因此做了一些 BFF 的工作,下面是登录功能的实现:

```ts // app/api/login/route.ts import { api } from '@/config/api'; import { NextRequest, NextResponse } from 'next/server';

export async function POST(request: NextRequest) { const body = await request.json(); const { email, password } = body;

const response = await fetch(${api}/login, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email, password, }), });

if (response.status === 404) { return NextResponse.json({ success: false, msg: '请求地址不存在', }); }

const json = await response.json(); // 解析出失败的 json 数据 if (!response.ok) { return NextResponse.json( { success: false, msg: json.message, }, { status: response.status || 500 } ); } const token = json.data.token;

return NextResponse.json( // 返回body内容 { success: true, msg: json.message, }, // 设置其他 { headers: { 'Set-Cookie': token=${token};path=/;max-age=86400;HttpOnly, }, } ); } ```

调用 NextResponse.json 方法,第一个参数为返回给前端 json 数据,第二个参数用来配置请求头、状态码。在服务端设置响应头 Set-Cookie 后,发送给客户端,以后客户端就会自动带上请求头 Cookie。在上面代码中,Set-Cookie 中最重要的参数就是 token,它的值来自 API 中返回的 jwt 字符串。

  1. 登录时,响应头中加入了 Set-Cookie:

image.png

  1. Cookie 中存入了 token:

image.png

  1. 发请求时,请求头中存在 Cookie:

image.png

登出功能

登出时,需要把 cookie 删除,于是我使用了 NextRequest 和 NextResponse 中提供的 request.cookie.delete方法和 response.cookie.delete 方法:

```ts request.cookies.delete('token');

let response = NextResponse.next(); response.cookies.delete('token'); ```

但这并不起作用。

下面是有效的代码:

```ts import { NextResponse } from 'next/server'; import { cookies } from 'next/headers';

export async function DELETE() { // 设置过期时间为0来删除cookie cookies().set('token', '', { maxAge: 0 });

return NextResponse.json({ success: true, msg: '登出成功', }); } ```

调用 next/headers 中的 cookies 成功地删除了 cookies,实现了登出功能。

路由中间件

在 Next.js 中的中间件是介于服务器和应用之间的一层介质。当一个请求到达应用时,它会首先通过中间件。然后中间件可以根据这个请求的信息(比如URL、headers、cookies等)执行一些动作,然后有选择的转发这个请求到你的页面或者api路由,或者直接返回一个响应。

有了中间件,你就可以在一个集中的地方处理跨越多个页面或API路由的逻辑。比如:

  • 认证和授权:检查请求的 cookie 或 header,来确认用户的身份,然后决定他是否有权限访问请求的资源。
  • 重定向和路由改写
  • 自定义的缓存规则

下面是检查认证和重定向的例子:

```ts import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) { // 检查 token(从cookie中获取token) const token = request.cookies.get('token')?.value;

// 没有 token 时,跳回登录页 if (!token) { const url = request.nextUrl.clone(); url.pathname = '/login'; return NextResponse.redirect(url); } } ```

如果未登录,则重定向到登录页。

为什么使用 cookie?

要清楚 Route Handler 属于服务器层面,这里无法使用浏览器提供的window对象,也就无法使用HTML5的 localStorage 和 sessionStorage 作为 token 的存储方案。路由中间件 middleware.ts 也在服务器中,同样无法调用浏览器中的 localStorage 等 API。

综上,在客户端和服务端都能够使用的存储方案只有 cookie。


技术交流:

公众号:见嘉 Being Dev

v:withhisx

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值