当前位置: 首页 > ops >正文

深入解析Django重定向机制

概述

核心是一个基类 HttpResponseRedirectBase,以及两个具体的子类 HttpResponseRedirect(302 临时重定向)和 HttpResponsePermanentRedirect(301 永久重定向)。它们都是 HttpResponse 的子类,专门用于告诉客户端(通常是浏览器)跳转到另一个URL。


class HttpResponseRedirectBase(HttpResponse):allowed_schemes = ['http', 'https', 'ftp']def __init__(self, redirect_to, *args, **kwargs):super().__init__(*args, **kwargs)self['Location'] = iri_to_uri(redirect_to)parsed = urlparse(str(redirect_to))if parsed.scheme and parsed.scheme not in self.allowed_schemes:raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)url = property(lambda self: self['Location'])def __repr__(self):return '<%(cls)s status_code=%(status_code)d%(content_type)s, url="%(url)s">' % {'cls': self.__class__.__name__,'status_code': self.status_code,'content_type': self._content_type_for_repr,'url': self.url,}class HttpResponseRedirect(HttpResponseRedirectBase):status_code = 302class HttpResponsePermanentRedirect(HttpResponseRedirectBase):status_code = 301

逐行解析

1. 基类:HttpResponseRedirectBase
class HttpResponseRedirectBase(HttpResponse):allowed_schemes = ['http', 'https', 'ftp']
  • 继承:它继承自 HttpResponse,这意味着它拥有所有普通HTTP响应的特性(如状态码、头部、内容等),并在此基础上增加了重定向的特殊功能。
  • 类属性 allowed_schemes:这是一个非常重要的安全特性。它定义了一个白名单,列出了允许重定向到的URL协议(scheme)。默认只允许 'http', 'https', 'ftp'。这可以防止一种称为不安全的URL重定向的安全漏洞,例如,如果有人试图构造一个 javascript:alert('xss')data:text/html;base64,... 这样的恶意链接,由于其协议(javascript:, data:)不在白名单内,重定向将会被阻止并抛出异常。
    def __init__(self, redirect_to, *args, **kwargs):super().__init__(*args, **kwargs)
  • 构造函数:接受一个必需的参数 redirect_to(要重定向到的目标URL),以及其他任何父类 HttpResponse 可能接受的参数(如 content, content_type 等)。
  • 调用父类构造函数super().__init__(*args, **kwargs) 确保 HttpResponse 被正确初始化。
        self['Location'] = iri_to_uri(redirect_to)
  • 设置Location头部:这是实现重定向的关键。HTTP协议规定,重定向响应必须在 Location 头部中包含目标URL。这里通过将字典式的赋值(self['Location'])来设置响应头。
  • iri_to_uri函数:这是一个Django的工具函数,用于将国际化资源标识符(IRI) 转换为标准的统一资源标识符(URI)。IRI支持Unicode字符(如中文),而URI只允许使用ASCII字符。这个函数会正确处理非ASCII字符的编码(例如,将“中文”转换为%E4%B8%AD%E6%96%87)。
        parsed = urlparse(str(redirect_to))if parsed.scheme and parsed.scheme not in self.allowed_schemes:raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)
  • 安全验证
    1. urlparse(str(redirect_to)):使用Python的 urllib.parse.urlparse 函数解析目标URL,将其拆分成各个组成部分(scheme, netloc, path等)。
    2. 检查解析出的协议(parsed.scheme)是否存在且不在允许的协议白名单(self.allowed_schemes)中。
    3. 如果协议不被允许,则抛出一个 DisallowedRedirect 异常,中止重定向过程。这是防止安全漏洞的关键防线。
    url = property(lambda self: self['Location'])
  • 只读属性 url:使用 property 装饰器创建了一个名为 url 的只读属性。当你访问 response.url 时,它会返回 Location 头部的值,即重定向的目标URL。这提供了一个非常方便和直观的访问方式。
    def __repr__(self):return '<%(cls)s status_code=%(status_code)d%(content_type)s, url="%(url)s">' % {'cls': self.__class__.__name__,'status_code': self.status_code,'content_type': self._content_type_for_repr,'url': self.url,}
  • 对象表示:定义了 __repr__ 方法,当你在Python shell中打印这个响应对象时,它会返回一个格式化的、信息丰富的字符串,而不是默认的晦涩的内存地址。例如:<HttpResponseRedirect status_code=302, url="https://example.com/">。这在调试时非常有用。

