Introduction
The application I'm mostly working on gives access to students and teacher to their personal information inside their institute. Often the students use shared computers inside the campus which may lead to security/privacy problems. One of those problems is links to documents inside pages the student visited. As the links are stored with the page, it's clearly possible for others to see them too, while using the same computer/browser. I will give some resolution to this problem here...
Background
In the mentioned environment, students have the ability to ask questions from teachers and academic staff - like 'why my grade is 99 and not 100!'...
To those question in - most cases - they attach some documents to prove their case. Those documents stored on some storage and later presented to the other side. In the first versions of our application, that was done by creating some <a>
elements on the page linked to the document. As concerns regarding security/privacy come into focus, we decided that we have to find a way to hide information about the location of the documents and prevent watching those documents at any later time.
The Solution
Step One - Remove document information from client
We replaced the <a>
with a button. On that button, the only information we have is the identifier of the document to be shown - we already had a table where references to all the documents are stored so we only use that tables' id...
<asp:Button ID="idShow" runat="server" Text="View Document"
CommandName="Show" CommandArgument="[document-id]"
OnCommand="ButtonCommand" />
For totally removing information, we pass even that document-id
on the session - so no way client can see and reuse it...
protected void ButtonCommand ( Object sender, CommandEventArgs e )
{
Button oBtn = ( Button )sender;
if ( oBtn.CommandName == "Show" )
{
Session.Add( "file_id", oBtn.CommandArgument );
ScriptManager.RegisterStartupScript( this, this.GetType( ), "showFile",
"window.open('FileStream.aspx')", true );
}
}
There is a flaw in this solution, as most modern browsers will block the new window we try to open as a suspected popup. However, according the security experts, we are working with it's ain't problem, and that bit of involvement of the end user is expected...
Step Two - Render the document
The most important part is how we use the document-id we received. Use and destroy! So after rendering the document once even page refresh will result in some kind of missing document.
int nID = Convert.ToInt32( Session[ "file_id" ] );
Session.Remove( "file_id" );
DocumentDetails oDocumentDetails = oDAL.GetDocumentDetails( nID );
With that code, we have all the information on the requested document so we can move to the rendering phase...
string szPath = Server.MapPath( Path.Combine( oDocumentDetails.Path ) );
Response.Clear( );
Response.ContentType = MimeMapping.GetMimeMapping( szPath );
Response.TransmitFile( szPath )
Response.End( );
This is maybe the most simple code you ever saw. The only catchy part is the ContentType
. You have to put there the right MIME type for your document, otherwise your browser may display it as gibberish.
In this sample, I use a .NET 4.5 feature - GetMimeMapping
, however in older application, you may write a method (with some switch
-case) to retrieve the correct MIME type.
How It Looks Like
In the image, you can see that while the user opened two different documents, the address bar of both is the same. On the other hand, the browser knows exactly well how to handle the document as we send the correct MIME type...
Demo Code
The code represented inside the tip will not compile into a full solution - however the attached demo contains a full - working solution...
Summary
You will notice that not a bit of information about the origin of the document made known to the client machine, so even on a shared computer will no security/privacy problem present itself...