问题描述
我必须同时包含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的验证一个子目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!