简体   繁体   English

Windows 身份验证在本地 IIS 7.5 上不起作用。 错误 401.1

[英]Windows Authentication not working on local IIS 7.5. Error 401.1

I recently had a nasty issue getting Windows Authentication to work on a local instance of IIS 7.5 (Windows 7 Pro) to an ASP.net 4.0 site.我最近遇到了一个令人讨厌的问题,让 Windows 身份验证在 IIS 7.5 (Windows 7 Pro) 的本地实例上运行到 ASP.net 4.0 站点。 I followed the basic steps.我遵循了基本步骤。

IIS Authentication IIS 身份验证

  • Disable Anonymous Authentication禁用匿名身份验证
  • Enable Windows Authentication启用 Windows 身份验证

Edit web.config编辑 web.config

<authentication mode="Windows" />

This did a nice job of enabling Windows Authentication but every attempt to login was rejected and ultimately returned a 401.1 error.这在启用 Windows 身份验证方面做得很好,但每次登录尝试都被拒绝并最终返回 401.1 错误。 This is where the problem started.这就是问题开始的地方。 There appear to be many reasons for this that are well documented around the web including here on Stack Overflow.这似乎有很多原因,这些原因在网络上都有很好的记录,包括在 Stack Overflow 上。

I'd tried:我试过:

  • Editing IIS Authentication 'Advanced settings' for Windows Authentication to disable Extended Protection and Kernel-mode authentication编辑 Windows 身份验证的 IIS 身份验证“高级设置”以禁用扩展保护和内核模式身份验证
  • Editing IIS Authentication 'Providers' to move NTLM above Negotiate.编辑 IIS 身份验证“提供程序”以将 NTLM 移至协商之上。
  • Editing IIS .NET Authorization Rules to explicity Allow users (and various other combinations).编辑 IIS .NET 授权规则以明确允许用户(和各种其他组合)。
  • Various IIS command line scripts and tweaks.各种 IIS 命令行脚本和调整。
  • Various config tweaks in web.config file. web.config 文件中的各种配置调整。
  • Even some file system permissions tweaks.甚至一些文件系统权限调整。

But all to no avail, the dreaded 401.1 remained.但一切都无济于事,可怕的 401.1 仍然存在。

This really is a case of "can't see the wood for the trees".这真是一个“见树不见林”的案例。 None of the solutions I managed to find (call it a case of bad search parameters if you will) worked for me so I thought it worth posting this question to, hopefully, provide a clear answer that's easier to find for anyone suffering the same issue.我设法找到的所有解决方案(如果你愿意,可以称之为错误搜索参数的情况)对我有用,所以我认为值得发布这个问题,希望能提供一个明确的答案,让遇到同样问题的人更容易找到.

The issue here is that modern versions of Windows (Windows XP SP2, Windows Server 2003 SP1 and up) include a loopback check security feature that is designed to help prevent reflection attacks on your computer.这里的问题是,现代版本的 Windows(Windows XP SP2、Windows Server 2003 SP1 及更高版本)包含一个环回检查安全功能,旨在帮助防止对您的计算机进行反射攻击。 Therefore, authentication fails if the FQDN or the custom host header that you use does not match the local computer name.因此,如果您使用的 FQDN 或自定义主机标头与本地计算机名称不匹配,则身份验证将失败。

This can be resolved by either explicitly specifying host names or by disabling the loopback check.这可以通过明确指定主机名或禁用环回检查来解决。 Obviously the former being the more controlled approach.显然,前者是更受控制的方法。

  1. Set the DisableStrictNameChecking registry entry to 1. See: 281308 (Note: This should be unnecessary for Windows Server 2008/Vista and later)将 DisableStrictNameChecking 注册表项设置为 1。请参阅: 281308 (注意:对于 Windows Server 2008/Vista 及更高版本,这应该是不必要的)
  2. In Registry Editor, locate and then click the following registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0在注册表编辑器中,找到并单击以下注册表项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
  3. Right-click MSV1_0, point to New, and then click Multi-String Value.右键单击 MSV1_0,指向新建,然后单击多字符串值。
  4. Type BackConnectionHostNames, and then press ENTER.键入 BackConnectionHostNames,然后按 Enter。
  5. Right-click BackConnectionHostNames, and then click Modify.右键单击 BackConnectionHostNames,然后单击修改。
  6. In the Value data box, type the host name or the host names for the sites that are on the local computer, and then click OK.在数值数据框中,键入本地计算机上站点的主机名或主机名,然后单击确定。
  7. Quit Registry Editor, and then restart the IISAdmin service.退出注册表编辑器,然后重新启动 IISAdmin 服务。

