Introduction
Most of our applications are installed under the local user account which has full-trust permissions. But what if we were to deploy the applications in a more secure environment, say an office where the administrator does not wish to grant you write access?
Well the .NET Framework provides a little less known feature called Isolated Storage to overcome such restrictions. The cool part of this feature is that the .NET Framework takes care of all the plumbing work of creating, fetching and reading the files. However the most important aspect of Isolated Storage is to overcome security limitations of applications writing data to the operating system. Your application will be able to write/read user data to/from the underlying O/S regardless of it running under partial, limited or full-trust mode when it uses Isolated Storage.
Overview
So how does it work? The framework creates stores in an isolated environment in which the application can create and use both files and directories. Further other applications will not have access to this store and two users on the same system will have different stores for the same application. It is very much like a virtual file system.
Building Blocks
It uses the System.IO.IsolatedStorage
namespace of the .NET Framework.
It makes use of the IsolatedStorageFile
, IsolatedStorageFileStream
classes.
Using the Code
The sample application creates and stores project files that contain a name and version. The UserStore.cs class does all of the heavy lifting and you can use this in your projects or even extend it for whatever other requirements you may have.
Let us take a look at the UserStore
class. We must first grant permissions to the class that will use Isolated Storage. We can do this by using the following annotation with the class or method.
[IsolatedStorageFilePermissionAttribute(SecurityAction.Demand)]
public class UserStore
Then we need to instantiate an IsolatedStorageFile
object called ifl
:
IsolatedStorageFile ifl;
public UserStore()
{
ifl = IsolatedStorageFile.GetUserStoreForAssembly();
}
Create the project files in the storage:
public void createProject(string fname,string content)
{
IsolatedStorageFileStream isf = new IsolatedStorageFileStream(fname+".prj",
FileMode.Create, ifl);
StreamWriter sw = new StreamWriter(isf);
sw.Write(content);
sw.Close();
}
Get files from the storage:
public string[] getProjects()
{
string []files = ifl.GetFileNames("*.prj");
return files;
}
To read the contents of a file, create a IsolatedStorageFileStream
and wrap it in a StreamReader
:
public string getProjectContents(string fname)
{
IsolatedStorageFileStream isf = new IsolatedStorageFileStream(fname,
FileMode.Open, ifl);
StreamReader sr = new StreamReader(isf);
string content = sr.ReadToEnd();
sr.Close();
return content;
}
Delete a file from the storage:
public void deleteProject(string fname)
{
ifl.DeleteFile(fname);
}
Points of Interest
Isolated storage isn't a substitute for securing sensitive information. As you can see from the screen shot, the file location and contents of the file are easily accessible. I strongly recommend encrypting passwords and other sensitive data before storing them in the Isolated Storage area.
You can set quotas for space available to each user of the application by specifying it in the class annotation.
[assembly:IsolatedStorageFilePermissionAttribute
(SecurityAction.Demand, UserQuota=5242880)]
This is important from a Security Architecture point of view as you can benefit running under lower user privileges.
In the next article, I'd like to introduce Smart Clients. This will be a base for that article.
History
- 16th April, 2009: Initial post