Invoke-Webrequest gets 401 on POST but not on GET with Basic Auth

﹥>﹥吖頭↗ 提交于 2021-02-08 07:35:48

问题


I have a dev site with Basic Auth enabled. I am get to GET a page using the following to add basic auth to the headers:

$creds = "$($BASIC_AUTH_USER):$($BASIC_AUTH_PASS)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"
$headers = @{
    Authorization = $basicAuthValue
}

$login = Invoke-WebRequest $url -SessionVariable session -UseBasicParsing -Headers $headers

But I am unable to post to the same URL:

$fields = @{ Email = $SITE_USER; Password = $SITE_PASS; }
$login = Invoke-WebRequest -Uri $url -Method POST -WebSession $session -Body $fields -UseBasicParsing -Headers $headers

I get a 401 Unauthorized back. Everything works fine if I disable basic auth on the site. So I know it isn't a server issue. I am able to POST using my browser.

Edit: So it seems basic auth is working correctly when I debug on the server. But my server returns a redirect, which is then causing Invoke-Webrequest to interpret that as a 401.

Any idea on why this may not be working?


回答1:


You get this behaviour because of the redirect; when making this additional request to the redirect location the authorization header doesn't get included.

For this reason PowerShell 6.0.0 added the PreserveAuthorizationOnRedirect parameter.

Indicates the cmdlet should preserve the Authorization header, when present, across redirections.
By default, the cmdlet strips the Authorization header before redirecting. Specifying this parameter disables this logic for cases where the header needs to be sent to the redirection location.

Invoke-WebRequest reference


As an alternative, if you are not on PowerShell 6, you can work around it via a more lowlevel script using System.Net.WebRequest wich defines a property AllowAutoRedirect that can be set to False in order to skip the redirect after a successful POST, avoiding the 401 error.

Notice that you have to take care of things like the data/body formatting (json, form-urlencoded, ...) and http-headers yourself.

The script will look like here below.
Notice the line with AllowAutoRedirect = $false.

$creds = "$($BASIC_AUTH_USER):$($BASIC_AUTH_PASS)"
$encodedCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($creds))
$basicAuthValue = "Basic $encodedCreds"

$url = "http://your.url"
$request = [System.Net.WebRequest]::CreateHttp($url);   
$request.Method = "post"
$request.Headers.Add("Authorization", $basicAuthValue)
$request.AllowAutoRedirect = $false

$body = "your formatted data goes here"
$bytes = [System.Text.Encoding]::UTF8.GetBytes($body);
$stream = $request.GetRequestStream()
$stream.Write($bytes, 0, $bytes.Length);
$stream.Close();

$request.GetResponse();


来源:https://stackoverflow.com/questions/52637039/invoke-webrequest-gets-401-on-post-but-not-on-get-with-basic-auth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!