2. 具体实现类:HttpResponseRedirectHttpResponsePermanentRedirect

这两个类非常简单,它们只做了一件事:继承基类并设置正确的HTTP状态码。

class HttpResponseRedirect(HttpResponseRedirectBase):status_code = 302
  • 302 临时重定向:HTTP状态码302表示所请求的资源暂时位于另一个URI下。客户端(如浏览器或搜索引擎爬虫)在遇到此重定向时,应该继续使用原始URL发起请求,因为这次重定向可能是临时的。
class HttpResponsePermanentRedirect(HttpResponseRedirectBase):status_code = 301
  • 301 永久重定向:HTTP状态码301表示所请求的资源已永久移动到新的URI。客户端(尤其是搜索引擎爬虫)在遇到此重定向后,应该更新其书签或索引,将来所有的请求都应直接发送到新的URL。这对SEO有重要意义。

总结与使用场景

特性HttpResponseRedirect (302)HttpResponsePermanentRedirect (301)
状态码302301
语义临时移动永久移动
浏览器行为会继续使用原URL发起请求可能会缓存重定向,后续直接请求新URL
SEO影响原URL的权重和排名通常不会传递到新URL原URL的权重和排名会传递到新URL
常见使用场景用户登录后跳转、表单提交后跳转(Post/Redirect/Get模式)网站改版更换URL结构、HTTP升级到HTTPS

在实际视图中的用法

在Django视图中,你通常不会直接实例化这些类,而是使用更简短的快捷函数 redirect(),它内部就是创建这些类的实例。

等效的写法:

from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
from django.shortcuts import redirect# 方法一:直接使用类(显式,稍显冗长)
def my_view(request):return HttpResponseRedirect('/some/url/')# 或者 return HttpResponsePermanentRedirect('/some/url/')# 方法二:使用redirect()快捷函数(推荐,更灵活)
def my_view(request):# redirect() 函数默认返回 302 重定向return redirect('/some/url/') # 可以传递一个模型对象,它会自动调用 get_absolute_url()# return redirect(some_model_object) # 可以传递一个视图名和参数# return redirect('view-name', arg=arg) # 要返回 301 重定向,使用 permanent 参数return redirect('/some/url/', permanent=True)

总之,这段代码展示了Django如何通过面向对象的继承和组合,构建出一个既安全(通过协议白名单和IRI转换)又灵活(通过基类和不同状态码的子类)的重定向响应体系。

http://www.xdnf.cn/news/19833.html

相关文章:

  • 2025React面试题集锦
  • Java 与 Docker 的最佳实践
  • wins中怎么用一个bat文件启动jar包和tomcat等多个服务
  • Linux tail 命令使用说明
  • 【C++详解】C++11(四) 包装器:function、bind、STL中⼀些变化
  • 【AI论文】UI-TARS-2技术报告:借助多轮强化学习推进图形用户界面(GUI)智能体发展
  • 20. 云计算-华为云-云服务
  • Linux Centos7搭建LDAP服务(解决设置密码生成密文添加到配置文件配置后输入密码验证报错)
  • 分享星空投影灯方案
  • 高效菜单管理页面:一键增删改查
  • Word 常用快捷键大全:提升文档处理效率的必备技巧​
  • FastGPT源码解析 Agent工作流编排后端详解
  • Ansible自动化运维:从入门到精通
  • 【面试题】词汇表大小如何选择?
  • React实现点击按钮复制操作【navigator.clipboard与document.execCommand】
  • Elasticsearch面试精讲 Day 6:Query DSL查询语法详解
  • 【JAVA】windows本地跑zookeeper,然后使用代码连接服务获取znode数据
  • 【leetcode】130. 被围绕的区域
  • NLP插曲番外 · 猫猫狐狐问答夜话
  • 分词器详解(一)
  • 信息融智学=信息哲学+信息科学+信息技术+信息系统工程+信息处理之智
  • 组长跟我说,她招人看重的是数据分析能力
  • 计算机视觉(七):膨胀操作
  • 机器学习 - Kaggle项目实践(8)Spooky Author Identification 作者识别
  • awk命令
  • GitHub 上那些值得收藏的英文书籍推荐(计算机 非计算机类)
  • 逻辑回归:从原理到实战的完整指南
  • 刻意练习理论
  • 群晖为家纺企业 500 名员工打造企业网盘,赋能家纺制造效率飞跃
  • Python数据分析与处理(二):将数据写回.mat文件的不同方法【超详细】