当前位置: 首页 > 知识库问答 >
问题:

Python请求401未经授权

韶云瀚
2023-03-14

我正在尝试登录基于cloudflare服务器的网站。我使用cloudserver绕过了登录问题,但我的下一个停止点是当我试图发送get请求以访问一些登录后令牌时。

我的代码:

headers = {
          'authority': 'www.paf.es',
          'accept': 'application/json, text/plain, */*',
          'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36',
          'x-requested-with': 'XMLHttpRequest',
          'sec-fetch-site': 'same-origin',
          'sec-fetch-mode': 'cors',
          'sec-fetch-dest': 'empty',
          'referer': 'https://www.paf.es/my-paf',
          'accept-language': 'es-ES,es;q=0.9,en;q=0.8',
          'cookie': '__cfduid=d4247b3fce5d260d7c5257b5d65a572001592254859; com.paf.frontend.common.LocaleCookie=es_ES; _gcl_au=1.1.193127229.1592254863; _ga=GA1.2.484179826.1592254863; _gid=GA1.2.1016568931.1592254863; _fbp=fb.1.1592254863595.468566668; com.paf.frontend.cookiesAccepted=true; com.paf.frontend.common.device=desktop; __cf_bm=10366cb3cb936cf0d9188cdf37dfaf276961f164-1592257614-1800-AbXayDicXL3zBDecjcoUuzlv+Qb5YhjhhqZO6goD80+W/J7ahYM+mwNHdcav405NnNOcPxyErOcdvPzijcdXGhk=; BIGipServerprod01_pool=1067697930.22811.0000; _gat_UA-641842-15=1; com.paf.frontend.common.showMenu=account; _gali=loginButton; JSESSIONID=tuO580BlkBaMw5v3txOBy0v2hqQV-61ZBQCVRqdqcTEQN4-5Z6tuu0021151447412; com.paf.frontend.common.LoginTime=1592257626364; com.paf.frontend.common.LoggedIn=true; __cfruid=5fe9d18ceeda0612668c20982f65d634686cb526-1592227626; com.paf.frontend.common.LifeCycleCookie=HAS_LOGGED_IN; trackingParams={"_ga":{"value":"GA1.2.484179826.1592254863","expiration":1600033627916},"utm_nooverride":{"value":"1","expiration":1600033627916}}; com.paf.frontend.common.LocaleCookie=es_ES; JSESSIONID=m4650rp-X0aJYw_6b8-3ghQIOU-h1luYOQV4dAwZz6UGVc4RanvZ!151447412; com.paf.frontend.common.LoginTime=1592255494930; com.paf.frontend.common.LoggedIn=true; __cfruid=3ffb40834f313a4c2b4d351r24f9a946uu5f7db9-1592255495'
        }
cloudserver.get(url=url,headers=headers,data=json.dumps({}))

这返回401作为答案:

The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.46) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity MAY include relevant diagnostic information.

它的标题是

{'Date': 'Wed, 17 Jun 2020 23:56:04 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'CF-Ray': '5a50b4816fddd665-MAD', 'Set-Cookie': 'com.paf.frontend.common.LocaleCookie=es_ES; expires=Thu, 17-Jun-2021 23:56:04 GMT; path=/, com.paf.frontend.common.LoggedIn=; expires=Thu, 01-Jan-1970 01:00:00 GMT; path=/, __cf_bm=73f0a2b2216d419f8a19f3e8ff74e8eca2458229-1592438164-1800-AaPuIPRQVOJGvI9l1DBiMeXXmyczqpm7Owaf2XUHFqZ+FJ9PT44TdL4kxAU4FCOWDWQmztz9Ff1FTHrCcDQw88w=; path=/; expires=Thu, 18-Jun-20 00:26:04 GMT; domain=.paf.es; HttpOnly; Secure; SameSite=None', 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains; preload', 'CF-Cache-Status': 'DYNAMIC', 'cf-request-id': '03664f24e50000d66506af8200000001', 'Expect-CT': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'X-Content-Type-Options': 'nosniff', 'Vary': 'Accept-Encoding', 'Server': 'cloudflare', 'alt-svc': 'h3-27=":443"; ma=86400'}

好的,我首先试着给一个auth。这样地

s.get(url=url,headers=headers,data=json.dumps({}),auth=HTTPBasicAuth('somemail@mail.com','password'))

我再次得到相同的错误,401,但这次响应的头确实有一个www身份验证,我应该质询

