通过本文你能学到什么?
- 深入理解
301
和302
重定向的本质区别 - 掌握重定向对
SEO
的影响机制 - 学习重定向的最佳实践和常见错误
- 了解重定向在登录系统中的应用
- 掌握重定向的调试方法 和工具使用
- 学习
Next.js
和Nest.js
中的重定向实现 - 理解浏览器对重定向的缓存行为
大家好,我是芝士,欢迎点此扫码加我微信 Hunyi32 交流,最近创建了一个低代码/前端工程化交流群,欢迎加我微信 Hunyi32 进群一起交流学习,也可关注我的公众号[ 前端界 ] 持续更新优质技术文章
1. HTTP重定向基础
1.1 什么是301重定向
301
重定向(Moved Permanently)是 HTTP
协议中的一种状态码,表示请求的资源已被永久移动到新位置。当用户或搜索引擎访问旧 URL
时,会自动重定向到新的URL。
301
重定向表明请求的资源已永久移动到新的位置,搜索引擎和浏览器都会相应地更新其索引和缓存。
1.2 什么是302重定向
302
重定向(Found/Moved Temporarily)表示请求的资源临时位于不同的 URL
下。与 301
不同,302
暗示这种重定向是暂时的,将来可能会恢复原 URL
。
1.3 301与302重定向的本质区别
301
和 302
重定向有着本质的区别,它们分别适用于不同的场景,对 SEO
的影响也截然不同。
特性 | 301重定向 | 302重定向 |
---|---|---|
含义 | 永久重定向 | 临时重定向 |
HTTP状态码 | 301 Moved Permanently | 302 Found / Moved Temporarily |
SEO权重传递 | 90-99% | 较少或不传递 |
搜索引擎行为 | 更新索引为新URL | 保留原URL索引 |
浏览器缓存 | 通常会缓存 | 通常不会长期缓存 |
适用场景 | 网站迁移、域名更换 | 临时维护、用户认证 |
2. 301重定向与SEO
2.1 权重传递机制
- 旧
URL
的SEO
权重会传递到新URL
- 传递比例约为
90-99%
- 包括
PageRank
、外部链接权重等 - 搜索引擎会更新其数据库中的
URL
索引
2.2 搜索引擎行为
当搜索引擎遇到 301
重定向时,通常会:
- 发现
301
重定向后会自动抓取新URL - 将新
URL
添加到索引中 - 逐渐删除旧
URL
的索引 - 将外部链接权重传递给新
URL
Google
会认为这是永久性的改变
2.3 301常见应用场景
301
重定向常见于以下场景:
- 域名迁移
js
http://old-domain.com/* -> http://new-domain.com/*
HTTP
到HTTPS
迁移
js
http://domain.com/* -> https://domain.com/*
- 网站改版
js
/old-product-page -> /new-product-structure
-
多域名整合
domain1.com/* -> main-domain.com/*
domain2.com/* -> main-domain.com/*
3. 302重定向的应用场景
3.1 适用情境
与 301
不同,302
重定向主要用于以下场景:
- 用户认证和登录:当用户访问需要认证的页面时,临时重定向到登录页面
- A/B测试:临时将部分流量重定向到测试页面
- 临时维护:网站维护期间临时重定向到通知页面
- 地域识别:根据用户IP临时重定向到对应地区的页面
- 季节性内容:节日促销等临时内容变更
目前工作中发现用户认证和登录是302重定向使用最多的场景。
3.1.1 A/B 测试是什么?
A/B
测试(也称为分割测试或桶测试)是一种用户体验研究方法,通过将用户流量分成不同的组,向不同组展示不同版本的页面或功能,然后比较这些版本的效果,以确定哪个版本能产生更好的结果。
A/B测试的基本原理
- 随机分配 :将用户随机分配到
A
组(对照组)或B组(实验组) - 同时测试:两个版本同时运行,确保外部因素影响一致
- 数据收集:收集用户行为数据,如点击率、转化率、停留时间等
- 统计分析:使用统计方法确定结果是否具有统计显著性
A/B测试的常见应用场景
测试不同的页面布局;评估不同的产品描述下的埋点数据;测试不同的产品定价策略;比较不同的注册流程
3.2 登录系统中的302重定向
登录系统普遍使用 302
而非301
重定向,原因如下:
- 临时性:登录重定向是一个临时操作,不是永久性的URL变更
- 状态变化:用户认证状态是临时的,可能会变化
- 避免缓存:防止浏览器缓存重定向结果,确保每次都进行身份验证
- 保留原始URL:方便用户返回登录前的页面
- 多端登录:同一用户可能从不同设备登录,需要每次都验证
实际登录流程示例:
bash
1. 用户访问需要认证的页面 /protected-page
2. 系统检测到未登录,发送302重定向到 /login?return_url=/protected-page
3. 用户填写登录表单并提交
4. 服务器验证凭据后,发送302重定向到原始的 /protected-page
3.2.1 登录流程时序图
发现未登录 App-->>User: 2. 302 重定向到登录页
Location: /login?return_url=/protected-page User->>Auth: 3. GET /login?return_url=/protected-page Auth-->>User: 4. 返回登录页面 Note over User: 用户输入
用户名密码 User->>Auth: 5. POST /login
(提交登录表单) Note over Auth: 验证用户凭据 Auth-->>User: 6. 302 重定向到原始页面
Location: /protected-page
Set-Cookie: session=xxx User->>App: 7. GET /protected-page
Cookie: session=xxx Note over App: 验证会话有效 App-->>User: 8. 200 返回页面内容 Note over User,App: 所有重定向都使用302(临时重定向)
以确保每次都进行身份验证
4. 重定向最佳实践
4.1 301重定向最佳实践
重定向规则
- 直接跳转,避免重定向链
- 保持
URL
结构一致性 - 确保新
URL
是有效的 - 避免重定向循环
技术实现示例
typescript
// 直接重定向
@Controller()
export class RedirectController {
@Get('old-path/:id')
@Redirect('', 301)
redirect(@Param('id') id: string) {
return {
url: `/new-path/${id}`
};
}
}
监控和维护
- 记录重定向日志
- 定期检查重定向状态
- 监控重定向链长度,并且检查是否有断链
4.2 重定向实施中的常见问题
技术实现问题
- 错误使用重定向类型 :临时变更使用
301
重定向(应使用302
),永久变更使用302
重定向(应使用301
) - 重定向循环 :
A
重定向到B
,B
又重定向回A
,导致无限循环 - 重定向链过长 :多次重定向(如
A→B→C→D
)会降低用户体验和SEO
效果 - 内部链接未更新 :网站内部链接仍指向旧
URL
,导致不必要的重定向
SEO相关问题
- 内容相关性缺失:重定向到内容不相关的页面,搜索引擎可能视为低质量信号
- 重定向链过长 :多次重定向会稀释
SEO
权重,降低搜索引擎对目标页面的信任 - 站点地图未更新 :未在站点地图中反映
URL
变更,影响搜索引擎爬取效率 - 未通知搜索引擎 :未通过 Google Search Console等工具提交URL变更,延缓搜索引擎更新索引
4.3 重定向优化策略
技术层面优化
- 直接重定向:尽可能使用单次重定向,避免重定向链
- URL结构一致性 :保持新旧
URL
结构相似,便于用户和搜索引擎理解 - 规范化URL :使用规范链接标签(
canonical tag
)明确首选URL
版本 - 监控系统:建立重定向监控机制,及时发现并解决重定向问题
SEO层面优化
- 规范链接标记 :使用
<link rel="canonical">
标签明确首选URL - 更新站点地图:及时更新XML站点地图,反映最新的URL结构
- 搜索引擎通知 :通过Google Search Console提交URL变更,加速索引更新
- 重定向稳定性:确保重定向长期稳定,避免频繁变更导致搜索引擎信任度下降
- 内容质量保证 :确保重定向目标页面内容质量不低于原页面,避免用户体验和
SEO
价值下降
5. 重定向调试指南
5.1 Chrome开发者工具使用
"Preserve log"(保留日志) 在调试重定向时非常重要,勾选后页面导航或重定向的网络请求记录都会被保留。可以看到完整的请求链:原始请求 → 重定向 → 最终请求
Network面板查看
- 打开开发者工具(
F12
或右键-检查) - 切换到
Network
标签 - 勾选
Preserve log
选项(保留日志) - 执行会导致重定向的操作(如登录/退出登陆)
- 查看请求列表,重定向的请求会有状态码
301
或302
- 点击请求可以查看详细信息,响应头中的
Location
字段就是重定向的目标URL
5.2 分析重定向链

观察状态码
- 在
Network
面板中的Status
列查看301/302
表示重定向 - 重定向请求后通常会紧跟一个状态码为
200
的请求 - 使用筛选器快速找到重定向请求:在
Filter
输入框中输入"status-code:301"
或"status-code:302"
这里我说下为什么重定向请求之后通常跟着一个状态码为
200
的请求,是因为服务器返回302
状态码的同时通过Location
字段告诉浏览器临时移动到的新位置。 并且浏览器收到302
响应后,会自动向Location
指定的新URL发起一个新的请求。当服务器成功处理这个新请求并返回内容时,会返回200状态码

text
浏览器 → 请求原始URL → 服务器返回302 + Location:新URL → 浏览器自动请求新URL → 服务器返回200 + 内容
查看Initiator列
- 在
Network
面板中的Initiator
列可以查看请求的发起者 - 重定向链中的请求
Request initiator chain
,Initiator
会显示一系列请求链路
5.3 辅助工具推荐
可以使用一些 Chrome
扩展来帮助分析重定向(可以自行搜索安装下):
- Redirect Path:跟踪和显示URL重定向路径
- Redirect Checker:检查页面的重定向类型和次数
- Lighthouse:评估页面性能,包括重定向对性能的影响
6. 重定向缓存
6.1 301重定向缓存
Chrome默认会缓存301重定向 缓存时间通常为7天(这是Chrome的默认值) 可以通过Chrome的开发者工具查看:
- 打开
Network
面板 - 勾选
"Preserve log"
- 查看重定向 响应头 中的的
"Cache-Control"
和"Expires"
头
Cache-Control 与 Expires 介绍
Cache-Control:是 HTTP/1.1
引入的响应头,用于控制缓存行为,可以设置多个指令,用逗号分隔,优先级高于 Expires
。
服务器响应示例内容如下:
http
HTTP/1.1 200 OK
Cache-Control: max-age=3600, public
Content-Type: text/html
Expires:是 HTTP/1.0
引入的响应头,指定资源的过期时间,使用 GMT
时间格式,优先级低于 Cache-Control
。
服务器响应示例内容如下:
http
HTTP/1.1 200 OK
Expires: Wed, 21 Oct 2023 07:28:00 GMT
Content-Type: text/html
6.2 302重定向缓存
Chrome
默认不会缓存 302
重定向 每次访问都会发送新的请求 在 Network
面板中可以看到每次都是新的请求
6.3 浏览器验证方式
- 打开
Chrome
开发者工具(F12) - 切换到
Network
面板 - 勾选
"Preserve log"
- 访问一个
301
重定向的URL
- 此时会看到两个请求:
- 原始URL → 301重定向
- 新URL → 200响应
- 此时会看到两个请求:
- 刷新页面
- 此时只会看到一个请求:
- 新URL → 200响应
- 原始
URL
的请求和301
重定向过程不会出现
- 此时只会看到一个请求:
6.3 其他浏览器缓存行为
- Firefox:
301
重定向默认缓存时间也是7
天302
重定向默认不缓存
- Safari:
301
重定向默认缓存时间可能更长(这个没有具体验证,知道的小伙伴可以和我说下)302
重定向默认不缓存
- Edge:
- 基于
Chromium
,行为与Chrome
类似 301
重定向默认缓存7
天302
重定向默认不缓存
7. 重定向代码实战
7.1 Next.js实现重定向
Next服务端重定向
js
// 在getServerSideProps中实现重定向
export async function getServerSideProps(context) {
const { req, res } = context;
const isAuthenticated = checkUserAuthentication(req);
if (!isAuthenticated) {
return {
redirect: {
destination: '/login?returnUrl=' + encodeURIComponent(req.url),
permanent: false, // 使用302临时重定向
},
};
}
return {
props: {}, // 将传递给页面组件的数据
};
}
中间件重定向
js
// middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
// 检查用户是否已认证(例如,通过检查cookie)
const isAuthenticated = request.cookies.get('auth-token');
if (!isAuthenticated && !request.nextUrl.pathname.startsWith('/login')) {
const loginUrl = new URL('/login', request.url);
loginUrl.searchParams.set('returnUrl', request.nextUrl.pathname);
return NextResponse.redirect(loginUrl);
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!api|_next/static|favicon.ico).*)'],
};
客户端重定向
js
import { useRouter } from 'next/router';
import { useEffect } from 'react';
function ProtectedPage() {
const router = useRouter();
const isAuthenticated = checkClientSideAuth();
useEffect(() => {
if (!isAuthenticated) {
router.push(`/login?returnUrl=${encodeURIComponent(router.asPath)}`);
}
}, [isAuthenticated, router]);
// 页面内容
}
7.2 Nest.js 实现重定向
使用控制器装饰器
js
import { Controller, Get, Redirect, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller('auth')
export class AuthController {
@Get('protected')
@Redirect('', 302) // 302是临时重定向
protected(@Req() request: Request) {
const isAuthenticated = this.authService.isAuthenticated(request);
if (!isAuthenticated) {
const returnUrl = encodeURIComponent(request.originalUrl);
return { url: `/login?returnUrl=${returnUrl}` };
}
// 已认证,不需要重定向
return { url: '' };
}
}
使用 Response 对象实现重定向
js
import { Controller, Get, Req, Res } from '@nestjs/common';
import { Request, Response } from 'express';
@Controller('auth')
export class AuthController {
@Get('check')
checkAuth(@Req() request: Request, @Res() response: Response) {
const isAuthenticated = this.authService.isAuthenticated(request);
if (!isAuthenticated) {
// 对应CAS例子的实现方式
const serviceUrl = encodeURIComponent(request.originalUrl);
const redirectUrl = `https://cas.example.com/session/check?service=${serviceUrl}&appId=12345`;
return response.redirect(302, redirectUrl);
}
// 已认证,继续处理请求
return response.status(200).json({ authenticated: true });
}
// CAS回调例子
@Get('callback')
casCallback(@Req() request: Request, @Res() response: Response) {
const ticket = request.query.ticket;
const service = request.query.service;
// 验证CAS票据
this.authService.validateTicket(ticket, service)
.then(user => {
// 验证成功,重定向回原始服务
return response.redirect(302, service as string);
})
.catch(err => {
// 验证失败,重定向到登录页
return response.redirect(302, '/login');
});
}
}
使用守卫(Guard)实现
js
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
const response = context.switchToHttp().getResponse();
const isAuthenticated = this.checkIfUserIsAuthenticated(request);
if (!isAuthenticated) {
const returnUrl = encodeURIComponent(request.originalUrl);
response.redirect(302, `/login?returnUrl=${returnUrl}`);
return false;
}
return true;
}
private checkIfUserIsAuthenticated(request: any): boolean {
// 检查用户认证逻辑
return !!request.session.userId;
}
}
// 使用守卫
@Controller('protected')
@UseGuards(AuthGuard)
export class ProtectedController {
// 受保护的路由...
}
大家好,我是芝士,最近创建了一个低代码/前端工程化交流群,欢迎点此扫码加我微信 Hunyi32 交流,也可关注我的公众号[ 前端界 ] 持续更新优质技术文章
8. 总结
301
重定向是SEO
友好的重定向方式,适用于永久性URL
变更301
重定向会传递90-99%
的链接权重,对SEO
价值保留至关重要302
重定向适用于临时性变更,尤其是登录和认证流程- 合理设计重定向策略需要考虑用户体验和搜索引擎优化
- 正确的重定向实现和监控是网站维护的重要部分
小伙伴们合理使用 301
和 302
重定向,可以在网站改版、域名迁移等场景下,最大程度地保持 SEO
价值和用户体验。