如何使用WSGI将用户从http重新路由到https

Mar*_*nch 7 python ssl https google-app-engine webapp2

原始问题


App Engine SDK 1.6.5
Python 2.7
webapp2

我已经实现了webapp2方案来保护页面到https.问题是,当用户说http:// site/login而不是https:// site/login时,由于方案无法识别路由,因此会出现404错误.

示例main.py

#  Libraries
import webapp2

#  Local Controllers
from controllers.HomeHandler import HomeHandler
from controllers.LoginHandler import LoginHandler

app = webapp2.WSGIApplication([
    webapp2.Route(r'/', HomeHandler),
    webapp2.Route(r'/login', LoginHandler, schemes=['https'], name='login')
], debug=True)
Run Code Online (Sandbox Code Playgroud)

我在https路由下面添加了另一个路由/控制器来捕获http请求:
webapp2.Route(r'/login', RouteLogin)

RouteLogin.py

#  Libraries
import webapp2

class RouteLogin(webapp2.RequestHandler):
    def get(self):
        self.redirect('https://site.appspot.com/login')
Run Code Online (Sandbox Code Playgroud)

这有效,但似乎应该有更好的方法来做到这一点.就像在Apache Web服务器上使用htaccess一样.这对我喜欢的黑客来说太像了.我真的不喜欢我的代码中的硬编码URL.更不用说登录的2个请求并不是什么大不了的事,但可能还有其他一些例子,它最终导致成本太高.

注意1:如果您正在查看此解决方案,请注意使用HTTPS方案还意味着您将无法在不删除SCHEME或配置为dev设置的变量的情况下使用开发控制台.

注意2:我能够以编程方式提供HTTPS而不是HTTP.我在正确的轨道上有下面的评论,但它需要一个参数.

webapp2.uri_for('login', _scheme='https')
这将为您提供正确的https://someapp.appspot.com/login网址.遗憾的是,我没有处理我的主要问题,如何处理人们在没有https的情况下在地址栏中键入url并收到错误,除非我使用上面的hack.所以我仍然在寻找WSGI方式将收入请求路由到HTPPS.

编辑:添加了注释1并澄清了标题,我认为很明显我是从源代码而不是CGI使用WSGI.

Wil*_*hes 8

在app.yaml中设置URL,而不是在代码中.请参阅https://developers.google.com/appengine/docs/python/config/appconfig#Secure_URLs

例如:

handlers:

- url: /foo/.*
  script: accounts.py
  secure: always
Run Code Online (Sandbox Code Playgroud)

这会将HTTP重定向到HTTPS.

  • "secure:always"选项也适用于WSGI处理程序.请注意,只要最常用的模式是最后一个,您可以使用相同的处理程序(main.app,我假设)但具有不同的url模式和不同选项的多个子句. (3认同)

Mar*_*nch 1

这是我在测试这个问题时使用的工作代码。

注意:开发 Web 服务器(截至撰写本文时为 v1.6.5)不支持 https,因此您的 WSGI 路由需要删除这些方案才能在开发环境中工作。您可以在部署之前将它们添加回来,或者创建一个变量来设置检查环境的方案,如下所示。

您可以通过将 app.yaml 定义为:
app.yaml让 App Engine Python 重新路由请求

application: cgi-vs-wsgi
version: 1
runtime: python27
api_version: 1
threadsafe: yes

libraries:
- name: webapp2
  version: latest

handlers:

- url: /profile
  script: main.app
  secure: always

- url: /login
  script: main.app
  secure: always

- url: /.*
  script: main.app
Run Code Online (Sandbox Code Playgroud)

然后在 main.py 中,您可以像平常一样声明 WSGI 处理程序,如下所示:

主要.py

import webapp2
import os

# Models
from models.Shout import Shout

# Controllers
from controllers.HomeHandler import HomeHandler
from controllers.LoginHandler import LoginHandler
from controllers.ProfileHandler import ProfileHandler

if os.environ['SERVER_SOFTWARE'].startswith('Development'):
    app_scheme = 'http'
else:
    app_scheme = 'https'

app = webapp.WSGIApplication([
    webapp2.Route(r'/login', LoginHandler, name='login', schemes=[app_scheme]),
    webapp2.Route(r'/profile', ProfileHandler, name='profile', schemes=[app_scheme]),
    webapp2.Route(r'/', HomeHandler)
], debug=True)
Run Code Online (Sandbox Code Playgroud)

我已将此应用程序的代码上传到我的AE-BaseApp GitHub,请随意下载并在您的应用程序中使用它。该代码已获得 Apache License 2.0 许可。