草庐IT

python - 中间件筛选器页面的安全问题

coder 2023-08-18 原文

虽然我的启动处于暗模式,但我希望除访问/之外的所有访问权限都可以转到筛选器页面,用户在该页面上输入了代表给他们的密码。我提出了以下简单的中间件来执行任务。需要明确的是,这是为了确保用户同意在允许网站四处浏览之前对网站保密,而不是将其用作安全系统或 .htaccess 克隆。但是我想阻止他们在不知道筛选器密码的情况下看到任何公共(public)页面(即那些没有用@login_required 装饰的页面)。 password_check 函数使用 Django Auth 生成输入密码的哈希值以检查数据库值。

大家有什么思路/规避技巧可以看看?我的一个想法是更改登录功能以将 LicenceKey 推送到新登录的用户 session 中,而不是为登录用户提供豁免。然而,由于他们只能通过登录来创建新 session ,并且登录需要同意筛选器,所以这似乎是多余的。

感谢反馈。

中间件看起来像这样:

from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
import re

class LicenceScreener(object):
    SCREENER_PATH = reverse("licence")
    INDEX_PATH = reverse("index")
    LICENCE_KEY = "commercial_licence"
    def process_request(self, request):
        """ Redirect any access not to the index page to a commercial access screener page
            When the screener form is submitted, request.session[LICENCE_KEY] is set.
        """
        if not LicenceScreener.LICENCE_KEY in request.session \
            and not request.user.is_authenticated() \
            and LicenceScreener.SCREENER_PATH != request.path\
            and LicenceScreener.INDEX_PATH != request.path:
                return HttpResponseRedirect(self.SCREENER_PATH)

View 看起来像这样:

def licence(request):
    c = RequestContext(request, {}  )
    if request.method == 'POST':
        form = LicenceAgreementForm(request.POST)
        if form.is_valid():
            if password_check(form.cleaned_data["password"]):
                request.session[LicenceScreener.LICENCE_KEY] = True
                return HttpResponseRedirect(reverse("real-index"))
            else:
                form._errors["password"] = form.error_class([_("Sorry that password is incorrect")])    
    else:
        form = LicenceAgreementForm()  
    c["form"] = form        
    return render_to_response('licence.html',c)

编辑 1. 按照 Tobu 的建议删除正则表达式

最佳答案

这是我的解决方案。它使用的不是 COOKIES,而是自定义 Auth Backend。

第一步

有一个 Django 应用程序 很好:

key_auth/
    templates/
        key_auth_form.html # very simple form template
    __init__.py
    models.py
    urls.py
    views.py
    forms.py
    middleware.py
    backend.py

settings.py:

INSTALLED_APPS = (
    # ...
    'key_auth',
)

第二步

我们需要一个模型来存储您的代币。 模型.py:

from django.db import models
from django.contrib.auth.models import User

class SecurityKey(models.Model):
    key = models.CharField(max_length=32, unique=True)
    user = models.OneToOneField(User)

注意:在我的简单解决方案中,您需要手动创建和同步新用户及其安全 key 。但您可以在未来改进这一点。

第三步

我们需要一个自定义的中间件,它将要求所有页面上的所有用户进行身份验证(少数特殊页面除外)。这是 middleware.py:

from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse

class KeyAuthMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        login_url = reverse('key_auth_login') # your custom named view

        # Exceptional pages
        login_page = request.path.find(login_url) == 0
        logout_page = request.path.find(reverse('logout')) == 0
        admin_page = request.path.find(reverse('admin:index')) == 0 # I've excluded Admin Site urls

        if not login_page and not logout_page and not admin_page:
            view_func = login_required(view_func, login_url=login_url)

        return view_func(request, *view_args, **view_kwargs)

此中间件会将未经授权的用户重定向到“key_auth_login”页面,其中包含授权表单。

第四步

这是映射“key_auth_login” View 的 urls.py:

from django.conf.urls.defaults import patterns, url

urlpatterns = patterns('key_auth.views',
    url(r'^$', 'login_view', name='key_auth_login'),
)

以及全局项目的urls.py:

from django.contrib import admin
from django.conf.urls.defaults import patterns, include, url

admin.autodiscover()

urlpatterns = patterns('',
    url(r'^key_auth/$', include('key_auth.urls')),
    url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name='logout'),
    url(r'^admin/', include(admin.site.urls)),
    url(r'^$', 'views.home_page'),
)

如您所见 - 管理站点已打开(因此您也可以以管理员身份登录)。

第 5 步

这是我们的观点 (views.py):

from django.contrib.auth import login
from django.views.generic.edit import FormView
from key_auth.forms import KeyAuthenticationForm

class KeyAuthLoginView(FormView):
    form_class = KeyAuthenticationForm
    template_name = 'key_auth_form.html'

    def form_valid(self, form):
        login(self.request, form.user)
        return super(KeyAuthLoginView, self).form_valid(form)

    def get_success_url(self):
        return self.request.REQUEST.get('next', '/')

login_view = KeyAuthLoginView.as_view()

我不会显示“key_auth_form.html”,因为它是非常简单的表单模板,没什么特别的。但我会展示形式类

第六步

表单类(forms.py):

from django import forms
from django.contrib.auth import authenticate

class KeyAuthenticationForm(forms.Form):
    key = forms.CharField('Key', help_text='Enter your invite/authorization security key')
    user = None

    def clean_key(self):
        key = self.cleaned_data['key']
        self.user = authenticate(key=key)
        if not self.user:
            raise forms.ValidationError('Please, enter valid security key!')
        return key

正如我们所见,这里使用了 authenticate() 。此方法将尝试使用现有后端对用户进行身份验证。

第七步

自定义身份验证后端。 后端.py:

from django.contrib.auth.models import User
from key_auth.models import SecurityKey

class KeyAuthBackend(object):
    def authenticate(self, key=None):
        try:
            return SecurityKey.objects.get(key=key).user
        except SecurityKey.DoesNotExist:
            return None

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None

非常简单!只需检查 key ( token )。 这是它的安装 (settings.py):

AUTHENTICATION_BACKENDS = (
    'key_auth.backends.KeyAuthBackend',
    'django.contrib.auth.backends.ModelBackend',
)

留下第二个以保持管理站点正常运行。

简历

就是这样!

  1. 任何请求都通过 KeyAuthMiddleware
  2. KeyAuthMiddleware 跳过登录、注销和管理 url ...
  3. ... 并将所有未经授权的用户重定向到 token 验证登录页面(使用 token 登录表单)
  4. 此表单通过 django.contrib.auth.authenticate() 方法验证“ key ”...
  5. ... 尝试通过自定义 KeyAuthBackend 身份验证后端对用户进行身份验证
  6. 如果身份验证成功且表单有效,则自定义 KeyAuthLoginView 生成 django.contrib.auth.login(user) 并重定向到请求的页面

您还可以在没有 key_auth ckeck 的情况下使用管理站点和登录/注销 View 。

关于python - 中间件筛选器页面的安全问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6408399/

有关python - 中间件筛选器页面的安全问题的更多相关文章

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

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

  2. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  6. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  7. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  8. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  9. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  10. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

随机推荐