Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Cron作业无法访问带有admin_必需装饰符的url_Python_Unit Testing_Google App Engine_Flask_Cron - Fatal编程技术网

Python Cron作业无法访问带有admin_必需装饰符的url

Python Cron作业无法访问带有admin_必需装饰符的url,python,unit-testing,google-app-engine,flask,cron,Python,Unit Testing,Google App Engine,Flask,Cron,根据文档,应允许Cron作业访问受管理保护的视图。但是,如果在get方法上有@admin\u required装饰程序,则会出现302错误 在应用程序yaml中,我定义了: - url: /generator script: run.news.app login: admin 视图: class GeneratorView(MethodView): @admin_required def get(self): return 'success', 200

根据文档,应允许Cron作业访问受管理保护的视图。但是,如果在get方法上有
@admin\u required
装饰程序,则会出现302错误

在应用程序yaml中,我定义了:

- url: /generator
  script: run.news.app
  login: admin
视图:

class GeneratorView(MethodView):
    @admin_required
    def get(self):
        return 'success', 200
cron:
- description: Scrape every 3 hours
  url: /generator
  schedule: every 3 hours synchronized
def admin_required(func):
    """Requires App Engine admin credentials"""

    @wraps(func)
    def decorated_view(*args, **kwargs):
        if users.get_current_user():
            if not users.is_current_user_admin():
                abort(401)  # Unauthorized
            return func(*args, **kwargs)
        return redirect(users.create_login_url(request.url))

    return decorated_view
url.py

app.add_url_rule('/generator', 'generator', view_func=GeneratorView.as_view('generator'))
cron作业:

class GeneratorView(MethodView):
    @admin_required
    def get(self):
        return 'success', 200
cron:
- description: Scrape every 3 hours
  url: /generator
  schedule: every 3 hours synchronized
def admin_required(func):
    """Requires App Engine admin credentials"""

    @wraps(func)
    def decorated_view(*args, **kwargs):
        if users.get_current_user():
            if not users.is_current_user_admin():
                abort(401)  # Unauthorized
            return func(*args, **kwargs)
        return redirect(users.create_login_url(request.url))

    return decorated_view
装饰师:

class GeneratorView(MethodView):
    @admin_required
    def get(self):
        return 'success', 200
cron:
- description: Scrape every 3 hours
  url: /generator
  schedule: every 3 hours synchronized
def admin_required(func):
    """Requires App Engine admin credentials"""

    @wraps(func)
    def decorated_view(*args, **kwargs):
        if users.get_current_user():
            if not users.is_current_user_admin():
                abort(401)  # Unauthorized
            return func(*args, **kwargs)
        return redirect(users.create_login_url(request.url))

    return decorated_view
有趣的是,当我删除
admin\u required
decorator时,由于app.yaml中的
login:admin
,url仍然只受admin保护

但是,由于缺少decorator,我的单元测试没有通过授权检查

def test_generator_fails_as_normal_user(self):
        self.setCurrentUser(u'john@example.com', u'123')
        rv = self.client.get('/generator')
        self.assertEqual(rv.status_code, 401)
断言错误:200!=401


如果我把装饰器放回去,单元测试通过,cron作业失败。有什么建议吗?

单元测试的
self.client.get
无疑不会返回到
app.yaml
进行路由选择——因此,如果您删除在decorator中执行的应用程序级别检查,它会允许非管理员用户通过也就不足为奇了

然而,真正的问题是,当
cron
点击该URL时,装饰程序没有发现任何人“登录”。这是在以下位置暗示的(当然应该更清楚/明确地记录!):

注意:虽然cron作业可以使用受
登录:admin限制的URL路径,但是,
他们不能使用受
登录:必需
限制的URL路径

这表明服务基础结构不会通过检查当前登录的用户来验证cron请求,因为它不会发现任何请求。相反,它依赖于请求中的

来自Cron服务的请求还将包含HTTP头:

X-AppEngine-Cron:true

X-AppEngine-Cron
头由Google App Engine在内部设置。如果 您的请求处理程序找到此标头,它可以信任该请求 是一个cron请求。如果标头存在于外部用户中 请求您的应用程序时,它将被剥离,但来自已登录应用程序的请求除外 在应用程序的管理员中,允许谁设置 标题用于测试目的

因此,您的装饰程序必须检查
self.request
——如果发现
X-AppEngine-Cron:true
,它必须让请求通过,否则它可以继续执行您现在正在执行的检查

我不太确定在您选择的web框架中如何最好地获取请求的标题,您没有提到,但如果它是例如
webapp2
,则类似于:

@wraps(func)
def decorated_view(self, *args, **kwargs):
    if self.request.headers.get('X-AppEngine-Cron') == 'true':
        return func(self, *args, **kwargs)
    # continue here with the other checks you do now
应该做到这一点。

似乎在说你不能像这样装饰你的方法:

装饰视图

因为视图类本身不是视图 添加到路由系统中的功能它没有多大用处 装饰班级本身的意义。相反,你要么 手动装饰as_view()的返回值:

从烧瓶0.8开始,还有另一种方法可以 指定要在类声明中应用的装饰器列表:

class UserAPI(MethodView):
    decorators = [user_required]
由于来电者的隐式自我,您无法使用 但是,在视图的各个方法上使用常规视图装饰器, 记住这一点。


不过,我不明白其中的道理

谢谢你的全面回复。我正在使用
烧瓶
。我希望这个片段在那里也能起作用。我要试一试。感谢
if request.headers.get('X-AppEngine-Cron')=='true':return func(*args,**kwargs)
在Flask中工作。非常感谢