本文介绍了关闭ASP.Net WebForms的验证一个子目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须同时包含WebForms和MVC页面的大型企业应用程序。它现有的认证和授权的设置,我不希望改变。

I have a large enterprise application containing both WebForms and MVC pages. It has existing authentication and authorisation settings that I don't want to change.

该认证的WebForms在web.config配置:

The WebForms authentication is configured in the web.config:

 <authentication mode="Forms">
  <forms blah... blah... blah />
 </authentication>

 <authorization>
  <deny users="?" />
 </authorization>

相当标准为止。我有一个REST服务,是这个大应用程序的一部分,我想使用HTTP认证,而不是为这一个服务。

Fairly standard so far. I have a REST service that is part of this big application and I want to use HTTP authentication instead for this one service.

所以,当用户试图从它返回一个HTTP 401状态和 WWW验证头REST服务获取JSON数据。如果他们有一个正确的HTTP 授权响应应对它可以让他们进来。

So, when a user attempts to get JSON data from the REST service it returns an HTTP 401 status and a WWW-Authenticate header. If they respond with a correctly formed HTTP Authorization response it lets them in.

问题是,WebForms的覆盖这个处于较低的水平 - 如果返回401(未经授权),它覆盖了一个302(重定向到登录页面)。这是在浏览器不错,但没用REST服务。

The problem is that WebForms overrides this at a low level - if you return 401 (Unauthorised) it overrides that with a 302 (redirection to login page). That's fine in the browser but useless for a REST service.

我要关掉身份验证设置在web.config中,覆盖休息文件夹:

I want to turn off the authentication setting in the web.config, overriding the 'rest' folder:

 <location path="rest">
  <system.web>
   <authentication mode="None" />
   <authorization><allow users="?" /></authorization>
  </system.web>
 </location>

授权的位工作正常,但的验证的行(&LT;身份验证模式=无/&GT; )会导致异常:

The authorisation bit works fine, but the authentication line (<authentication mode="None" />) causes an exception:

这是使用注册为allowDefinition =应用程序级别之外'MachineToApplication'的节是错误的。

我在应用层面,虽然这个配置 - 它在根web.config - 这错误是在子目录web.configs

I'm configuring this at application level though - it's in the root web.config - and that error is for web.configs in sub-directories.

我如何重写的验证的让所有的网站的其余部分使用WebForms的认证,这个目录使用无?

How do I override the authentication so that all of the rest of the site uses WebForms authentication and this one directory uses none?

这是类似于另一个问题: JSON请求,但我中号不找相同的解决方案 - 我不想只是删除的WebForms认证和全球新增的自定义code,有远得多的风险和工作有关。我想改变只是配置中的一个目录。

This is similar to another question: 401 response code for json requests with ASP.NET MVC, but I'm not looking for the same solution - I don't want to just remove the WebForms authentication and add new custom code globally, there's far to much risk and work involved. I want to change just the one directory in configuration.

更新

我想建立一个Web应用程序并在这我想所有的页面的WebForms和MVC的意见使用的WebForms认证。我想一个目录使用基本的HTTP验证。

I want to set up a single web application and in that I want all the WebForms pages and MVC views to use WebForms authentication. I want one directory to use basic HTTP authentication.

请注意,我说的认证,而不是授权。我想REST调用来与用户名和放大器;密码HTTP头,和我想的WebForm&安培; MVC的网页来与.NET中的身份验证Cookie - 在这两种情况下授权对我们所做的DB

Note that I'm talking about authentication, not authorisation. I want REST calls to come with the username & password in an HTTP header, and I want WebForm & MVC pages to come with the authentication cookie from .Net - in either case authorisation is done against our DB.

我不希望重写的WebForms认证和推出自己的饼干 - 似乎荒谬的是一个HTTP授权REST服务添加到应用程序的唯一途径。

I don't want to rewrite WebForms authentication and roll my own cookies - it seems ridiculous that is the only way to add an HTTP authorised REST service to an application.

我不能添加额外的应用程序或虚拟目录 - 它一定是作为一件申请

I can't add an additional application or virtual directory - it's got to be as one application.

推荐答案

我解决这个杂乱的工作方式 - 通过在Global.asax欺骗Forms身份验证现有的全部网页

I've worked around this the messy way - by spoofing the Forms authentication in the global.asax for all the existing pages.

我还是不太有这种完全正常的,但它是这样的:

I still don't quite have this fully working, but it goes something like this:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    // lots of existing web.config controls for which webforms folders can be accessed
    // read the config and skip checks for pages that authorise anon users by having
    // <allow users="?" /> as the top rule.

    // check local config
    var localAuthSection = ConfigurationManager.GetSection("system.web/authorization") as AuthorizationSection;

    // this assumes that the first rule will be <allow users="?" />
    var localRule = localAuthSection.Rules[0];
    if (localRule.Action == AuthorizationRuleAction.Allow &&
        localRule.Users.Contains("?"))
    {
        // then skip the rest
        return;
    }

    // get the web.config and check locations
    var conf = WebConfigurationManager.OpenWebConfiguration("~");
    foreach (ConfigurationLocation loc in conf.Locations)
    {
        // find whether we're in a location with overridden config
        if (this.Request.Path.StartsWith(loc.Path, StringComparison.OrdinalIgnoreCase) ||
            this.Request.Path.TrimStart('/').StartsWith(loc.Path, StringComparison.OrdinalIgnoreCase))
        {
            // get the location's config
            var locConf = loc.OpenConfiguration();
            var authSection = locConf.GetSection("system.web/authorization") as AuthorizationSection;
            if (authSection != null)
            {
                // this assumes that the first rule will be <allow users="?" />
                var rule = authSection.Rules[0];
                if (rule.Action == AuthorizationRuleAction.Allow &&
                    rule.Users.Contains("?"))
                {
                    // then skip the rest
                    return;
                }
            }
        }
    }

    var cookie = this.Request.Cookies[FormsAuthentication.FormsCookieName];
    if (cookie == null ||
        string.IsNullOrEmpty(cookie.Value))
    {
        // no or blank cookie
        FormsAuthentication.RedirectToLoginPage();
    }

    // decrypt the 
    var ticket = FormsAuthentication.Decrypt(cookie.Value);
    if (ticket == null ||
        ticket.Expired)
    {
        // invalid cookie
        FormsAuthentication.RedirectToLoginPage();
    }

    // renew ticket if needed
    var newTicket = ticket;
    if (FormsAuthentication.SlidingExpiration)
    {
        newTicket = FormsAuthentication.RenewTicketIfOld(ticket);
    }

    // set the user so that .IsAuthenticated becomes true
    // then the existing checks for user should work
    HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(newTicket), newTicket.UserData.Split(','));

}

我不是很满意这个作为一个修复 - 这似乎是一个可怕的黑客攻击,并重新发明轮子,但它看起来这是对我的窗体身份验证的页面的唯一途径和HTTP验证的REST服务在相同的应用程序的工作。

I'm not really happy with this as a fix - it seems like a horrible hack and re-invention of the wheel, but it looks like this is the only way for my Forms-authenticated pages and HTTP-authenticated REST service to work in the same application.

这篇关于关闭ASP.Net WebForms的验证一个子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 11:02