草庐IT

python - flask 的双向 ssl 身份验证

coder 2023-05-27 原文

我已经实现了 SSL 通信,其中客户端应用程序使用 flask 验证 SSL 服务器应用程序的身份。现在我希望 SSL 服务器应用程序验证 SSL 客户端应用程序的身份。 flask 可以吗?如何验证客户端证书?在第一次握手期间,客户端发送 CSR,作为响应,我发送回由自签名 CA 证书签名的证书。

但我还不清楚下一次通信时服务器将如何验证客户端。证书验证是否有任何回调。链接 Google groups说它不可能在 Flask 上进行 ssl 身份验证。为了做到这一点,需要使用像 apache、ngnix 这样的网络服务器。这是验证客户端的唯一方法吗?

我还想实现一件事,即我需要根据每个客户的证书来识别他们。 flask 甚至可以吗?

我的问题可能很幼稚,因为我对 flask 还不太熟悉

最佳答案

免责声明

在我开始之前,我会注意@Emanuel Ey 的评论。您需要考虑是否首先在生产或开发服务器上完成。例如;如果您使用的是 Apache WebServer,则可以从 Apache 完成 HTTPS 组件。唯一不同的做法是将证书详细信息作为选项传递,然后您的服务器应用程序将在应用程序本身内验证序列号。

有可能

但它可能的方式并不被认为是良好的编程习惯。不幸的是,它不能从 flask.request 访问,并且不能通过 Flask 包访问。但是,Flask 使用 Werkzeug,可以通过修补 werkzeug.serving 包来编写您的主要 Flask 代码。不建议这样做,因为您可能希望稍后更新 Flask 或 Werkzeug,并且您的补丁可能会损坏并需要重新分解。即从 0.9 到 1.0。

这提供了一个不使用 Web 服务器的解决方案。但我会推荐 Web 服务器/环境变量组合。这是更清洁且相对较好的做法。

我做了一些测试,看看这是否容易实现。我能够确认此方法可以使用最新的开发代码库“Werkzeug-0.10_devdev_20141223-py2.7”。

您可能需要验证在每个证书中找到的序列号(种子号)(甚至可能还有其他一些变量)。您可能知道,序列号对于每个证书都是唯一的,并且在证书生成过程中由您在服务器端确定。它有助于将其与客户端记录和证书信息(如果适用)一起存储,以便稍后验证客户端证书序列号。注意:它可能需要在十六进制和以 10 为底的十进制之间进行更改。

Werkzeug dev_2014122

我所做的是将以下选项添加到对 wrap_socket()werkzeug.serving.BaseWSGIServer.__init__ 调用中。

使用这些; server_side=True, ca_certs= '/etc/apache2/ssl/ca.pem', cert_reqs=ssl.CERT_REQUIRED

  • ca_certs:用这个来验证,这是用来生成客户端证书的CA证书)
  • ssl.CERT_REQUIRED:要求针对 ca_certs 验证客户端证书

注意:如果客户端证书未通过初始验证,您将无法获取客户端证书。它将是无。

然后在我的 Flask 测试类中我修补了 verify_request 在哪里

def verify_request(self, request, client_address):

cert = request.getpeercert(True)
raw = decoder.decode(cert)[0]
print "Serial Number of your certificate is: % " % str(raw[0][1])
# todo: do checks & if serial no is ok then return true
return True

werkzeug.serving.BaseWSGIServer.verify_request = verify_request

这证明这是可能的,但您可能需要调查 BaseWSGIServer 继承的 HTTPServer 类的请求处理程序,以找到更好的方法来进行回调或覆盖。

Werkzeug 0.9.X

如果您使用的是 Werkzeug 0.9.X,我假设您使用的是 import from OpenSSL import SSL。见代码片段 here .我没有测试过。

您可能对此版本感兴趣的一些电话是: - Context.set_verify(mode, callback) - Connection.get_peer_certificate()

澄清

我不明白的是您提到在第一次握手期间发送 CSR。如果这是您生成客户端证书的过程,您可能需要重新考虑如何在系统和环境的上下文中执行此操作。如果我能有更多的信息,我可以进一步评论..

此外,SSL/TLS 上下文中的“握手”通常是指首先使用现有证书创建安全连接的操作。握手后立即建立连接。

关于python - flask 的双向 ssl 身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23262768/

有关python - flask 的双向 ssl 身份验证的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  4. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  5. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  6. ruby-on-rails - 如何将验证与模型分开 - 2

    我有一些非常大的模型,我必须将它们迁移到最新版本的Rails。这些模型有相当多的验证(User有大约50个验证)。是否可以将所有这些验证移动到另一个文件中?说app/models/validations/user_validations.rb。如果可以,有人可以提供示例吗? 最佳答案 您可以为此使用关注点:#app/models/validations/user_validations.rbrequire'active_support/concern'moduleUserValidationsextendActiveSupport:

  7. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  8. ruby - 如何在 Rails 4 中使用表单对象之前的验证回调? - 2

    我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser

  9. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  10. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

随机推荐