Is there a way to create a protected download link which is random, expiry, requires a password and pointing to a specific file in C# that is associated with IIS 7.0?
Several random links can link to the same file.
Built-in codes or perhaps 3rd party libraries?
For example, http://www.example.com/<some random gibberish>/<md5 of file>/file.jpg
One way to do this would be to use GUIDs. GUIDs are designed not to collide, and that design also leads to a difficulty in guessing valid GUIDs. I'm sure someone out there will tell me that this is not very secure! Well, you are also protecting with a password. It is pretty easy to generate a GUID in C#.
I guess what you need is firstly a way of ingesting the files that you want to protect in this way, and secondly a handler that will respond to requests in a given path and inspect the GUID in the path to determine if it's valid.
You'd then need a database back end to maintain lists of GUIDs corresponding to URLs, the password (preferably crypted) and the expiry date. The handler would inspect the entry for the requested URL/GUID to see if the link has expired, then prompt the user (could do this via a web form easily enough) for the password and check this against the crypted password stored in the database.
To generate a GUID, you want:
System.Guid.NewGuid().ToString()
To create a module that is called before every request (for IIS7) you can add an entry to your web.config like so:
<modules>
<add name="MyDownloadModule" type="Example.MyDownloadModule, Example"/>
</modules>
where MyDownloadModule is the class containing your handler, in the namespace Example.
Inside that class you then need to implement the IHttpModule interface, in particular overriding the methods:
public string ModuleName {
get { return "MyDownloadModule"; }
}
public void Init(HttpApplication app) {
// Add an event handle which is called at the beginning of each request
app.BeginRequest += new EventHandler(this.AppBeginRequest);
}
//
// Our event handler for the BeginRequest event
//
private void AppBeginRequest(Object source, EventArgs e)
{
HttpRequest request = app.Context.Request;
//
// Is this a file download?
//
if (request.AppRelativeCurrentExecutionFilePath == "~/downloads") // or whatever
{
// this is where you work your GUID inspecting magic
}
}
Going about it this way means this will be called for every request to the server, which may not be what you want.
You could always create your own HttpHandler, and then implement your own proprietary expiration/validation code.
Something like:
http://www.example.com/download?token={your_token}
It would then be a trivial matter to have the handler intercept the request and grab the file from disk, and deliver it to the client if the ?token querystring value is correct.
For more information on the IHttpHandler interface, see MSDN http://msdn.microsoft.com/en-us/library/system.web.ihttphandler.aspx
Related
Hello fellow seasoned developers!
I was wondering if it were possible to override the .Net Request.QueryString object somehow? It would be really nice if this could be done without having to create my own HTTP module as well.
I have been tasked with RSA(1024) encrypting all the querystrings in my application. However, the application is already built and there's a LOT of places where querystrings are being set so ideally i would like to make a global change that would decrypt the query and place it in the normal Request.QueryString so as to not have to change my code everywhere, and maybe pass it along to other devs within my team and they also don't have to change their code.
Now, I already built the encryption object and use the SessionID for salts to make the keys unique per session. I have also tried intercepting the HTTP request in Global.asax so as to rewrite the request path with the decrypted query, however, that was a bust as any postbacks being performed on those pages put the decrypted querystring back into the POST, which i obviously don't want.
So now i'm at a stage where i would like instead of re-writing the path, to intercept or override the Request.QueryString object on a global level and use my decryption methods there whenever a call to this[key] is placed, and thus again, not having to stop using Request.QueryString. However, after hours of searching on the web, i could not find a single example on how to do this...
If anyone could help me out with this i would be most grateful!
I think the easiest way to accomplish this is to use an Extension Method. Perhaps something like this:
class Program
{
static void Main()
{
var decryptedValue = HttpContext.Current.Request.DecryptQueryStringParam("myParam");
}
}
public static class HttpRequestExtensions
{
public static string DecryptQueryStringParam(this HttpRequest extendee, string name)
{
// do stuff to decrypt
return DecryptMethodStub(extendee.QueryString[name]);
}
private string DecryptMethodStub(string queryString)
{
return "something decrypted the string";
}
}
Please note that the Program class above is for illustrative purposes only... in reality you would call Request.{ExtensionMethod} within the body of a asp.net web forms page or an MVC controller which already provide direct access to the HttpRequest object through the Request property.
here is some information about extensions:
http://msdn.microsoft.com/en-us/library/bb383977.aspx
I have a website that, in order to work properly, needs to have a XML file appended to all its URLs, let's say the file is called module-1.xml.
In order to keep those URls clean, I wrote a IHttpModule's that uses the HttpContext.Current.RewritePath to do the appending job inside the OnBeginRequest event.
The IHttpModule looks pretty simple and works:
public void OnBeginRequest(Object s, EventArgs e)
{
string url = HttpContext.Current.Request.Url.AbsolutePath;
if (url.EndsWith(".aspx"))
HttpContext.Current.RewritePath(url + "?module-1.xml");
}
Now, I wanted to use the session variable to detect when a user decides to switch the website from model-1.xml to model-2.xml and have my code changed as follow:
public void OnBeginRequest(Object s, EventArgs e)
{
string url = HttpContext.Current.Request.Url.AbsolutePath;
if (url.EndsWith(".aspx"))
{
if (HttpContext.Current.Session["CurrentMode"] == "1")
HttpContext.Current.RewritePath(url + "?module-1.xml");
else if(HttpContext.Current.Session["CurrentMode"] == "2")
HttpContext.Current.RewritePath(url + "?module-2.xml");
}
}
From what I have found, the session can be accessed inside a module but
not from inside the OnBeginRequest event which is the only event where HttpContext.Current.RewritePath can be made functional (at least from all the testing I have been doing).
Is my assumption correct? And if it is, what alternative could I use? Create a custom Session variable? Should I read from a txt file or from a DB in order to know what module the user is looking at? How could I keep track of a user from within the module?
It depends on the security required by your application. If you don't care about a malicious user being able to change the value, just store the module name in a cookie. If you do, you could store a securely generated identifier in a cookie, and look that up in a database to get the value you need to use.
Get rid of the module completely. You are only attaching it to aspx pages, so there is no need for that to be in the URL. Instead just create a base page for your project pages to inherit from:
public class Solution.Web.UI.Page : System.Web.UI.Page
{
public string CurrentMode
{
get { return String.Compare(Session["CurrentMod"].ToString(), "1") == 0) ? "module-1.xml" : "module-2.xml"; }
}
}
That way you can simply access it on your pages without the overhead of that module or the risk of putting that info in a cookie.
I have a WebService built in WCF (C#.Net) that contains dozens of methods. On every methods, I wan't to validate if the current user has access to this particular action.
Right now, I have something like this :
public MyContract MyMethod(int MyParameter)
{
ValidateAccess(MyCurrentIdentityInfo, ActionEnum);
// Do stuff here...
}
public void MyMethod2(int MyParameter)
{
ValidateAccess(MyCurrentIdentityInfo, ActionEnum);
// Do stuff here...
}
etc...
You'll notice that I call a method at the beginning to check the access rights and then, do the code I need. This code works fine, but I have to call this method on every method in my service and I don't find it pretty.
Is there a more elegant way to acheive what I'm trying to do? I tried using a custom attribute but didn't succeed.
Note that I'm NOT trying to authenticate the user on the WebService itself. In the exemple above, the user would be valid on the WebService. But I'd like to run a custom code to check if he can call a method that deletes a record for instance.
You can think to use Castle Dynamic Proxy to inject the validation of the operation on the logged user.
Let us consider a sample website application and running in local host.say for example www.asdf.com . when ever the user hitting the url in browser
Can it can be captured by inheriting ihttp handler or ihttp module to our class
If the url has been hitted by changing www.asdf.com?t=value is it possible to take that value.
In java this concept is used as servelet filters . Is there any thing like that in dotnet
waiting for your responses
Modules and Handlers do two different things.
Modules plug into the application and request lifecycles and respond to any number of events along the way to affect some bit of functionality to each request. Usually, it for stuff like security, logging, compression, etc. For example, FormsAuthenticationModule responds to the AuthorizeRequest (amongst others) event during each request, where it checks to see if there is an authentication ticket, validate it, and then indicate to the current context whether or not the user is authenticated (and who).
Handlers are designed to wait for a request to certain paths or extensions and do something useful. For example, requests to .ASPX files are handled by a Page handler, which parses and executes an ASPX and its associated codebehind (if there is one).
Both Modules and Handlers have access to the HttpContext object, which allows them to inspect and in many cases manipulate the current application, the current request and response, the user, etc. So yes, either can access the query string values provided during a request.
I believe modules are most analogous to a servlet filters.
This module looks for the t query string and echoes it at the beginning of every request.
public class MyModule : IHttpModule {
public String ModuleName {
get { return "MyModule"; }
}
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;
context.Response.Write(string.Format("The value of \"t\" is {0}", context.Request.QueryString["t"]);
}
public void Dispose()
{
}
}
I have my own SQL based session class. I want to automatically commit the data in the session at the end of program execution (i.e. at the end of serving the page request). Do object destructors (finalizers) not get executed at the end of every request? Is there anyway of doing this instead of having to explicitly call a Dispose() method every time I am done with my session object?
One possibility is by using the global.asax. There is a handler for the end of a request, in C# the call inside global.asax.cs would look something list this:
protected void Application_EndRequest(object sender, EventArgs e){
//perform action - you have access to the HttpContext
}
You have to watch out for what is going through the handler though - depending on your configuration your assets (stylesheet, images, etc.) may also be hitting this request so you may have to devise a way to ensure only your pages have the actions taken on them.
In C#, finalizers are non-deterministic, which means you don't have any guarantee when it will be executed. So, no, you can't use them for your scenario.
I see two ways to approach this:
Programmatically calling Dispose at some point towards the end of the page's life cycle (or via the global.asax as mentioned by Michael G.).
Have your SQL based session class wire itself up to a page event (such as the Unload event) to do whatever actions it wants to clean itself up.
UPDATE:
In response to your question about suggestion #2, I will expound a bit. This option would be to somehow allow your SQL based session class to gain a refernce to the web page instance. One option (which I'll show below) would be to use the constructor of the SQL based session class to obtain a reference to the web page. Then the SQL based session class can sign up for any event that it desires in order to know what is happening to the page.
namespace SomeNamespace
{
using System.Web.UI;
public class SqlBasedSession
{
public SqlBasedSession(Page webPage)
{
webPage.Unload += new EventHandler(webPage_Unload);
}
void webPage_Unload(object sender, EventArgs e)
{
// the web page is being unloaded so this class can
// cleanup it's resources now
}
}
}
Let me know if this still isn't clear.
I would suggest to go with IOC container provider for these kind of stuff. You can hook them up, to the end of a request and execute some code, especially good for some transactional stuff.
I have been using Autofac, it has OnActivated() method, which I use to hook my transaction commits to on activation of session.