Full details of how do to this can be found on MSDN: 896861有关如何执行此操作的完整详细信息,请参阅 MSDN: 896861

Hope this helps someone out.希望这可以帮助某人。 If you have any alternate suggestions or improvements please add.如果您有任何替代建议或改进,请添加。

I want to add Michael Dark's comment as an answer because I don't have permissions to modify my registry so Pete's answer doesn't work for me but I was able to solve the problem.我想添加 Michael Dark 的评论作为答案,因为我没有修改注册表的权限,所以 Pete 的答案对我不起作用,但我能够解决问题。

I solved it by adding a new Binding to my website with no specified host name and a different port (because localhost:80 is used for me).我通过向我的网站添加一个没有指定主机名和不同端口的新绑定来解决它(因为 localhost:80 用于我)。 As soon as I tried calling it from http://localhost:86/mypage , it worked.一旦我尝试从http://localhost:86/mypage调用它,它就起作用了。 After a quick check in the browser, I tested a few times with cURL and it correctly accepted and rejected my credentials.在浏览器中快速检查后,我用 cURL 测试了几次,它正确地接受并拒绝了我的凭据。

再次重新安装 IIS 功能并确保选中 WINDOWS auth 复选框状态。

Here's the PowerShell code that I use to deal with back connection host names and IIS.这是我用来处理反向连接主机名和 IIS 的 PowerShell 代码。 Note that with a little work, the commandlets can be saved out to a module and used that way.请注意,只需做一些工作,就可以将命令行开关保存到模块中并以这种方式使用。

Import-Module WebAdministration

function Add-BackConnectionHostname
{
    <#
    .SYNOPSIS
    Adds the back connection hostnames that will bypass the server loopback check.
    .DESCRIPTION
    Adds the hostname to the list of back connection hostnames that will bypass the server loopback check. Back connection host names  
    can be used to address the problem with IIS sites using Windows Authentication that is described in Microsoft KB896861.
    .EXAMPLE
    Add-BackConnectionHostname mywebsite.mydomain.tld
    .EXAMPLE
    Add-BackConnectionHostname mywebsite1.mydomain.tld, mywebsite2.mydomain.tld
    .PARAMETER Hostname
    The Hostname to add to the back connection hostnames list.
    .LINK
    Remove-BackConnectionHostname
    Get-BackConnectionHostname
    Enable-ServerLoopbackCheck
    Disable-ServerLoopbackCheck
    Get-ServerLoopbackCheck
    "You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version" (http://support.microsoft.com/en-us/kb/896861)
    #>
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        [Parameter(ValueFromPipeline = $true, Mandatory = $true)]
        [string] $Hostname
    )

    begin
    {
        $keyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0"
        $propertyName = "BackConnectionHostnames"
        $key = Get-Item $keyPath
        $property = $null
        $propertyValues = $null

        if ($key -ne $null)
        {
            $property = Get-ItemProperty $keyPath -Name $propertyName -ErrorAction SilentlyContinue

            if ($property -eq $null)
            {
                $property = New-ItemProperty $keyPath -Name $propertyName -Value $null -PropertyType ([Microsoft.Win32.RegistryValueKind]::MultiString) -ErrorAction Stop

                Write-Verbose "Created the $($propertyName) property."
            }

            if ($property -ne $null)
            {
                $propertyValues = $property.$propertyName
            }
        }
    }

    process
    {
        if ($property -ne $null)
        {
            foreach ($hostNameValue in $Hostname)
            {
                if ([string]::IsNullOrWhiteSpace($hostName) -eq $false -and $propertyValues -notcontains $hostNameValue)
                {
                    $propertyValues += $hostNameValue

                    Write-Verbose "Added $($hostName) to the back connection hostnames."
                }
                else
                {
                    Write-Verbose "Back connection host names already has an entry for $($hostName)."
                }
            }
        }
    }

    end
    {
        if ($propertyValues -ne $null)
        {
            $propertyValues = $propertyValues | ?{ [string]::IsNullOrWhiteSpace($_) -eq $false } | Sort -Unique
            Set-ItemProperty $keyPath -Name $propertyName -Value $propertyValues
        }
    }
}

