【问题标题】:Why is my web request failing authorization, but the same request works in python and postman?为什么我的 Web 请求授权失败,但相同的请求在 python 和 postman 中有效?
【发布时间】:2021-02-15 08:23:08
【问题描述】:

最近我的互联网遇到了一些问题。看起来在调制解调器上,或者在调制解调器之前(在我的 ISP 这边)。我想记录日志和连接指标。我快速测试了使用 python 和 postman 登录。现在我想换成 c#,因为这让我很舒服,但一切都不起作用。

在 python 和 postman 中,我必须发送两个请求才能使其工作。第一个通过身份验证,第二个有效。在 python 中,我不得不换成Session 而不是Request,因为两个连续的请求会失败。所以我认为它与饼干或其他东西有关?但是,邮递员显示没有存储任何 cookie。在使用 c# 时,我通常不会发出 Web 请求,所以这可能是一个简单(愚蠢)的问题。如何在 c# 中模拟此会话行为?

我调用Get() 两次,以反映python 和邮递员接受两个请求,但两个请求都失败了。下面是我的 c# 代码,下面是 python 代码。显然,这些是虚拟凭据。

public static class ModemMonitor
{
    public static string Get()
    {
        string result = "";

        Uri BaseUri = new Uri("http://192.168.100.1/");
        // I have tried all of the below auth strings and methods.
        // All give a 401 not authorized.
        string username = "admin";
        string password = "password";
        string auth = System.Convert.ToBase64String(Encoding.Default.GetBytes(username + ":" + password));
        string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));

        try
        {
            var request = HttpWebRequest.CreateHttp(BaseUri);
            request.Headers.Add("authorization", auth);
            request.PreAuthenticate = true;
            request.Method = WebRequestMethods.Http.Get;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            using(StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                result += reader.ReadToEnd();
            }
        }
        catch (WebException webEx) { result += webEx.Message; }
        catch (Exception ex) { result += ex.Message; }

        return result;
    }
}

工作 python 代码。

import requests
from requests import Session

session = requests.Session()
session.auth = ('admin', 'password')
baseUrl = 'http://192.168.100.1/'

auth = session.get(baseUrl)
response = session.get(baseUrl + 'eventLog.htm')
print(response.text)

【问题讨论】:

  • 我在 C# 中看到用户名 + ":" + 密码,在 python 中看到 ('admin', 'password')
  • 我已经尝试直接从邮递员那里复制粘贴编码的身份验证字符串。 Python 在内部添加了该冒号。它是在一个隐藏的构造函数中完成的。 requests.readthedocs.io/en/master/user/authentication/…
  • 试试request.Headers.Add("authorization", "Basic " + auth);
  • 我之前的评论不够清楚。我已经尝试过了。在它不起作用之后,我什至尝试将编码字符串的字符串文字代替您评论中的 auth 变量。

标签: python c# postman httpwebrequest


【解决方案1】:

你自己说过邮递员需要两个电话。 第一个创建令牌,第二个发出请求。

  1. 创建令牌
       public async Task<AuthenticateUser> Authenticate(string username, string password)
        {
            var data = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string,string>("grant_type","password"),
                new KeyValuePair<string,string>("username",username),
                new KeyValuePair<string,string>("password",password),
            });


            using (HttpResponseMessage response = await _ApiClient.PostAsync("/Token", data))
            {
                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsAsync<AuthenticateUser>();
                    return result;
                }
                else
                {
                    throw new Exception(response.ReasonPhrase);
                }
            }
        }

  1. 使用token调用api
   public async Task GetLoggedInUserInfo(string token)
        {
            _ApiClient.DefaultRequestHeaders.Clear();
            _ApiClient.DefaultRequestHeaders.Accept.Clear();
            _ApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            _ApiClient.DefaultRequestHeaders.Add("Authorization", $"Bearer { token}");

            using (HttpResponseMessage response = await _ApiClient.GetAsync("/api/user"))
            {
                if (response.IsSuccessStatusCode)
                {
                    var result = await response.Content.ReadAsAsync<LoggedInUserModel>();

                    
                   
                }
                else
                {
                    throw new Exception(response.ReasonPhrase);
                }
            }
        }

【讨论】:

  • 这真的没有意义。我得到了持有令牌的概念,但你怎么知道我的调制解调器会返回一个令牌?我可以告诉你它不会返回令牌。我已经检查了邮递员中的所有响应参数。另外,代码是什么?您是否只是从 API 客户端复制粘贴了一些令牌缓存代码?
  • 你试过这个 request.Headers.Add("basic", "admin password" );
猜你喜欢
  • 2021-03-24
  • 2017-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 2022-06-15
相关资源
最近更新 更多