使用本地访问的匿名身份验证保护遗留 Web 服务站点

Securing Legacy Web-Service site using anonymous authentication for local access

我有一个遗留的 WebForms 应用程序使用驻留在同一个 IIS[ 上的 (ASP.net) Web 服务(使用匿名访问) =24=] 服务器(同一个域,不同的应用程序每个都有自己的专用应用程序池)。此应用程序托管在受保护的 VPN 中,但现在有人请求公开托管它

在不进行大量重新编码(在应用程序级别)的情况下保护 Web 服务站点的权宜之计(但安全)的方法是什么。我已尝试在 IIS 中配置 Web 服务站点,以便它仅启用运行 Web 应用程序应用程序池的 服务帐户(标识)但是来自应用程序的当前请求模式始终使用匿名访问。我需要限制访问以仅允许此特定的 Web 应用程序。我正在考虑 ISAPI 过滤器,但不推荐用于 IIS 7+ ?

ADDENDUM: I would love to find an IIS based solution. Currently I am trying to restrict access based to just the Web Application source. Problem is (as stated) is those request are all "Anonymous" if I could make those requests use "Network Service" or some other local Identity then I would be set.

我建议您使用 IdentityServer 和 OpenIdConnect 来做到这一点。

IdentityServer is a .NET/Katana-based framework and hostable component that allows implementing single sign-on and access control for modern web applications and APIs using protocols like OpenID Connect and OAuth2. It supports a wide range of clients like mobile, web, SPAs and desktop applications and is extensible to allow integration in new and existing architectures.

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner. https://connect2id.com/learn/openid-connect

使用它,您可以要求身份服务器为您提供访问令牌和 ID 令牌。

An identity token represents the outcome of an authentication process. It contains at a bare minimum an identifier for the user (called the sub aka subject claim). It can contain additional information about the user and details on how the user authenticated at the OP.

An access token allows access to a resource. Clients request access tokens and forward them to an API. Access tokens contain information about the client and the user (if present). APIs use that information to authorize access to their data.

对于您的情况,例如,您可以在 Webforms 应用程序和 WebService 之间实现客户端凭据流。 (在此流程中,您不会向 WebForms 应用程序的用户提出任何要求)。因此,想法是 WebForms 应用程序将要求身份服务器为其提供访问令牌以访问 Web 服务资源。在 WebService 中,您必须根据需要(范围、声明等)实现授权。请阅读 LeastPrivilege 博客 (Dominick Baier),他和他的好友 Brock Allen 是这些主题的大师。由于我在 Whosebug 中不能 post 超过 1 link 这真的很糟糕,你必须 google 它们或 google 任何其他信息。

如果需要用户身份验证,可以使用隐式、代码或混合流程。但这取决于你真正想做什么。

我认为您可能需要编写一些代码,但不会太多。您可以找出一种在到达任何端点之前请求授权的方法。

我希望我说的很清楚。如果没有,请问我更多的解释。

经过更多研究,我确定了一个 http Module 解决方案,因为它具有以下优点:

• 最少编码

• 无需修改现有代码库

• 易于部署

• 遵循(本地访问)

的现有 ASP.Net 安全模型

模块(VS:DLL 项目)

using System;
using System.Web;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FilterModule
{
    class AuthorizeLocal : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            app.BeginRequest += new EventHandler(OnBeginRequest);
        }


        private void OnBeginRequest(Object s, EventArgs e)
        {
            HttpApplication app = s as HttpApplication;
            HttpRequest req = app.Request;
            HttpContext context = app.Context;

            if (!req.IsLocal)    // Is the request from a Local Source?
            {
                context.Response.Close(); // close the response: ends request
            }

            /* Optional Test Code - to view locally create an html page TestModule.html in target site */
            string Identity = Thread.CurrentPrincipal.Identity.Name;
            string filePath = context.Request.FilePath;
            string fileExtension = VirtualPathUtility.GetExtension(filePath);
            string fileName = VirtualPathUtility.GetFileName(filePath);

            if (fileName.ToLower().Equals("testmodule.html"))
            {
                try
                {
                    app.Context.Response.Write("app: " + app.ToString());
                    context.Response.Write("<br/>server: " + app.Server.ToString());
                    context.Response.Write("<br/>Thread.CurrentPrincipal.Identity.Name: " + Thread.CurrentPrincipal.Identity.Name);
                    context.Response.Write("<br/>HttpRequest: " + req.Url.ToString());
                    context.Response.Write("<br/>req.UserHostName: " + req.UserHostName);
                    context.Response.Write("<br/>req.UserHostAddress: " + req.UserHostAddress);
                    context.Response.Write("<br/>filePath: " + filePath);
                    context.Response.Write("<br/>fileName: " + fileName);
                    context.Response.Write("<br/>fileExtension: " + fileExtension);
                    context.Response.Write("<br/>req.IsLocal: " + req.IsLocal.ToString());
                    context.Response.Write("<br/>req.LogonUserIdentity: " + req.LogonUserIdentity);
                    context.Response.Write("<br/>req.UserHostName : " + req.UserHostName);
                    context.Response.Write("<br/>req.AnonymousID " + req.AnonymousID);
                    context.Response.Write("<br/>req.IsAuthenticated : " + req.IsAuthenticated);
                }
                catch (Exception Ex)
                {
                    context.Response.Write("<br/> " + Ex.ToString());
                }
            }

            //if (_eventHandler != null)
            //    _eventHandler(this, null);
        }

        public void Dispose()
        {

        }

    }
}

实施

  1. 将已编译的 DLL (FilterModule.dll) 添加到 Web 服务(站点)bin 目录。

  2. 将以下内容添加到 Web 服务(或站点)配置文件中的模块定义 (web.config)

<system.webServer> 部分下的 <modules>
添加以下内容:

<add name ="FilterModule" type="FilterModule.AuthorizeLocal" />