function Remove-BackConnectionHostname
{
    <#
    .SYNOPSIS
    Removes the hostname from the list of back connection hostnames that will bypass the server loopback check.
    .DESCRIPTION
    Removes the hostname from the list of back connection hostnames that will bypass the server loopback check.
    .EXAMPLE
    Remove-BackConnectionHostname mywebsite.mydomain.tld
    .EXAMPLE
    Remove-BackConnectionHostname mywebsite1.mydomain.tld, mywebsite2.mydomain.tld
    .PARAMETER Hostname
    The Hostname to remove from the back connection hostnames list.
    .LINK
    Add-BackConnectionHostname
    Get-BackConnectionHostname
    Enable-ServerLoopbackCheck
    Disable-ServerLoopbackCheck
    Get-ServerLoopbackCheck
    "You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version" (http://support.microsoft.com/en-us/kb/896861)
    #>
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        [Parameter(ValueFromPipeline = $true, Mandatory = $true)]
        [string] $Hostname
    )

    begin
    {
        $keyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0"
        $propertyName = "BackConnectionHostnames"
        $key = Get-Item $keyPath
        $property = $null
        $propertyValues = $null

        if ($key -ne $null)
        {
            $property = Get-ItemProperty $keyPath -Name $propertyName -ErrorAction SilentlyContinue

            if ($property -ne $null)
            {
                $propertyValues = $property.$propertyName
            }
            else
            {
                Write-Verbose "The $($propertyName) property was not found."
            }
        }
    }

    process
    {
        if ($property -ne $null)
        {
            foreach ($hostNameValue in $Hostname)
            {
                if ($propertyValues -contains $hostNameValue)
                {
                    $propertyValues = $propertyValues | ? { $_ -ne $hostName }

                    Write-Verbose "Removed $($hostName) from the $($propertyName) property."
                }
                else
                {
                    Write-Verbose "No entry for $($hostName) was found in the $($propertyName) property."
                }
            }
        }
    }

    end
    {
        if ($property -ne $null)
        {
            $propertyValues = $propertyValues | ?{ [string]::IsNullOrWhiteSpace($_) -eq $false } | Sort -Unique

            if ($propertyValues.Length -ne 0)
            {
                Set-ItemProperty $keyPath -Name $propertyName -Value $propertyValues
            }
            else
            {
                Remove-ItemProperty $keyPath -Name $propertyName

                Write-Verbose "No entries remain after removing $($hostName). The $($propertyName) property was removed."
            }
        }
    }
}

