【问题标题】:OWIN: IIS throws Access denied for authenticated user while accessing child applicationOWIN:IIS 在访问子应用程序时为经过身份验证的用户抛出访问被拒绝
【发布时间】:2016-02-24 20:31:44
【问题描述】:

背景
我有使用 OWIN + Azure AD 进行身份验证的 Web 表单应用程序。该应用程序托管在 IIS 10.0.10586.0 中。该应用程序作为 www.mydomain.com 托管在根目录(默认网站)。我还有子 .net 应用程序(不是虚拟目录),其中包含一些静态页面和一些 .Net 代码。因此经过身份验证的用户可以访问静态页面 www.mydomain.com/pages/page1.html

我遵循的步骤:
1> 创建 Web 表单应用程序并使用 OWIN 植入 Azure AD 身份验证,如 herehere
2> IIS 10 下的托管应用程序作为根应用程序(默认网站)
3> 此时一切正常,用户被重定向到 Microsoft 的登录页面,在那里进行身份验证,然后在成功身份验证后重定向回 mydomain.com
4> 我看到 System.Web.HttpContext.Current.Request.IsAuthenticated 是“真”
5> 我有一些静态页面,我希望只有经过身份验证的用户才能访问。所以我在默认网站下创建了一个新的应用程序,并相应地设置了物理路径。
6> 我还在 web.config 中添加了授权和 runAllManagedModulesForAllRequests(见下文)
7> 当经过身份验证的用户尝试访问页面 www.mydomain.com/pages/page1.html 他得到访问被拒绝错误

注意如果我创建子虚拟目录它可以工作。但我想要应用程序而不是虚拟目录)

访问被拒绝
错误消息 401.2.:未经授权:登录失败,原因是 服务器配置。验证您是否有权查看此内容 目录或页面基于您提供的凭据和 Web 服务器上启用的身份验证方法。联系网络 服务器管理员寻求更多帮助。

下面是 IIS 和应用程序池的快照(我也尝试将身份设置为 LocalSystem)“页面”是经过身份验证的用户无法访问的子应用程序。

OWIN 启动类

   [assembly: OwinStartup(typeof(AzureWithSL.Web.Startup))]
   namespace AzureWithSL.Web
   {
     public partial class Startup
     {
      private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
      private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
      private static string tenant = ConfigurationManager.AppSettings["ida:Tenant"];
      private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
      string authority = String.Format(CultureInfo.InvariantCulture, aadInstance, tenant);

     public void Configuration(IAppBuilder app)
     {
        ConfigureAuth(app);
     }       

     public void ConfigureAuth(IAppBuilder app)
     {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        app.UseOpenIdConnectAuthentication(
            new OpenIdConnectAuthenticationOptions
            {                   
                ClientId = clientId,
                Authority = authority,
                PostLogoutRedirectUri = postLogoutRedirectUri,
                Notifications = new OpenIdConnectAuthenticationNotifications
                {
                    AuthenticationFailed = context =>
                    {
                        context.HandleResponse();
                        context.Response.Redirect("/Error?message=" + context.Exception.Message);
                        return Task.FromResult(0);
                    }
                }
            });
     }
   }   
 }

应用程序启动页面

public class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        SignIn();
    }

    public void SignIn()
    {
        // Send an OpenID Connect sign-in request.
        if (!System.Web.HttpContext.Current.Request.IsAuthenticated)
        {
            HttpContext.Current.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, OpenIdConnectAuthenticationDefaults.AuthenticationType);
        }
    }
}

Web.Config

<configuration>
     <appSettings>
      <add key="webpages:Version" value="3.0.0.0" />
      <add key="webpages:Enabled" value="false" />
      <add key="ClientValidationEnabled" value="true" />
      <add key="UnobtrusiveJavaScriptEnabled" value="true" />
      <add key="owin:AutomaticAppStartup" value="true" />
      <add key="ida:ClientId" value="someid" />
      <add key="ida:Tenant" value="mytenant.onmicrosoft.com" />
      <add key="ida:AADInstance" value="https://login.microsoftonline.com/{0}" />
    <add key="ida:PostLogoutRedirectUri" value="http://localhost/Default.aspx" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.1" />
    <httpRuntime targetFramework="4.5.1" />     
    <authorization>
      <deny users="?" />      
    </authorization>
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />   
  </system.webServer>
  <location path="Default.aspx">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location> 
</configuration>

EDIT1
因此,无论我在子应用程序中是否有代码或静态页面,经过身份验证的用户都无法访问子应用程序。 我认为这是 OWIN 或 IIS 中的错误,有人可以确认一下吗?

EDIT2
所以在挖掘了几个小时后,我有点接近解决方案。

1> 我正在使用带有 OpenID Connect 的 Azure AD 进行单点登录身份验证。身份验证机制创建 cookie。为了使身份验证 cookie 跨越应用程序边界(即使第二个应用程序是 IIS 中的子应用程序),我们仍然需要使用相同的机器密钥来解密 cookie。在我的情况下,我的第二个应用程序设置为子应用程序(参见上面的 IIS 屏幕截图),所以我只需将机器密钥添加到根应用程序中。 (在旧的 FormsAuthentication 中,我们必须做同样的事情)

2> 最重要的是子应用程序需要是 .Net 4.5 或更高版本,并配置了 OWIN 和身份框架。它不能只是包含一些静态文件的文件夹。它必须是正确的 .Net Web 应用程序(我讨厌这个,因为我有几个子应用程序是使用 .Net 4 开发的 WCF 服务。所以现在我必须将所有这些应用程序转换为 4.5 并配置 OWIN & 身份框架和测试。真的吗???)
使用旧的 FormsAuthentication 我们不必这样做。 Authorization 元素能够保护子应用程序并在用户通过身份验证时允许访问,无论子应用程序是否包含 .net 应用程序、wcf 服务、静态 html 文件或图像。

【问题讨论】:

    标签: asp.net iis authorization owin azure-active-directory


    【解决方案1】:

    所以上面的 EDIT2 是我的答案
    您必须在主应用程序的 web.config 中有机器密钥。 (所有子应用都会继承它)

    并且所有子应用程序都必须为 OWIN 配置(与主应用程序相同。它们必须匹配 clientid、tenant 等)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-15
      • 2014-07-14
      • 2017-11-28
      • 2019-12-12
      • 2018-08-18
      • 2016-01-15
      • 2018-01-06
      • 1970-01-01
      相关资源
      最近更新 更多