Files
pages/2023/08/01/auth.html
2026-01-17 09:36:00 +00:00

459 lines
36 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>如何让Python脚本接收OAuth2.0的Code | Mayx的博客</title>
<meta name="generator" content="Jekyll v3.9.5" />
<meta property="og:title" content="如何让Python脚本接收OAuth2.0的Code" />
<meta name="author" content="mayx" />
<meta property="og:locale" content="zh_CN" />
<meta name="description" content="越简单,就越复杂。" />
<meta property="og:description" content="越简单,就越复杂。" />
<meta property="og:site_name" content="Mayx的博客" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-08-01T00:00:00+08:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="如何让Python脚本接收OAuth2.0的Code" />
<meta name="google-site-verification" content="huTYdEesm8NaFymixMNqflyCp6Jfvd615j5Wq1i2PHc" />
<meta name="msvalidate.01" content="0ADFCE64B3557DC4DC5F2DC224C5FDDD" />
<meta name="yandex-verification" content="fc0e535abed800be" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"mayx"},"dateModified":"2023-08-01T00:00:00+08:00","datePublished":"2023-08-01T00:00:00+08:00","description":"越简单,就越复杂。","headline":"如何让Python脚本接收OAuth2.0的Code","mainEntityOfPage":{"@type":"WebPage","@id":"/2023/08/01/auth.html"},"publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://avatars0.githubusercontent.com/u/17966333"},"name":"mayx"},"url":"/2023/08/01/auth.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="canonical" href="https://mabbs.github.io/2023/08/01/auth.html" />
<link type="application/atom+xml" rel="alternate" href="/atom.xml" title="Mayx的博客" />
<link rel="alternate" type="application/rss+xml" title="Mayx的博客(RSS)" href="/rss.xml" />
<link rel="alternate" type="application/json" title="Mayx的博客(JSON Feed)" href="/feed.json" />
<link rel="stylesheet" href="/assets/css/style.css?v=1768642553" />
<!--[if !IE]> -->
<link rel="stylesheet" href="/Live2dHistoire/live2d/css/live2d.css" />
<!-- <![endif]-->
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="Mayx的博客" />
<link rel="webmention" href="https://webmention.io/mabbs.github.io/webmention" />
<link rel="pingback" href="https://webmention.io/mabbs.github.io/xmlrpc" />
<link rel="preconnect" href="https://summary.mayx.eu.org" crossorigin="anonymous" />
<link rel="prefetch" href="https://www.blogsclub.org/badge/mabbs.github.io" as="image" />
<link rel="blogroll" type="text/xml" href="/blogroll.opml" />
<link rel="me" href="https://github.com/Mabbs" />
<script src="/assets/js/jquery.min.js"></script>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-ajaxtransport-xdomainrequest/1.0.3/jquery.xdomainrequest.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<script>
var lastUpdated = new Date("Sat, 17 Jan 2026 17:35:53 +0800");
var BlogAPI = "https://summary.mayx.eu.org";
</script>
<script src="/assets/js/main.js"></script>
<!--[if !IE]> -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async="async" src="https://www.googletagmanager.com/gtag/js?id=UA-137710294-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-137710294-1');
</script>
<script src="/assets/js/instant.page.js" type="module"></script>
<!-- <![endif]-->
</head>
<body>
<!--[if !IE]> --><noscript><marquee style="top: -15px; position: relative;"><small>发现当前浏览器没有启用JavaScript这不影响你的浏览但可能会有一些功能无法使用……</small></marquee></noscript><!-- <![endif]-->
<!--[if IE]><marquee style="top: -15px; position: relative;"><small>发现当前浏览器为Internet Explorer这不影响你的浏览但可能会有一些功能无法使用……</small></marquee><![endif]-->
<div class="wrapper">
<header class="h-card">
<h1><a class="u-url u-uid p-name" rel="me" href="/">Mayx的博客</a></h1>
<img src="https://avatars0.githubusercontent.com/u/17966333" fetchpriority="high" class="u-photo" alt="Logo" style="width: 90%; max-width: 300px; max-height: 300px;" />
<p class="p-note">Mayx's Home Page</p>
<form action="/search.html">
<input type="text" name="keyword" id="search-input-all" placeholder="Search blog posts.." />&#160;<input type="submit" value="搜索" />
</form>
<br />
<p class="view"><a class="u-url" href="/Mabbs/">About me</a></p>
<ul class="downloads">
<li style="width: 270px; border-right: none;"><a href="/MayxBlog.tgz">Download <strong>TGZ File</strong></a></li>
</ul>
</header>
<section class="h-entry">
<small><time class="date dt-published" datetime="2023-08-01T00:00:00+08:00">1 August 2023</time> - 字数统计3672 - 阅读大约需要12分钟 - Hits: <span id="/2023/08/01/auth.html" class="visitors">Loading...</span></small>
<h1 class="p-name">如何让Python脚本接收OAuth2.0的Code</h1>
<p class="view">by <a class="p-author h-card" href="//github.com/Mabbs">mayx</a></p>
<div id="outdate" style="display:none;">
<hr /><p>
这是一篇创建于 <span id="outime"></span> 天前的文章,其中的信息可能已经有所发展或是发生改变。
</p>
</div>
<script>
daysold = Math.floor((new Date().getTime() - new Date("Tue, 01 Aug 2023 00:00:00 +0800").getTime()) / (24 * 60 * 60 * 1000));
if (daysold > 90) {
document.getElementById("outdate").style.display = "block";
document.getElementById("outime").innerHTML = daysold;
}
</script>
<hr />
<b>AI摘要</b>
<p id="ai-output">这篇文章讨论了在Windows环境下让Python脚本接收OAuth2.0授权码Code的几种方法。作者尝试了以下几种方式
1. **URI Scheme**: 通过注册伪协议如mayx://并在Python脚本中解析回调URL来获取Code但这种方法可能被杀毒软件阻拦且不是所有平台都支持。
2. **HTTP服务监听**: 使用Flask创建一个简单的web服务来接收Code虽然简单但可能占用过多资源且已被弃用。
3. **Socket实现**: 用socket进行TCP连接来处理请求但初次访问时有问题且代码复杂。
4. **http.server模块**: 使用Python内置的HTTP服务器模块实现了基本功能更小且稳定但仍有程序结束前端口未释放的问题后来通过AI得到了解决。
作者在寻找最合适的方案时遇到困难感慨了解更多信息有时也带来困扰但最终还是AI有效地解决了问题。</p>
<hr />
<ul><li><a href="#起因">起因</a></li><li><a href="#解决方法">解决方法</a><ul><li><a href="#1-使用uri-scheme">1. 使用URI Scheme</a></li><li><a href="#2-使用http服务监听">2. 使用http服务监听</a><ul><li><a href="#使用flask实现">使用Flask实现</a></li><li><a href="#使用socket实现">使用socket实现</a></li><li><a href="#使用httpserver实现">使用http.server实现</a></li></ul></li></ul></li><li><a href="#感想">感想</a></li></ul>
<hr />
<main class="post-content e-content" role="main"><p>越简单,就越复杂。<!--more--></p>
<h1 id="起因">
<a href="#起因"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 起因
</h1>
<p>最近我在写一个在Windows上运行的Python脚本需要做一个类似于第三方登录的功能。一般来说像这种东西都是使用的OAuth2.0来做认证我接入的平台没有悬念的也是使用的这个东西其中的重点就是获取到第三方网站的授权码Code然后用它换取用户信息。于是我就在想怎么做比较好呢</p>
<h1 id="解决方法">
<a href="#解决方法"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 解决方法
</h1>
<h2 id="1-使用uri-scheme">
<a href="#1-使用uri-scheme"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 1. 使用URI Scheme
</h2>
<p>我看VSCode在实现类似功能的时候似乎用到了URI Scheme就是在系统中注册一个伪协议然后通过这个伪协议来调用程序实现获取Code方法很简单首先先在注册表里导入</p>
<div class="language-ini highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">Windows</span> <span class="err">Registry</span> <span class="err">Editor</span> <span class="err">Version</span> <span class="err">5.00</span>
<span class="nn">[HKEY_CLASSES_ROOT\mayx]</span>
<span class="err">"URL</span> <span class="err">Protocol"="D:\\mayx.exe"</span>
<span class="err">@="MayxProtocol"</span>
<span class="nn">[HKEY_CLASSES_ROOT\mayx\DefaultIcon]</span>
<span class="err">@="D:\\mayx.exe,1"</span>
<span class="nn">[HKEY_CLASSES_ROOT\mayx\shell]</span>
<span class="nn">[HKEY_CLASSES_ROOT\mayx\shell\open]</span>
<span class="nn">[HKEY_CLASSES_ROOT\mayx\shell\open\command]</span>
<span class="err">@="\"D:\\mayx.exe\"</span> <span class="err">\"%1\""</span>
</code></pre></div></div>
<p>然后编写一个Python脚本并用Pyinstaller打包</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">sys</span>
<span class="k">print</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</code></pre></div></div>
<p>最后将回调地址填为“mayx://get”这样认证完成之后就会像这样调用程序“D:\mayx.exe mayx://get?code=something”再用urllib简单做个解析就完成了。 </p><p>
这样看起来是不是非常的简单看起来确实是挺简单的可惜坑比较大第一个是像上述这样的注册表有些杀毒软件会拒绝导入因为像“shell\open\command”这种东西被病毒啥的滥用的地方太多了除非软件通过了数字签名或者某些认证否则正常情况下根本没法导入。二是不是所有的第三方平台都支持伪协议的方式调用不过我试了一下我用的那个平台倒是支持😂除了杀毒软件比较讨厌之外其他的倒还好。</p>
<h2 id="2-使用http服务监听">
<a href="#2-使用http服务监听"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 2. 使用http服务监听
</h2>
<p>很多跨平台的程序像有些主要在Linux上运行的某些程序就喜欢在获取Code的时候启动一个简单的web服务。其实用这个方法的话可能还更方便一点不容易出问题。</p>
<h3 id="使用flask实现">
<a href="#使用flask实现"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 使用Flask实现
</h3>
<p>最开始我想着要不然就用Flask来实现这个功能吧实现起来也简单写起来就几行</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">flask</span> <span class="kn">import</span> <span class="n">Flask</span><span class="p">,</span> <span class="n">request</span>
<span class="n">code</span> <span class="o">=</span> <span class="s">""</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/getcode'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get</span><span class="p">():</span>
<span class="k">global</span> <span class="n">code</span>
<span class="n">code</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">args</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"code"</span><span class="p">)</span>
<span class="n">shutdown</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">"werkzeug.server.shutdown"</span><span class="p">]</span>
<span class="n">shutdown</span><span class="p">()</span>
<span class="k">return</span> <span class="s">"OK"</span>
<span class="n">app</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="n">host</span><span class="o">=</span><span class="s">"127.0.0.1"</span><span class="p">,</span><span class="n">port</span><span class="o">=</span><span class="mi">8000</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">code</span><span class="p">)</span>
</code></pre></div></div>
<p>看起来也确实很简单功能实现的也很完美但是有个问题是总感觉用Flask做这么简单的事情实在是大材小用打包成程序也要占不少空间另外就是这个方法已经被弃用了感觉就是很不爽。那要说不爽的话怎么才爽呢</p>
<h3 id="使用socket实现">
<a href="#使用socket实现"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 使用socket实现
</h3>
<p>我想起来之前期末时写的期末作业<a href="https://github.com/Mabbs/socket-bbs">socket-bbs</a>这就是用socket实现的一个简单的论坛那我这么简单的功能想来用socket实现不是很好吗于是就写了一个这段代码没有测试因为这个方法不能用所以把代码删了这是重新做的</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">urllib.parse</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span><span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span> <span class="c1">#打开一个网络连接
</span><span class="n">server</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">'127.0.0.1'</span><span class="p">,</span><span class="mi">8000</span><span class="p">))</span> <span class="c1">#绑定要监听的端口
</span><span class="n">server</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># 设置最大的连接数量为5
</span><span class="n">code</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">sock</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">server</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span> <span class="c1"># 建立客户端连接
</span> <span class="n">data</span> <span class="o">=</span> <span class="n">sock</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">8192</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">).</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span><span class="c1">#接收TCP数据数据以字符串的形式返还
</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
<span class="n">sock</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> <span class="c1"># 关闭连接
</span> <span class="k">continue</span>
<span class="n">url</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">parse</span><span class="p">.</span><span class="n">urlparse</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">split</span><span class="p">()[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">if</span> <span class="n">url</span><span class="p">.</span><span class="n">path</span> <span class="o">==</span> <span class="s">'/getcode'</span><span class="p">:</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">parse</span><span class="p">.</span><span class="n">parse_qs</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">)</span>
<span class="n">code</span> <span class="o">=</span> <span class="n">query</span><span class="p">[</span><span class="s">"code"</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">((</span><span class="s">"HTTP/1.0 200 OK"</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">((</span><span class="s">"Content-Type: text/html; charset=utf-8"</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">"OK"</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span> <span class="c1">#发送TCP数据
</span> <span class="n">sock</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> <span class="c1"># 关闭连接
</span> <span class="k">break</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">((</span><span class="s">"HTTP/1.0 404 Not Found"</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">((</span><span class="s">"Content-Type: text/html; charset=utf-8"</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">).</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="n">sock</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">"Not Found"</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span> <span class="c1">#发送TCP数据
</span> <span class="n">sock</span><span class="p">.</span><span class="n">close</span><span class="p">()</span> <span class="c1"># 关闭连接
</span><span class="k">print</span><span class="p">(</span><span class="n">code</span><span class="p">)</span>
</code></pre></div></div>
<p>看起来是不是复杂多了?其实大多数时候工作的好像挺正常的,但是不知道为什么莫名其妙第一次访问的时候会卡住,改了半天头都大了,于是就只好放弃这种方法了……</p>
<h3 id="使用httpserver实现">
<a href="#使用httpserver实现"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 使用http.server实现
</h3>
<p>这时候我突然想到我平时用来传文件用的python自带的模块http.server既然这个模块是自带的大小应该大不到哪去吧随后我就写了一个</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">http.server</span> <span class="kn">import</span> <span class="n">BaseHTTPRequestHandler</span><span class="p">,</span> <span class="n">ThreadingHTTPServer</span>
<span class="kn">import</span> <span class="nn">urllib.parse</span>
<span class="n">code</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">class</span> <span class="nc">Resquest</span><span class="p">(</span><span class="n">BaseHTTPRequestHandler</span><span class="p">):</span>
<span class="n">timeout</span> <span class="o">=</span> <span class="mi">5</span>
<span class="k">def</span> <span class="nf">do_GET</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">parse</span><span class="p">.</span><span class="n">urlparse</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">path</span><span class="p">)</span>
<span class="k">if</span> <span class="n">url</span><span class="p">.</span><span class="n">path</span> <span class="o">==</span> <span class="s">"/getuser"</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">send_response</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">send_header</span><span class="p">(</span><span class="s">"Content-type"</span><span class="p">,</span> <span class="s">"text/html"</span><span class="p">)</span> <span class="c1"># 设置服务器响应头
</span> <span class="n">code</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">parse</span><span class="p">.</span><span class="n">parse_qs</span><span class="p">(</span><span class="n">url</span><span class="p">.</span><span class="n">query</span><span class="p">)[</span><span class="s">"code"</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">buf</span> <span class="o">=</span> <span class="s">'''OK'''</span>
<span class="bp">self</span><span class="p">.</span><span class="n">wfile</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">shutdown</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">send_response</span><span class="p">(</span><span class="mi">404</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">send_header</span><span class="p">(</span><span class="s">"Content-type"</span><span class="p">,</span> <span class="s">"text/html"</span><span class="p">)</span> <span class="c1"># 设置服务器响应头
</span> <span class="bp">self</span><span class="p">.</span><span class="n">end_headers</span><span class="p">()</span>
<span class="n">buf</span> <span class="o">=</span> <span class="s">'''Not Found'''</span>
<span class="bp">self</span><span class="p">.</span><span class="n">wfile</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
<span class="n">host</span> <span class="o">=</span> <span class="p">(</span><span class="s">"127.0.0.1"</span><span class="p">,</span> <span class="mi">8000</span><span class="p">)</span>
<span class="n">server</span> <span class="o">=</span> <span class="n">ThreadingHTTPServer</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">Resquest</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Starting server, listen at: %s:%s"</span> <span class="o">%</span> <span class="n">host</span><span class="p">)</span>
<span class="n">server</span><span class="p">.</span><span class="n">serve_forever</span><span class="p">()</span>
<span class="n">server</span><span class="p">.</span><span class="n">socket</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">code</span><span class="p">)</span>
</code></pre></div></div>
<p>最后打包试了一下功能正常虽然还是大了点不过比Flask小😁。其实我在写这个代码的时候最开始不知道要在最后加上<code class="language-plaintext highlighter-rouge">server.socket.close()</code>一开始写的时候总是遇到程序执行完之前端口必定不会释放令人很烦直接搜也没什么好的结果不过问了下ChatGPT立马就解决了🤣它说</p>
<blockquote>
<p>当你调用<code class="language-plaintext highlighter-rouge">server.shutdown()</code>来停止服务器时它会停止接收新的连接并关闭已有的连接。但是由于Python的socket库的设计socket对象并不会立即释放端口。相反它会在一段时间内处于TIME_WAIT状态以确保在网络中所有挂起的数据都被正确传递或丢弃。这是一种网络协议的要求称为”TCP TIME_WAIT”状态。</p>
</blockquote>
<p>AI还真是方便啊……</p>
<h1 id="感想">
<a href="#感想"><svg class='octicon' viewBox='0 0 16 16' version='1.1' width='16' height='32' aria-hidden='true'><path fill-rule='evenodd' d='M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z'></path></svg></a> 感想
</h1>
<p>解决这么一个小问题却一时半会拿不下最合适的方案这难道就是了解太多的副作用吗😝不过最终来看还是AI厉害一下子就解决了我的问题。</p></main>
<small style="display: block">tags: <a rel="category tag" class="p-category" href="/search.html?keyword=Python"><em>Python</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=%E6%9C%8D%E5%8A%A1%E5%99%A8"><em>服务器</em></a> - <a rel="category tag" class="p-category" href="/search.html?keyword=OAuth"><em>OAuth</em></a> <span style="float: right;"><a href="https://gitlab.com/mayx/mayx.gitlab.io/tree/master/_posts/2023-08-01-auth.md">查看原始文件</a></span></small>
<h4 style="border-bottom: 1px solid #e5e5e5;margin: 2em 0 5px;">推荐文章</h4>
<p id="suggest-container">Loading...</p>
<script>
var suggest = $("#suggest-container");
$.get(BlogAPI + "/suggest?id=/2023/08/01/auth.html&update=" + lastUpdated.valueOf(), function (data) {
if (data.length) {
getSearchJSON(function (search) {
suggest.empty();
var searchMap = {};
for (var i = 0; i < search.length; i++) {
searchMap[search[i].url] = search[i];
}
var tooltip = $('<div class="content-tooltip"></div>').appendTo('body').hide();
for (var j = 0; j < data.length; j++) {
var item = searchMap[data[j].id];
if (item) {
var link = $('<a href="' + item.url + '">' + item.title + '</a>');
var contentPreview = item.content.substring(0, 100);
if (item.content.length > 100) {
contentPreview += "……";
}
link.hover(
function(e) {
tooltip.text($(this).data('content'))
.css({
top: e.pageY + 10,
left: e.pageX + 10
})
.show();
},
function() {
tooltip.hide();
}
).mousemove(function(e) {
tooltip.css({
top: e.pageY + 10,
left: e.pageX + 10
});
}).data('content', contentPreview);
suggest.append(link);
suggest.append(' - ' + item.date + '<br />');
}
}
});
} else {
suggest.html("暂无推荐文章……");
}
});
</script>
<br />
<div class="pagination">
<span class="prev">
<a href="/2023/07/09/bitmo.html">
上一篇:分享一种无人值守的新型诈骗手段
</a>
</span>
<br />
<span class="next">
<a href="/2023/09/06/satellite.html">
下一篇:关于卫星通信的一些看法
</a>
</span>
</div>
<!--[if !IE]> -->
<link rel="stylesheet" href="/assets/css/gitalk.css">
<script src="/assets/js/gitalk.min.js"></script>
<div id="gitalk-container"></div>
<script>
var gitalk = new Gitalk({
clientID: '36557aec4c3cb04f7ac6',
clientSecret: 'ac32993299751cb5a9ba81cf2b171cca65879cdb',
repo: 'mabbs.github.io',
owner: 'Mabbs',
admin: ['Mabbs'],
id: '/2023/08/01/auth', // Ensure uniqueness and length less than 50
distractionFreeMode: false, // Facebook-like distraction free mode
proxy: "https://cors-anywhere.mayx.eu.org/?https://github.com/login/oauth/access_token"
})
gitalk.render('gitalk-container')
</script>
<!-- <![endif]-->
</section>
<!--[if !IE]> -->
<div id="landlord" style="left:5px;bottom:0px;">
<div class="message" style="opacity:0"></div>
<canvas id="live2d" width="500" height="560" class="live2d"></canvas>
<div class="live_talk_input_body">
<form id="live_talk_input_form">
<div class="live_talk_input_name_body" >
<input type="checkbox" id="load_this" />
<input type="hidden" id="post_id" value="/2023/08/01/auth.html" />
<label for="load_this">
<span style="font-size: 11px; color: #fff;">&#160;想问这篇文章</span>
</label>
</div>
<div class="live_talk_input_text_body">
<input name="talk" type="text" class="live_talk_talk white_input" id="AIuserText" autocomplete="off" placeholder="要和我聊什么呀?" />
<button type="submit" class="live_talk_send_btn" id="talk_send">发送</button>
</div>
</form>
</div>
<input name="live_talk" id="live_talk" value="1" type="hidden" />
<div class="live_ico_box" style="display:none;">
<div class="live_ico_item type_info" id="showInfoBtn"></div>
<div class="live_ico_item type_talk" id="showTalkBtn"></div>
<div class="live_ico_item type_music" id="musicButton"></div>
<div class="live_ico_item type_youdu" id="youduButton"></div>
<div class="live_ico_item type_quit" id="hideButton"></div>
<input name="live_statu_val" id="live_statu_val" value="0" type="hidden" />
<audio src="" style="display:none;" id="live2d_bgm" data-bgm="0" preload="none"></audio>
<input id="duType" value="douqilai" type="hidden" />
</div>
</div>
<div id="open_live2d">召唤伊斯特瓦尔</div>
<!-- <![endif]-->
<footer>
<p>
<small>Made with ❤ by Mayx<br />Last updated at 2026-01-17 17:35:53<br /> 总字数614622 - 文章数178 - <a href="/atom.xml" >Atom</a> - <a href="/README.html" >About</a></small>
</p>
</footer>
</div>
<script src="/assets/js/scale.fix.js"></script>
<!--[if !IE]> -->
<script src="/assets/js/main_new.js"></script>
<script src="/Live2dHistoire/live2d/js/live2d.js"></script>
<script src="/Live2dHistoire/live2d/js/message.js"></script>
<!-- <![endif]-->
</body>
</html>