问题
I have been building a Windows desktop application in WPF and it has an embedded browser (CefSharp) that load local HTML/JS/CSS files. These files do not come readily with the application. They will be downloaded from a server each time the program is started. These files are kept in user's application data folder.
My concern is that these files, although hidden in the application data folder, user could still find them, open them and read their content. These files actually play the biggest part for the program's functionalities and my client really hope that no one could steal the source codes, meaning the content of the downloaded HTML/JS/CSS files.
So my first thought is to encrypt the files and decrypt them only when the program access the files. Question is, does CefSharp support this somehow? When or at which step does CefSharp begin to access the files? Could I intercept it and decrypt the files' content before CefSharp could read them? Otherwise CefSharp would not be able to read the encrypted content right? Note that the files should remain encrypted the whole time even when the program is running.
回答1:
After a long struggle, I finally found a working solution myself. The basic idea is to write my own resource handler as well as resource handler factory.
- Create MyResourceHandler that implements IResourceHandler.
- Do decryption in GetResponse function if ResponseLength has no value and Stream is null (optional).
- Create MyResourceHandlerFactory that implements IResourceHandlerFactory.
- Do decryption in GetResourceHandler function.
- Use MyResourceHandlerFactory while initializing ChromiumWebBrowser.
Sample GetResponse function in MyResourceHandler:
public virtual Stream GetResponse(IResponse response, out long responseLength, out string redirectUrl)
{
redirectUrl = null;
responseLength = -1;
response.MimeType = MimeType;
response.StatusCode = StatusCode;
response.StatusText = StatusText;
response.ResponseHeaders = Headers;
if (ResponseLength.HasValue)
{
responseLength = ResponseLength.Value;
}
else
{
//If no ResponseLength provided then attempt to infer the length
var memoryStream = Stream as MemoryStream;
if (memoryStream != null)
{
responseLength = memoryStream.Length;
}
else
{
var absoluteFilePath = new Uri(FilePath).AbsolutePath;
var fileBytes = File.ReadAllBytes(absoluteFilePath);
if (ShouldDecrypt)
{
memoryStream = Decrypt(fileBytes);
}
else
{
memoryStream = new MemoryStream(fileBytes);
}
responseLength = memoryStream.Length;
Stream = memoryStream as Stream;
}
}
return Stream;
}
Sample GetResourceHandler function in MyResourceHandlerFactory:
public virtual IResourceHandler GetResourceHandler(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request)
{
try
{
var uri = new Uri(request.Url);
var filePath = uri.AbsolutePath;
if (!File.Exists(filePath)) return null;
var mime = GetMimeType(filePath);
var fileBytes = File.ReadAllBytes(filePath);
if (ShouldDecrypt)
{
Stream decryptedStream = Decrypt(fileBytes);
return MyResourceHandler.FromStream(decryptedStream, mime);
}
Stream fileStream = new MemoryStream(fileBytes);
return MyResourceHandler.FromStream(fileStream, mime);
}
finally
{
request.Dispose();
}
}
And finally in case you wish to know how to initialize ChromiumWebBrowser that uses MyResourceHandlerFactory:
var browser = new ChromiumWebBrowser
{
ResourceHandlerFactory = new MyResourceHandlerFactory()
};
回答2:
The only methods I know are :
- Minify your JS files and then convert it to ASCII hexadecimal code and then use eval(decodeURIComponent("YOUR_ASCII_CODE_HERE")) to execute the javascript.
- For CSS Files the only way that I know about is to minify them.
Even both methods don't offer real encryption but you will give them some work to do if they want to read the files.
Here is a website site that uses the same method for JS protection: http://www.hightools.net/javascript-encrypter.php
来源:https://stackoverflow.com/questions/40297106/cefsharp-accessing-encrypted-html-js-css-files