{'Date': 'Wed, 17 Jun 2020 23:58:42 GMT', 'Content-Type': 'text/html; charset=UTF-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'CF-Ray': '5a50b85dd8fdd665-MAD', 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains; preload', 'WWW-Authenticate': 'Basic realm="weblogic"', 'CF-Cache-Status': 'DYNAMIC', 'cf-request-id': '0366518ea80000d66506a1b200000001', 'Expect-CT': 'max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"', 'X-Content-Type-Options': 'nosniff', 'Set-Cookie': '__cf_bm=c153a7277cf7abbaa004cdb46da821906f04b7c6-1592438322-1800-AR+KhjkQM5NHTTqKA0scqXrUGJpKNOnG0ZASOG386zEILi28YAh28BV+pWYGXzly+7ptsr9TJSGurY2nBOTv75I=; path=/; expires=Thu, 18-Jun-20 00:28:42 GMT; domain=.paf.es; HttpOnly; Secure; SameSite=None', 'Vary': 'Accept-Encoding', 'Server': 'cloudflare', 'alt-svc': 'h3-27=":443"; ma=86400'}

根据我所读到的内容,它是基本的意味着我必须在我的头文件中添加一个像这样的键“身份验证”:“Basic fhsejdjsjejdsj”是Basic之后的字符串,Base64编码的“用户名:密码”。

然而,在我的标头中添加了这个内容后,我再次发送了一个请求,但我仍然停留在同一个点上,使用相同的401。

我的问题是,在“WWW认证”中:“基本领域=“weblogic”'领域之后是什么重要吗?我如何克服这一点,并能够完成我的请求?

共有3个答案

易自珍
2023-03-14

我不能百分之百确定您在这里使用的是哪一个库,但假设库是基于请求的,我阅读这篇文章的方式是:

您试图向服务器发送请求,但服务器失败,出现401错误。这意味着您的请求缺少访问您试图访问的内容所需的凭据。

因此,您发送另一个带有用户名和密码的请求。

服务器回复了另一个401错误,这仍然意味着相同的事情:您的请求缺少访问您试图访问的内容所需的凭据。

给定服务器提供的响应标头:'WWW-Authenticate':'基本领域="weblogic"',您需要使用基本身份验证是正确的。

weblogic领域是服务器告诉您需要登录的区域。您的请求需要在该服务器上拥有该领域的有效用户名和密码。

再次假设您的库是基于请求的,您不需要自己做任何事情,这个调用:

s.get(url=url,headers=headers,data=json.dumps({}),auth=HTTPBasicAuth('somemail@mail.com','password'))

或此速记版本:

s.get(url=url,headers=headers,data=json.dumps({}),auth=('somemail@mail.com','password'))

将为您处理,但您需要有效的用户名和密码组合。

壤驷向明
2023-03-14

好的,我试过的一些方法似乎部分有效。简单回顾一下,我尝试了一切:

添加授权:基本

添加授权:持有人

在请求中使用auth=HTTPBasicAuth(用户名、密码)

在请求中使用auth=HTTPDigestAuth(用户名、密码)

似乎什么都不管用。作为提醒,我使用cloudscraper而不是常规请求,因为服务器在cloudflare中,否则返回403。

所以,真正起作用的是重用登录尝试中使用的标头。所以代替这个

s=cloudscraper.create_scraper()
s.post(url=url,headers=headers,data=payload) #Being url the XHR for the login, headers the ones from postman, and  data a string with my actual username and password
s.get(url=url,headers=headers) #New url requests and new headers from postman

是我干的

s=cloudscraper.create_scraper()
s.post(url=url,headers=headers,data=payload)
s.get(url=url) #no headers here, just a reuse from the ones in the previous request

这不是完美的,因为有时它工作,有时它不工作,无缘无故地以完全相同的顺序发布完全相同的参数。但是,这是一个进步

卢磊
2023-03-14

为了防止HTTP身份验证在这里不清楚,我将解释它是如何工作的。

