what alternatives are there to using global.asax? - iis

I am using my own custom authentication with IIS, and I want the server on every page load (no matter what type of file) to first check the Application variable to see if the user is authenticated and authorized to see the site. In global.asax this could be:
void Application_Start(Object Sender, EventArgs e)
{
if(Application["username"] == null)
{
Response.redirect("login.aspx");
}
}
The problem is that this site has multiple sub-roots. That is, http://example.com/site1 is a completely different website from http://example.com/site2 . Therefore, I would like said Application_Start function to work on site1 but not affect site2.
If global.asax was customizable at directory level, then this wouldn't be a problem. But since there is only one global.asax per server I cannot implement this solution.
What alternatives are there to global.asax? or can global.asax be different somehow for each directory?

HttpModules are an alternative to global.asax
(see also https://www.codeguru.com/csharp/.net/net_asp/article.php/c19389/HTTP-Handlers-and-HTTP-Modules-in-ASPNET.htm
http://codebetter.com/blogs/karlseguin/archive/2006/06/12/146356.aspx )
HttpModules are registered in web.config; which, conveniently, is customizable at directory level. So every directory can have its own unique set of modules (that are inherited in lower directories). All modules have the same functionality as those found in global.asax .
Basically, every page request gets passed through every registered module before it ever gets to the actual page code itself. This happens regardless of what kind of request it is:
"page.aspx" "page.html"
| |
( | module 1 | )
( | module 2 | )
( | module 3 | )
V V
(handler 1) (handler 2)
((a much better picture and description can be found at https://www.codeguru.com/csharp/.net/net_asp/article.php/c19389/HTTP-Handlers-and-HTTP-Modules-in-ASPNET.htm ))
So then all you need to do is define your code as a module instead of in global.asax . If the user isn't authenticated, then: response.redirect("login.aspx") will stop control from ever reaching the handler and parsing/returning/running the requested page.
It's a little more complicated than that, so a better description/tutorial can be found at the codeguru website.

I'm pretty sure that your code is going to allow access to everybody once a single person logs in - probably not what you want.
According to http://msdn.microsoft.com/en-us/library/ms178473.aspx:
"Called when the first resource (such as a page) in an ASP.NET application is requested. The Application_Start method is called only one time during the life cycle of an application"
Furthermore according to http://support.microsoft.com/kb/307598#1
"Application state variables are, in effect, global variables for each ASP.NET application."
I would suggest you use the built in Membership API and restrict access using the web.config files.
If you are open to using the Membership API rather than rolling your own authentication mechanism, you can use the web.config to check if a user is authorized for a particular folder. You can also relatively simply have the user log in on one site and automatically be logged into the other sites by sharing authentication tickets -- provided they are all on the same root domain.
For sharing authentication tickets see:
http://msdn.microsoft.com/en-us/library/ms998288.aspx and http://www.netomatix.com/development/singlesignon.aspx
For how to use the web.config to restrict access:
http://www.devhood.com/Tutorials/tutorial_details.aspx?tutorial_id=85

Actually I believe there's just one global.asax per asp.net application. If you want example.com/subsite1 to be a different application from example.com/subsite2 you can create two different applications in IIS. As a result they'll run in entirely different application domains (although they may be in the same process (aspnet_wp.exe or w3wp.exe) and even share application pools). As such, if they're different applications they should also get to have independent global.asax files.
To turn a directory into an application. Open IIS->Find the directory/sub site, right click->Properties->Home Directory tab->Click "Create".
For more information on application domains and worker processes, consider reading this blog entry. Hope that helps.

Related

How to avoid running entire client-side process in Blazor WebAssembly before Azure AD authentication?

I'm building a Blazor WASM app with Azure AD, and I'm struggling with what appears to be an inefficiency in the way it's designed. The entire application, including the home page, needs to be secured by [Authorize]. It works (with one exception noted below), but the initial load is painfully slow. Basically, on reaching the home page, Blazor loads the entire application -- running Program.Main in it's entirety, loading JS files from CDN or webpack bundles, loading all the .NET dlls, and THEN decides that it needs to redirect to Azure to authenticate. Once it returns, it does all that again. Loading the various files is not too much of a problem, since it gets them from the browser cache the second time. The problem is that is also needs to run Program.Main again.
In my rather large client app, it takes a few seconds to configure all the services (I'm using a lot of gRPC). The biggest culprit though is a call to the server API to get certain app settings that I don't want to expose to the client (basically doing this). Moreover, that API call doesn't even succeed, since the API endpoint is secured, and the user hasn't authenticated yet, but I don't know how to get the user info from within Program.Main. The log messages show that the user identity is not even created until sometime after Program.Main completes. (One of the settings is the roles-to-permissions mapping, so I can't even draw the app's menu without it. I've resorted to removing the auth requirement from the API controller for now, obviously not a permanent fix)
To replicate the behavior, just create a brand new Blazor WebAssembly app, selecting Auth Type = Microsoft identity platform, and checking the ASP.NET Core hosted box. Then just edit both appsettings.json files to provide your Azure login info; change the requested scope in Client.Program.Main (and change the one in WeatherForecastController to match); and add [Authorize] to the _imports.razor file, and [AllowAnonymous] to Authentication.razor. Finally add some logging Console.WriteLine("Running in Client.Program.Main"); near the end of that method.
In the basic Blazor app template as described above, this all runs pretty fast. Once there's a significant amount of startup code in Program.Main, though, it becomes quite noticeable, it can be several seconds both before and after the login redirect. And I can't make an authenticated API call.
Specifying endpoints.MapFallbackToFile("index.html").RequireAuthorization(); in the server side Startup doesn't seem to make any difference. Neither does adding options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build(); to the AddAuthorization call.
So basically, I'm looking to:
Identify the user in Client.Program.Main, so I can make a secure call to the settings API
Identify the user in Client.Program.Main, so I can bypass all the time-consuming stuff myself on the first pass
Get Blazor (server?) to somehow recognize that a request for a protected page will fail for an unauthenticated user, and go directly to the Azure login page without all the usual ceremony
Any suggestions?

Progressive web app within the scope of another progressive web app

I wish to make a progressive web app for a domain www.xyz.com and another progressive web app for the domain www.xyz.com/abc. How should I go about it and what will be the behaviour of service workers in both the cases? Will there be 2 service worker registrations or a single one will work for both the PWAs? Also, should I make 2 manifest files for them?
You can have only one PWA for both URLs. When you create your service worker, its scope covers the current folders and the relative children.
If you place it at the root level, you can use one service worker for both URLs, without the need to make thinks more complex introducing nested constructions.
You can define different caching strategies within the same service worker with ease.
If you want to deepen the PWA topic, you can have a look at the articles I wrote about them, starting from basic concepts and then going deeper with more advanced themes.
Update
The scope property of the manifest file determines which HTTP calls can be intercepted by the Service Worker (SW).
If you have scope: '/', your SW will intercept all HTTP requests made by your app. If it would be /user, the SW couldn't intercept a request that doesn't fall within its scope (e.g. /orders/code.js), but it would intercept all GET calls under the user root, like /user/details.
In your case you can have therefore two SWs (even on the same page) where you can define different scopes to intercept, you have just to be careful in not overlapping the scopes among them.
If you plan to cache also static assets, keep it in mind that the scope for the SW is given by the folder where the SW file is stored and its subfolders.
About multiple manifest files, Jeff gave an answer about it on SO.

Modx - Multiple contexts on one domain

I've a Modx site running. Now i want to get some resources like modx-generated javascript files. It is possible to put these in the web context, but than it can be seen by all users.
So i created a new context named "Resources" (key: res), gave it Load-Only permissions and created a resource in it. I've also initialize it in the index.php file:
$modx->initialize('web');
$modx->initialize('res');
But when i try to access the resource, it doesn't work.
Did i missed something?
Calling modX::initialize() twice will not work as it checks for state.
Either remove the first call to initailise the web state or write a plugin and use modX::switchContext()

IIS worker threads issue

I have my site hosted on IIS hosting. Site has feature that needs calling WCF service and then return result. The issue is that site is processing calling to WCF service another web site calling is freezing and not return content fast (this is just static content). I setup two chrome instances with different imacros' scripts, which one is calling page that requests wcf service and another one page is just static content. So here I can just see that when first page that requests wcf services freezes, another one page also freezes and when first is released the second is too.
Do I need reconfigure something in my Web.Config or do should I do something else to get possible to get static content immediately.
I think that there are two seperate problems here:
Why does the page that uses the WCF service freeze
Why does the static content page freeze
On the page that calls the WCF service a common problem is that the WCF client is not closed. By default there are 10 WCF connections with a timeout of 1 min. The first 10 calls go fine (say they execute i 2 secs), then the 11th call comes, there are no free wcf connections it must therefore wait 58 secs for a connection to timeout and become available.
On why your static page freezes. It could be that your client only allows one connection to the site, the request for the static page is not sent untill the request for the page with the wcf services is complete.
You should check the IIS logs to see how must time IIS is reporting that the request is taking.
I would say that this is a threading issue. This MSDN KB article has some suggestions on how to tune your ASP.NET threading behavior:
http://support.microsoft.com/kb/821268
From article - ...you can tune the following parameters in your Machine.config file to best fit your situation:
maxWorkerThreads
minWorkerThreads
maxIoThreads
minFreeThreads
minLocalRequestFreeThreads
maxconnection
executionTimeout
To successfully resolve these problems, do the following:
Limit the number of ASP.NET requests that can execute at the same time to approximately 12 per CPU.
Permit Web service callbacks to freely use threads in the ThreadPool.
Select an appropriate value for the maxconnections parameter. Base your selection on the number of IP addresses and AppDomains that are used.
etc...
Consider such scenario: when you make a request to IIS your app changes, deletes or creates some file outside of App_Data folder. This often tends to be a log file which is mistakenly was put at bin folder of the app. The file system changes lead to AppDomain reloading by IIS as it thinks that app was changed, hence the experienced delay. This may or may not apply to your issue, but it is a common mistake in ASP.NET apps.
Well, maybe there is no problem...
It may be just the browser's same domain simultaneous requests limit.
Until the browser not finished the request to the first page (the WCF page), it won't send the request to the second page (the static).
Try this:
Use different browsers for each page (for example chrome/firefox).
Or open the second page in chrome in incognito window (Ctrl + Shift + N).
Or try to access each page from different computer.
You could try to use AppFabric and see what is wrong with your WCF services http://msdn.microsoft.com/en-us/windowsserver/ee695849

How is a web application started? Where is the entry point (if there's one)?

I am using IIS to develop some web applications. I used to believe that every application should have a entry point. But it seems a web application doesn't have one.
I have read many books and articles addressing how to build an ASP.NET application under IIS, but they are just not addressing the most obvious and basic thing that I want to know.
So could anyone tell me how is a web application started? What's the difference between a traditional desktop application and a web application in terms of their working paradigm, such as the starting and terminating logic.
Many thanks.
Update - 1 - 23:14 2011/1/4
My current understanding is:
When some request arrives, the URL contained in the request will be extracted by the IIS. I guess IIS must have maintained some kind of a internal table which maps a URL to corresponding physical directory on disk. Let's take the following URL as an example:
http://myhost/webapp/page1.aspx
With the help of the aforementioned internal table, IIS will locate the page1.aspx file on disk. And then this file is checked and the code-behind code file is located. And then proper page class instance will be contructed and its methods defined in the code-behind file will be invoked in a pre-defined order. The output of the series of method invoking will be the response sent to the client.
Update - 2 - 23:32 2011/1/4
The URL is nothing but an identifier that serves as an index into the aforementioned internal table. With this index, IIS (or any kind of web server technology) could find the physical location of the resource. Then with some hint (such as file extension name like *.aspx), the web server knows what handler (such as the asp.net ISAPI handler) should be used to process that resource. That chosen handler will know how to parse and execute the resource file.
So this also explains why a web server should be extensible.
It depends what language and framework you are using, but broadly there are a number of entry points that will be bound to HTTP requests (e.g. by URL). When the server receives a request that matches one of these bindings, the bound code is executed.
There may also be various filter chains and interceptors that are executed based on other conditions of the request. There will probably also be some set-up code that the server executes when it starts up. Ultimately, there is still a single entry-point - the main() function of the server - but from the web application's perspective it is the request bindings that matter.
Edit in response to question edits
I have never used IIS, but I would assume there is no "lookup table", but instead some lookup rules. I shall talk you through the invocation of a .jsp page on an Apache server, which should be basically the same process.
The webapp is written and placed in the file system - e.g. C:/www/mywebapp
The web server is given a configuration rule telling it that the URL path /webapp/ should be mapped to C:/www/mywebapp
The web server is also configured to recognise .jsp files as being JSP servlets
The web server receives a request for /webapp/page1.jsp, this is dispatched to a worker thread
The web server uses its mapping rules to locate C:/www/mywebapp/page1.jsp
The web server wraps the code in the JSP file in a class with method serveRequest(request, response) and compiles it (if not already done so)
The web server calls the serveRequest function, which is now the entry point of the user code
When the user code is finished, the web server sends the response to the client, and the worker thread terminates
This is the most basic system - resource-based servlets (i.e. .jsp or .aspx files). The binding rules become much more complicated when using technologies like MVC frameworks, but the essential concepts are the same.
Similar to what OrangeDog mentioned in his answer, there is plenty that goes on when serving these pages Before you even get to your code.
Not only in asp.net mvc, but in asp.net in general there are various pieces that come into play when you're executing a request.
There is code like modules, handlers, etc that again do processing Before it gets to the code of the page. Additionally you can map the same page to be able to process different urls.
The concept of handler in asp.net is important, as there are various handlers that are responsible of processing requests that match extensions and/or http verbs (get, head, post). If you take a look into %systemroot%\Microsoft.NET\Framework64\v4.0.30319\Config\web.config, you can see a section. You can also see the handlers in IIS (these can be changed x site).
For example, the HttpForbiddenHandler is one that just rejects the request. It is configured to be called for special files like the sources "*.cs".
You can define your own handler, that is nothing more than a class that implements an IHttpHandler interface. So it has 2 methods: ProcessRequest and IsReusable. This is more similar to your cgi program, as the implementation is mainly a method that produces HTML or any other type of output based on the information in the request.
Asp.net pages build on top of that, and have plenty of extra features meant to make it easier for you to develop pages. You implement a class that inherits from Page, and there are 2 code files associated to it (.aspx and .cs). The same can be said for asp.net mvc, but it is structured differently. There is much more than it, if you want to take advantage of it you'd need to learn about it.
The downside of those abstractions, is that it makes some developers lose track of the context they're at / about the underlying. The context is still the same, you're producing an application that takes a request and produces an output. The difference is that there is plenty more code in place intended to make it easier.
In terms of a more detailed list of IIS's ASP.NET Request Lifecycle, there are a quite a few stages in the HTTPApplication Pipeline. Faily recently there was a good blog post that I thought summarized them very concisely and well. It's "HTTP Request Lifecycle Events in IIS Pipeline that every ASP.NET Developer Should Know" by Suprotim Agarwal.
For a more detailed explanation you should check out the MSDN article on the subject. This will also go into information on what happens before that pipeline.

Resources