从服务器而不是浏览器访问 API 时出现 403 错误

Posted

技术标签:

【中文标题】从服务器而不是浏览器访问 API 时出现 403 错误【英文标题】:403 error when accessing API from server and not from browser 【发布时间】:2016-05-08 21:39:54 【问题描述】:

我正在尝试使用 Python 和 urllib2 访问 Buxfer REST API。

问题是我得到以下响应:

urllib2.HTTPError: HTTP Error 403: Forbidden

但是当我通过浏览器尝试相同的调用时,它工作正常...

脚本如下:

username = "xxx@xxxcom"
password = "xxx"

    #############

def checkError(response):
    result = simplejson.load(response)
    response = result['response']
    if response['status'] != "OK":
        print "An error occured: %s" % response['status'].replace('ERROR: ', '')
        sys.exit(1)

    return response

base = "https://www.buxfer.com/api";
url  = base + "/login?userid=" + username + "&password=" + password;

req = urllib2.Request(url=url)
response = checkError(urllib2.urlopen(req))
token = response['token']

url  = base + "/budgets?token=" + token;
req = urllib2.Request(url=url)
response = checkError(urllib2.urlopen(req))
for budget in response['budgets']:
    print "%12s %8s %10.2f %10.2f" % (budget['name'], budget['currentPeriod'], budget['limit'], budget['remaining'])

sys.exit(0)

我也尝试使用 requests 库,但出现了同样的错误。 我要访问的服务器是 ubuntu 14.04,任何有关解释或解决为什么会发生这种情况的帮助将不胜感激。

编辑:

这是完整的错误信息:

                                                                                                            
  'cookies': <<class 'requests.cookies.RequestsCookieJar'>[]>,                                               
  '_content': '                                                                                              
    <!DOCTYPE html PUBLIC "-//IETF//DTD HTML 2.0//EN">                                                       
    <html><head>                                                                                             
    <title>403 Forbidden</title>                                                                             
    </head><body>                                                                                            
    <h1>Forbidden</h1>                                                                                       
    <p>You don't have permission to access /api/login                                                        
    on this server.</p>                                                                                      
    <hr>                                                                                                     
    <address>Apache/2.4.7 (Ubuntu) Server at www.buxfer.com Port 443</address>                               
    </body></html>',                                                                                         
  headers': CaseInsensitiveDict(                                                                            
    'date': 'Sun, 31 Jan 2016 12:06:44 GMT',                                                                 
    'content-length': '291',                                                                                 
    'content-type': 'text/html; charset=iso-8859-1',                                                         
    'server': 'Apache/2.4.7 (Ubuntu)'                                                                        
  ),                                                                                                        
  'url': u'https://www.buxfer.com/api/login?password=xxxx&userid=xxxx%40xxxx.com',                           
  'status_code': 403,                                                                                        
  '_content_consumed': True,                                                                                 
  'encoding': 'iso-8859-1',                                                                                  
  'request': <PreparedRequest [GET]>,                                                                        
  'connection': <requests.adapters.HTTPAdapter object at 0x7fc7308102d0>,                                    
  'elapsed': datetime.timedelta(0, 0, 400442),                                                               
  'raw': <urllib3.response.HTTPResponse object at 0x7fc7304d14d0>,                                           
  'reason': 'Forbidden',                                                                                     
  'history': []                                                                                              
             

编辑 2:(GoogleChrome 浏览器中的网络参数)

Request Method:GET
Status Code:200 OK
Remote Address:52.20.61.39:443
Response Headers
view parsed
HTTP/1.1 200 OK
Date: Mon, 01 Feb 2016 11:01:10 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Frame-Options: SAMEORIGIN
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Cache-Controle: no-cache
Set-Cookie: login=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; domain=buxfer.com
Set-Cookie: remember=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; domain=buxfer.com
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/x-javascript; charset=utf-8
Request Headers
view source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,fr;q=0.6
Connection:keep-alive
Cookie:phpSESSID=pjvg8la01ic64tkkfu1qmecv20; api-session=vbnbmp3sb99lqqea4q4iusd4v3; __utma=206445312.1301084386.1454066594.1454241953.1454254906.4; __utmc=206445312; __utmz=206445312.1454066594.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
Host:www.buxfer.com
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36

编辑 3:

我也可以通过我的本地 pycharm 控制台毫无问题地访问,只是当我尝试从我的远程服务器进行访问时...

【问题讨论】:

你能发布完整的错误信息吗?哪个请求会导致 403?你拿到令牌了吗? 当我在 buxfer 上创建帐户时,您的代码对我来说运行完美。我在 Ubuntu 14.04.3 上运行 Python 2.7.6。 嗨 Rob,你有 /var/www 文件夹吗?我在一些论坛中看到一些 API 要求此文件夹存在以用于回调过程 您使用的是真实的用户名和密码吗?从错误消息看来,您使用的用户无效。 403 Forbidden 并不奇怪。 我是,我正在使用在我的网络浏览器上的脚本中创建的相同 url,我可以访问。 【参考方案1】:

您可能需要执行 POST 而不是 GET 请求。大多数登录都是这样工作的。

使用 requests 库,您需要

response = requests.post(
    base + '/login',
    data=
        'userid': username,
        'password': password
    
)

【讨论】:

嗨,卡尔,感谢您的宝贵时间,我刚刚尝试使用 POST,但错误仍然相同 @johan855 你能不能看看你的浏览器开发者控制台中的网络选项卡(Chrome 和 Firefox 都有这个),完成登录过程,看看有什么信息被发送到服务器和如何。是 POST 还是 GET,是格式编码还是 JSON 编码,或者其他什么,参数及其值是什么(可能有一些隐藏字段)等。这应该提供使用脚本登录所需的所有信息。 嗨卡尔,我将结果添加到问题中,但恐怕这不包含我以前不知道的任何内容,请求是 GET 并且响应是 JSON 编码的,没有额外的提示或我导航到 url 后的表单 @johan855 我不知道urllib2 代码是否会维护服务器发回的cookie。根据您的 Chrome 输出,肯定会返回一些与登录相关的重要 cookie。你可以试着检查一下。如果您愿意转到requests,我可以尝试提供更多帮助,因为它在维护请求状态(包括 cookie)方面要好得多。 是的,我绝对同意转移到请求上,我只使用了 urllib2,因为这是他们的 API 示例所暗示的。我还尝试过的一件事是发送请求标题: User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36 但没有运气... 【参考方案2】:

从官方网站确认@Carl:

此命令只查看 POST 参数并丢弃 GET 参数。

https://www.buxfer.com/help/api#login

【讨论】:

以上是关于从服务器而不是浏览器访问 API 时出现 403 错误的主要内容,如果未能解决你的问题,请参考以下文章

AWS websocket服务器:从浏览器连接时出现403错误,从Python很好

在局域网中的其他计算机上使用 Web API 时出现 403 禁止访问被拒绝错误

为啥从浏览器上传到 S3 时出现 403 错误?

Google Directory API:使用服务帐户检索用户信息时出现 403

403 请求在容器内访问 GCP 上的 Secret 时出现身份验证不足问题

如何解决安装IIS时出现HTTP错误403禁止访问?