I have an ASP:NET web project with a simple HTTPHandler which filters out requests from outside IPs.
The code itself works, but the HTTPHandler prevents my page from loading. No error. No infinite load. There's just a blank page.
If I remove the reference in the config, it loads perfectly fine. It's definitely caused by the HTTPHandler. I've also stepped through the handler and the code is definitely reached, it's just that when the handler is done, the page doesn't load like it should.
Here is the code.
public class SecurityHttpHandler : IHttpHandler
{
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
string ipAddress = context.Request.UserHostAddress;
if (!IsValidIpAddress(ipAddress))
{
context.Response.StatusCode = 403;
}
}
private bool IsValidIpAddress(string ipAddress)
{
return true; //for the time being, this will always return true
}
public void Dispose() { } //clean
}
The handler exists in another project (i have a reference to the assembly) and the httphandler is registered in my webprojects web.config as such:
<handlers>
<add name="SecurityHttpHandler" verb="*"
path="*Default.aspx"
type="MyProjects.CommonResources.Web.SecurityHttpHandler"
resourceType="Unspecified" />
</handlers>
I'm running IIS 7.5 in integrated mode. .net framework 4.0.
Let me know if I should add more code. I excluded the code from my web-project as the handler itself seems to be the cause early in the asp.net pipeline.
Related
I want to create filter rule in the web.config file for a C# application, to block http://website.com/folder/Default.aspx,
but allow http://website.com/folder/Default.aspx?db=Database. Basically they don't have "Default.aspx?db=Database" in the URL, then it will either redirect them to a website another website (or Deny access).
You could implement an HttpModule that performs your desired logic. You can register it in the web.config without any code changes to the project. Just compile it into its own dll and drop that into the bin folder of your website.
The module
class RequestInterceptor : IHttpModule
{
public void Dispose()
{
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
}
private void Application_BeginRequest(Object source,
EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
//Inspect the URL and decide if this is a request you are interested in
//context.Request.Url
//context.Request.QueryString
//Redirect, or whatever...
//context.Response.Redirect(...)
}
}
The web.config:
<system.webServer>
<modules>
<add name="MyInterceptor" type="YourNamespace.RequestInterceptor, RequestInterceptor"/>
</modules>
...
I want to add some additional claims to a Principal during authentication. I am trying to implement a custom ClaimsAuthenticationManager in my MVC 4.5 project which uses Windows Authentication:
namespace Project.Infrastructure
{
public class ClaimsTransformer : ClaimsAuthenticationManager
{
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
{
((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "Admin"));
}
return incomingPrincipal;
}
}
}
I have the web.config set up to use my custom class:
<configSections>
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</configSections>
and
<system.identityModel>
<identityConfiguration>
<claimsAuthenticationManager type="Project.Infrastructure.ClaimsTransformer, [AssemblyName]" />
</identityConfiguration>
</system.identityModel>
But the Authenticate method never gets called. Am I missing something?
The missing step is that you need to add an HTTP Module to kick all of this off.
So, you need a class that looks like this:
public class MyClaimsAuthenticationModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += Context_PostAuthenticateRequest;
}
public void Dispose()
{
// Nothing to dispose, method required by IHttpModule
}
void Context_PostAuthenticateRequest(object sender, EventArgs e)
{
var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
if (transformer != null)
{
var context = ((HttpApplication)sender).Context;
var principal = context.User as ClaimsPrincipal;
var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, principal);
context.User = transformedPrincipal;
Thread.CurrentPrincipal = transformedPrincipal;
}
}
}
This will pick up the transformer you specified in the web.config and call authenticate on it, then attach the returned principal to the HttpContext and the current thread.
You will also need something like the following in your web.config:
<system.webServer>
<modules>
<add name="MyClaimsAuthenticationModule" type="MyApplication.MyHttpModels.MyClaimsAuthenticationModule, MyApplicationAssembly" />
</modules>
</system.webServer>
Update
You can, of course, put the code from the method Context_PostAuthenticationRequest in the PostAuthenticateRequest handler in your Global.asax.cs class file. However, I prefer to keep the responsibilities of the classes small so I go for an implementation of IHttpModule so that the module does its thing and it is obvious what that is, and it is separate from other things that may be happening at various stages of the pipeline.
If your Global.asax.cs file is small then there is no problem with putting the code there. It should still work. However, you are mixing responsibilities in the class and it could get unwieldy in the future.
Are you calling the Authenticate method with something like this, and the Authentication is not taking place?
ClaimsTransformer manager = new ClaimsTransformer();
manager.Authenticate("resource", incomingPrincipal )
You may want to replace the "return incomingPrincipal" from inside the ClaimsTransformer class with a call to:
return base.Authenticate(resourceName, incomingPrincipal);
Also why do you need Windows Authentication?
I've been trying to use url routing in asp.net 4.0 to make a clean url for my website. when I try it in localhost, it works perfectly just like what I want, but after I upload it to Windows Azure Website, I keep getting error The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I've been trying to add code like in this URL :
How to implement URL rewriting with Windows Azure?
Using Windows Azure Websites with ExtensionlessUrlHandler
and some other link with almost the same solution like the above but with no result, are there any way to implement URL Routing or any other way to make a clean url with asp.net 4.0 on Windows Azure
(I don't use MVC and I deploy it on Windows Azure Website, not Cloud Service or VM)
Edit: The code that I add
in Global.asax :
protected void Application_Start(object sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterRoutes(RouteCollection routes)
{
var routeHandlerBrands = new WebFormRouteHandler<Page>("~/brands_book.aspx");
var routeHandlerCategories = new WebFormRouteHandler<Page>("~/categories_fs.aspx");
RouteTable.Routes.Add(new Route("Catalog/Categories", routeHandlerCategories));
RouteTable.Routes.Add(new Route("Catalog/Brands", routeHandlerBrands));
}
In WebFormRouteHandler :
public interface IRoutablePage
{
RequestContext RequestContext { set; }
}
public class WebFormRouteHandler<T> : IRouteHandler where T : IHttpHandler, new()
{
public WebFormRouteHandler(string virtualPath)
: this(virtualPath, true)
{
}
public WebFormRouteHandler(string virtualPath, bool checkPhysicalUrlAccess)
{
this.VirtualPath = virtualPath;
this.CheckPhysicalUrlAccess = checkPhysicalUrlAccess;
}
public string VirtualPath { get; private set; }
public bool CheckPhysicalUrlAccess { get; set; }
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
if (this.CheckPhysicalUrlAccess
&& !UrlAuthorizationModule.CheckUrlAccessForPrincipal(this.VirtualPath
, requestContext.HttpContext.User
, requestContext.HttpContext.Request.HttpMethod))
throw new SecurityException();
var page = BuildManager
.CreateInstanceFromVirtualPath(this.VirtualPath
, typeof(Page)) as IHttpHandler;
if (page != null)
{
var routablePage = page as IRoutablePage;
if (routablePage != null)
routablePage.RequestContext = requestContext;
}
return page;
}
}
And add handler & modules in Web.config :
<system.webServer>
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="Route.RoutingHandler, Route"/>
</handlers>
it work's perfectly when I debug it in localhost or publish it in my local IIS, but when I publish it to Windows Azure, it doesn't work
Edit 2:
I've tried to publish it to Windows Azure Virtual Machine and it's working ( no error occured for now ), did anyone know any other way to make a clean url for windows azure website ( not virtual machine or cloud ), or I should move my current Website to the Virtual Machine?
After rechecking the file that I've uploaded to Windows Azure, it seems that I forgot to upload the Global.asax file, so it doesn't work. And after I uploaded the Global.asax file, now it works perfectly, no wonder that the routing doesn't work before.
I am using HttpHandler to retrieve image from database and then use the Handler as ImageUrl in an Image web control on my web page (aspx). The code is shown below. But it does not work and so far I could not figure out why. The issue is HttpHandler is never been hit, if I keep the breakpoint at processrequest() it is never hit
Below is the simple code in Handler
public class ImageHandler : IHttpHandler
{
StaffMemberRepository db = new StaffMemberRepository();
public void ProcessRequest(HttpContext context)
{
int id = Convert.ToInt32(context.Request.QueryString["id"].ToString());
byte[] image = db.GetImage(id);
context.Response.ContentType = "image/jpg";
context.Response.BinaryWrite(image);
}
public bool IsReusable
{
get
{
return false;
}
}
}
and below is the markup in my webpage
asp:Image ID="imgStaff" runat="server" ImageAlign="Middle" ImageUrl="~/Handlers/ImageHandler.ashx?id=2"
Can someone let me know what I am doing wrong here?
Ok I could see my folly now. I just registered my handler in web.config and everything seems ok now.
I've been using Ninject as my IOC in my web app. It's great and I think it works really well, however I have been trying to register some interfaces / classes as OnePerRequestBehaviour but it doesn't seem to actually use the behaviour. The code runs correctly but in one of my classes it lazy loads page information from the database then once it has been loaded it doesn't need to hit the database.
My problem is that the lazily loaded property will load in my first request, when I then request the next page the same instance of the class is used. The reason I know this is because the class is not instantiated again and the lazily loaded property is already set.
This code is within my module class :
public class NinjectModule : StandardModule
{
public override void Load()
{
Bind<IUnitOfWorkDataStore>().To<HttpContextDataStore>().Using<OnePerRequestBehavior>();
Bind<CmsService>().ToSelf().Using<OnePerRequestBehavior>();
Bind<CmsRepository>().ToSelf().Using<OnePerRequestBehavior>();
}
}
Then inside my Global.asax which inherits from NinjectHttpApplication I have the following:
protected override IKernel CreateKernel()
{
OnePerRequestModule module = new OnePerRequestModule();
module.Init(this);
KernelOptions options = new KernelOptions();
options.InjectNonPublicMembers = true;
IKernel kernel = new StandardKernel(options, new NinjectModule());
return kernel;
}
The first call made to CmsService is within the global.asax as well on authenticate_request:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.AbsoluteUri.Contains(".aspx") &&
!HttpContext.Current.Request.Url.AbsoluteUri.Contains(".aspx/"))
{
CmsService facCMS = HttpKernelFactory.Get<CmsService>();
ContentPage page = facCMS.GetCurrentPage();
// DO Logic based on the page being brought back
}
}
The above GetCurrentPage() code:
public ContentPage GetCurrentPage()
{
if (_currentPage != null)
return _currentPage;
return GetCurrentPage(_isAdmin);
}
So as you can see the _currentPage variable is only loaded if it hasn't been set before, which should be once per request, however Ninject doesn't seem to be creating the CmsService per request it seems to create it for an abritrary amount of time.
Deos anyone have any idea of why this isn't working for me or any example code of where it definately does work?
Thanks
The OnePerRequestModule is an HttpModule, and needs to be loaded into your ASP.NET pipeline in order to work. If you add it to your web.config, it should work:
IIS7:
<system.webServer>
<modules>
<add name="OnePerRequestModule" type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/>
</modules>
</system.webServer>
IIS6:
<system.web>
<httpModules>
<add name="OnePerRequestModule" type="Ninject.Core.Behavior.OnePerRequestModule, Ninject.Core"/>
</httpModules>
</system.web>
The OnePerRequest behavior is greatly improved in Ninject2 (which is yet to be released).