function Get-BackConnectionHostname
{
    <#
    .SYNOPSIS
    Gets the list of back connection hostnames that will bypass the server loopback check.
    .DESCRIPTION
    Gets the back connection hostnames that will bypass the server loopback check. Back connection host names can be used to address 
    the problem with IIS sites using Windows Authentication that is described in Microsoft KB896861.
    .EXAMPLE
    Get-BackConnectionHostname
    .LINK
    Add-BackConnectionHostname
    Remove-BackConnectionHostname
    Enable-ServerLoopbackCheck
    Disable-ServerLoopbackCheck
    Get-ServerLoopbackCheck
    "You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version" (http://support.microsoft.com/en-us/kb/896861)
    #>
    [CmdletBinding(SupportsShouldProcess = $false)]
    param
    (
    )

    begin
    {
        $keyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0"
        $propertyName = "BackConnectionHostnames"
        $key = Get-Item $keyPath
        $property = $null

        if ($key -ne $null)
        {
            $property = Get-ItemProperty $keyPath -Name $propertyName -ErrorAction SilentlyContinue

            if ($property -eq $null)
            {
                Write-Verbose "The $($propertyName) property was not found."
            }
        }
    }

    process
    {
        $propertyValues = $null

        if ($property -ne $null)
        {
            $propertyValues = $property.$propertyName
        }

        return $propertyValues
    }

    end
    {
    }
}

function Enable-ServerLoopbackCheck
{
    <#
    .SYNOPSIS
    Enables the server loopback check. Enabled is the normal state for a Windows Server.
    .DESCRIPTION
    Enables the server loopback check. Having the loopback check enabled is the normal state for a Windows Server. Disabling the loopback check can be used to address 
    the problem with IIS sites using Windows Authentication that is described in Microsoft KB896861. It is NOT the preferred method. See the KB article for more details.
    .EXAMPLE
    Enable-ServerLoopbackCheck
    .LINK
    Add-BackConnectionHostname
    Remove-BackConnectionHostname
    Get-BackConnectionHostname
    Enable-ServerLoopbackCheck
    Get-ServerLoopbackCheck
    "You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version" (http://support.microsoft.com/en-us/kb/896861)
    #>
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
    )

    begin
    {
        $keyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
        $propertyName = "DisableLoopbackCheck"
        $key = Get-Item $keyPath
        $property = $null

        if ($key -ne $null)
        {
            $property = Get-ItemProperty $keyPath -Name $propertyName -ErrorAction SilentlyContinue

            if ($property -eq $null)
            {
                Write-Verbose "The $($propertyName) property was not found."
            }
        }
    }

    process
    {
        if ($property -ne $null)
        {
            Set-ItemProperty $keyPath -Name $propertyName -Value 0
        }
    }

    end
    {
    }
}

function Disable-ServerLoopbackCheck
{
    <#
    .SYNOPSIS
    Disables the server loopback check for all hostnames. Enabled is the normal state for a Windows Server.
    .DESCRIPTION
    Disables the server loopback check for all hostnames. Having the loopback check enabled is the normal state for a Windows Server. Disabling the loopback check can be used 
    to address the problem with IIS sites using Windows Authentication that is described in Microsoft KB896861. It is NOT the preferred method. See the KB article for more details.
    .EXAMPLE
    Disable-ServerLoopbackCheck
    .LINK
    Add-BackConnectionHostname
    Remove-BackConnectionHostname
    Get-BackConnectionHostname
    Enable-ServerLoopbackCheck
    Get-ServerLoopbackCheck
    "You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version" (http://support.microsoft.com/en-us/kb/896861)
    #>
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
    )

    begin
    {
        $keyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
        $propertyName = "DisableLoopbackCheck"
        $key = Get-Item $keyPath
        $property = $null

        if ($key -ne $null)
        {
            $property = Get-ItemProperty $keyPath -Name $propertyName -ErrorAction SilentlyContinue

            if ($property -eq $null)
            {
                Write-Verbose "The $($propertyName) property was not found."
            }
        }
    }

    process
    {
        if ($property -ne $null)
        {
            Set-ItemProperty $keyPath -Name $propertyName -Value 1
        }
        else
        {
            $property = New-ItemProperty $keyPath -Name $propertyName -PropertyType ([Microsoft.Win32.RegistryValueKind]::DWord) -Value 1
        }
    }

    end
    {
    }
}

function Get-ServerLoopbackCheck
{
    <#
    .SYNOPSIS
    Gets the status of the server loopback check. Enabled is the normal state for a Windows Server.
    .DESCRIPTION
    Gets the status of the server loopback check. Having the loopback check enabled is the normal state for a Windows Server. Disabling the loopback check can be used 
    to address the problem with IIS sites using Windows Authentication that is described in Microsoft KB896861. It is NOT the preferred method. See the KB article for 
    more details.
    .EXAMPLE
    Get-ServerLoopbackCheck
    .LINK
    Add-BackConnectionHostname
    Remove-BackConnectionHostname
    Get-BackConnectionHostname
    Enable-ServerLoopbackCheck
    Disable-ServerLoopbackCheck
    "You receive error 401.1 when you browse a Web site that uses Integrated Authentication and is hosted on IIS 5.1 or a later version" (http://support.microsoft.com/en-us/kb/896861)
    #>
    [CmdletBinding(SupportsShouldProcess = $false)]
    param
    (
    )

    begin
    {
        $keyPath = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
        $propertyName = "DisableLoopbackCheck"
        $key = Get-Item $keyPath
        $property = $null

        if ($key -ne $null)
        {
            $property = Get-ItemProperty $keyPath -Name $propertyName -ErrorAction SilentlyContinue
        }
    }

    process
    {
        $loopbackCheckStatus = "Enabled"

        if ($property -ne $null)
        {
            switch ($property)
            {
                0 { $loopbackCheckStatus = "Enabled" }
                1 { $loopbackCheckStatus = "Disabled" }
                default { $loopbackCheckStatus = "Unknown" }
            }
        }

        return $loopbackCheckStatus
    }

    end
    {
    }
}

function Get-WebsiteHostname
{
    <#
    .SYNOPSIS
    Gets the hostnames for the IP addresses bound to a web site.
    .DESCRIPTION
    Gets the hostnames for the IP addresses bound to a web site. Where a host header exists, the host header is used; otherwise, the IP address is looked up
    in DNS to see if a PTR record exists.
    .EXAMPLE
    Get-WebSiteHostname $webSite
    .EXAMPLE
    Get-WebSiteHostname -Name 'Default Web Site'
    .EXAMPLE
    Get-Website | Get-WebSiteHostname
    .LINK
    Get-Website 
    #>
    [CmdletBinding(SupportsShouldProcess = $false)]
    param
    (
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true)]
        [string] $Name
    )

    process
    {
        $siteHostnames = @()

        foreach ($webSiteName in $Name)
        {
            $bindings = Get-WebBinding -Name $Name

            foreach ($binding in $bindings)
            {
                $bindingInfo = $binding.bindingInformation.Split(':')
                $hostHeader = $bindingInfo[2]
                $bindingInfoAddress = $null
                $isValidIP = [System.Net.IPAddress]::TryParse($bindingInfo[0], [ref] $bindingInfoAddress)
                $siteHostname = $null

                if ($bindingInfo -eq '*')
                {
                    Write-Warning "The $($webSiteName) web site has a binding address set to All Unassigned."
                }
                elseif ([string]::IsNullOrWhiteSpace($hostHeader) -eq $false)
                {
                    $siteHostname = $hostHeader
                    Write-Verbose "The $($webSiteName) web site has a host header set to $($siteHostname)."
                }
                elseif ($isValidIP -eq $true)
                {
                    $siteHostname = (Resolve-DnsName $bindingInfoAddress -DnsOnly PTR -ErrorAction SilentlyContinue).NameHost

                    if ($siteHostname -ne $null)
                    {
                        Write-Verbose "The $($webSiteName) web site has an IP Address $($bindingInfoAddress) that resolves to $($siteHostname)."
                    }
                    else
                    {
                        Write-Warning "The $($webSiteName) web site has an IP Address $($bindingInfoAddress) with no PTR record."
                    }
                }
            }

            if ($siteHostname -ne $null)
            {
                $siteHostnames += $siteHostname
            }
        }

        return $siteHostnames | Sort -Unique
    }
}

Get-Website | ?{ (Get-WebConfiguration -Filter '/system.web/authentication' -PSPath $_.PSPath).mode -eq 'Windows' } | Get-WebsiteHostname | Add-BackConnectionHostname

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM