首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当repoze.who身份验证失败时,如何返回JSON输出?

当repoze.who身份验证失败时,如何返回JSON输出?
EN

Stack Overflow用户
提问于 2015-04-16 11:59:36
回答 1查看 86关注 0票数 1

我正在编写一个插件,希望从repoze.who身份验证中间件返回JSON,并且仍然控制HTTP代码。这是如何做到的呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-16 11:59:36

实现这一点的一种方法是实现挑战者接口。下面的解决方案利用了一个事实,即WebOb异常(在webob.exc中)可以用作WSGI应用程序。下面的示例显示了如何在假设的Facebook插件中使用该插件,在该插件中,2.x API允许用户不授予用户对电子邮件的访问权限,这可能是成功注册/身份验证所必需的:

代码语言:javascript
复制
import json
from webob.acceptparse import MIMEAccept
from webob.exc import HTTPUnauthorized, HTTPBadRequest


FACEBOOK_CONNECT_REPOZE_WHO_NOT_GRANTED = 'repoze.who.facebook_connect.not_granted'


class ExampleJSONChallengerPlugin(object):
    json_content_type = 'application/json'
    mime_candidates = ['text/html',
                       'application/xhtml+xml',
                       json_content_type,
                       'application/xml',
                       'text/xml']

    def is_json_request_env(self, environ):
        """Checks whether the current request is a json request as deemed by
        TurboGears (i.e. response_type is already set) or if the http
        accept header favours 'application/json' over html.
        """
        if environ['PATH_INFO'].endswith('.json'):
            return True

        if 'HTTP_ACCEPT' not in environ:
            return False

        # Try to mimic what Decoration.lookup_template_engine() does.
        return MIMEAccept(environ['HTTP_ACCEPT']) \
            .best_match(self.mime_candidates) is self.json_content_type

    def challenge(self, environ, status, app_headers, forget_headers):
        if FACEBOOK_CONNECT_REPOZE_WHO_NOT_GRANTED in environ:
            response = HTTPBadRequest(detail={
                'not_granted': 
                environ.pop(FACEBOOK_CONNECT_REPOZE_WHO_NOT_GRANTED),
            })
        elif status.startswith('401 '):
            response = HTTPUnauthorized()
        else:
            response = None

        if response is not None and self.is_json_request_env(environ):
            response.body = json.dumps({
                'code': response.code,
                'status': response.title,
                'explanation': response.explanation,
                'detail': response.detail,
            })
            response.content_type = self.json_content_type

        return response

这里的一个要点是,responsewebob.exc.WSGIHTTPException子类的一个实例,它被用作WSGI应用程序,但是如果设置了responsebody属性,那么它就不会自动生成,我们使用这个事实显式地将响应的主体设置为JSON格式的字典字符串表示。如果在处理以'.json‘结尾的URL的请求时调用上述挑战者,或者Accept头包含application/json,响应主体可能会呈现如下:

代码语言:javascript
复制
{
    "status": "Bad Request",
    "explanation": "The server could not comply with the request since it is either malformed or otherwise incorrect.",
    "code": 400, 
    "detail": {"not_granted": ["email"]}
}

如果没有,那么主体将被呈现为HTML:

代码语言:javascript
复制
<html>
 <head>
  <title>400 Bad Request</title>
 </head>
 <body>
  <h1>400 Bad Request</h1>
  The server could not comply with the request since it is either 
  malformed or otherwise incorrect.<br /><br />
{'not_granted': [u'email']}


 </body>
</html>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29674069

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档