>

  • 您以通常的方式请求HTTP资源,其中包含您认为需要的所有标头

    如果内容或区域(即领域)受密码保护,则服务器返回401错误。响应包含WWW Authenticate标头,它告诉您在响应服务器时必须使用哪种身份验证方法以及它应用于哪个领域。

    如果收到401,则向服务器重复请求,但将授权标头添加到请求中。其内容根据所使用的方法而变化,即服务器在第一次响应中请求的方法。对于基本身份验证方法,您的授权应该将单词basic作为第一个“参数”,然后使用冒号“:”分隔用户名和密码,但此字符串必须是Base64编码的。您可以执行以下操作:

    头文件[“Authorization”]=“Basic”((%s:%s”%s%(用户名、密码))。编码(“base64”)

    这是为了支持浏览器和GUI对话框而设计的。当浏览器收到401时,它会弹出一个对话框,询问您的用户名和密码。当您单击确定时,它会重复添加授权标头的请求。从这一点开始,浏览器始终发送授权标头以继续登录,直到收到另一个领域的另一个401。使用Realm是为了让浏览器可以根据领域服务器正在请求的会话自动更改凭据,而不会在每次请求相同的领域时提示您再次输入它们。这是因为您可能有不同的文件区域受到不同的密码保护,或者同一服务器上的多个帐户等等。

    现在,出于安全和标准化的原因,服务器可能总是拒绝第一个请求,无论它是否已经收到授权标头。事实上,如果您在未请求WWW身份验证之前发送授权,它可能会将其视为安全漏洞。一些服务器会发送一次,并期望从这时起授权存在,并且只有在客户端的进一步请求中消失时才重复401。其他将始终发送401,然后期望重复请求。有些还会完全切断您的访问权限,如果您发送不正确的凭据,例如连续3次,您将收到403禁止。此外,如果服务器使用的是基本身份验证,这通常意味着服务器使用的是HTTPS,而不是HTTP。由于发送的数据很容易在HTTP链接上拦截和读取,如果使用HTTP,将要求其他一些加密的方法来保护安全性。因此,如果您通过HTTP而不是HTTPS发送带有基本方法的授权标头,服务器也可能会拒绝您。

    我上面描述的服务器的特性(HTTP标准身份验证过程)是您有时进入并有时再次收到401的原因。处理这种情况的方法是,除非先收到401,否则永远不要发送授权标头。使用urllib处理这个问题很容易,因为会为401未经授权的应用程序引发HTTPError()。所以你只需要:

    def get (*args, **kwargs):
        user = kwargs.pop("user", "")
        pwd  = kwargs.pop("pwd", "")
        r = Request(*args, **kwargs) # A request with URL and headers and data
        try:
            u = urlopen(r)
        except HTTPError as e:
            if e.code==401 and "WWW-Authenticate" in e.headers:
                if not e.headers.get("WWW-Authenticate").lower().startswith("basic "):
                    raise
                r.add_header("Authorization", "Basic "+(user+":"+pwd).encode("base64"))
                u = urlopen(r)
            else:
                raise
        c = u.read()
        u.close()
        return c
    

    您需要查看服务器是每次发送401还是只发送一次。在使用请求时,必须使用responses属性检查响应代码,而不使用try-except块。或者切换到stdlib-urllib/urllib2。这就是我要做的,因为看起来你无论如何都不会使用来自请求(如会话)的功能,而是每次手动发送cookie。

    这里真正的问题是JSON需要什么身份验证,HTTP头需要什么身份验证。两者都需要,或者只需要其中一个。你只需要做实验。在我看来,API执行HTTP身份验证,即使您仅通过数据发送凭据。但是

  •  类似资料:
    • 我有一个在Azure网站上运行的标准Web API,启用了Azure AD身份验证,当在浏览器中浏览API时,我可以通过浏览器登录并获得对API的访问权。 但是,WPF桌面应用程序在提交请求时接收到未经授权的响应: 更新: 我已经在一个Azure帐户中重新创建了这个环境,我可以访问这个帐户,但仍然收到一个未经授权的响应(在浏览器中运行良好)。

    • 所以,我试图用Tweepy喜欢一个推文,但是这个错误正在发生: 有什么想法吗?

    • 我已经为此挠头两天了。我使用WebAPI版本2.2和我使用CORS。这个设置工作在服务器端,我被允许从我的web客户端服务器代码获得授权的内容,但在我的ajax调用中获得未经授权的内容。 以下是我的配置: Web API配置 WebApiConfig: Startup.Auth.cs: (我已经尝试了app.UseCors(CorsOptions.AllowAll)和config.EnableCo

    • 请看下面生成的guzzle请求数据。 我在这里做错了什么?请分享你的想法。谢谢你。

    • 我的代码:GoogleCredential凭据 credential.refreshToken() 错误日志: 创建服务号的步骤: 我在凭据中的oauth 2.0中创建了一个Web应用程序 然后我用客户端ID创建了一个服务号 现在我正在使用这个服务号和从它生成的p12证书来验证和创建Google凭据的对象 一旦刷新令牌,我就给了我401例外。 在这种情况下,任何帮助都会受到感激

    • 我想使用爪哇谷歌驱动器API。我尝试了这段代码: 但是我得到了这个错误: 我使用以下配置: 你能告诉我怎么解决这个问题吗?