0

The following code, located inside of an HTML file, reads the contents of a local .txt file into a Javascript string variable:

<script>
    window.onload=function(){
    var allText;
    readTextFile("/files/Textfile.txt");

    function readTextFile(file)
    // https://stackoverflow.com/a/14446538/8840617
    {
        var rawFile = new XMLHttpRequest();
        rawFile.open("GET", file, false);
        rawFile.onreadystatechange = function ()
        {
            if(rawFile.readyState === 4)
            {
                if(rawFile.status === 200 || rawFile.status == 0)
                {
                    allText = rawFile.responseText;
                }
            }
        }
        rawFile.send(null);
    }
}
</script>

The JavaScript code continues to parse this text to extract a specific substring from allText, and then finally this substring is shown to the user in the HTML.

The problem is that any visitor can find the text file's path by clicking "View Source" in their browser, and then they can navigate to the text file in their browser to see the file in full.

I do not want anyone to be able to see the complete contents of this text file.

So, is it possible to prevent visitors from viewing the .txt file, while still allowing my .html webpage to import the data from the .txt file as a string?

If it is not possible, how should I accomplish this effect, exactly?

Crickets
  • 524
  • 1
  • 8
  • 23
  • 1
    It's not possible. If you want JavaScript to get the whole text but don't want people to see the whole text then that's not possible. Everybody can just open their developer tools and look at the request. Why are you trying to do this? What's the context? – Felix Kling May 10 '18 at 00:12
  • Short answer, no. But you can send a request to web server, that will fetch and return the text for you. – Felippe Duarte May 10 '18 at 00:12
  • @FelippeDuarte Can you please provide an example of how I can "send a request"? – Crickets May 10 '18 at 00:13
  • AJAX uses the same underlying HTTP communication as opening a URL in the browser. You can't block just one of them. – Barmar May 10 '18 at 00:13
  • @FelippeDuarte That's what he's doing already. `XMLHttpRequest` sends a request to the server. – Barmar May 10 '18 at 00:14
  • @Crickets Anything you want to hide from users has to be done only in the server-side script, it shouldn't be sent to the browser. – Barmar May 10 '18 at 00:15
  • Don't forget that even if you prevent them from viewing the source, they can just go into the Developer Tools and look at the Javascript objects. – Barmar May 10 '18 at 00:15
  • @FelixKling The context is like I want to provide a "dish of the day" on a public website, but I do not want anyone to be able to see the list of future dishes. – Crickets May 10 '18 at 00:19
  • Then create an endpoint that when accessed only returns todays dish. The endpoint can still read your file, but on the server side, and only returns the data should be accessible. – Felix Kling May 10 '18 at 00:19
  • @FelixKling All dishes are simply contained in a single .txt file. Can you please link to or provide an example of how to create an "endpoint"? – Crickets May 10 '18 at 00:23
  • That depends on which webserver (and server side language) you are using (if any), and is out of scope for comments. – Felix Kling May 10 '18 at 00:23
  • Once they have that path there is also nothing stopping them going to the path and opening it with their text editor of choice. As others have mentioned, this functionality should be handled server-side, not client-side. – Jon P May 10 '18 at 00:37

1 Answers1

1

No - that's an attempt at a security through obscurity model and not a very obscure one. You can't trust the client or hide information from it. If a script can see it, a malicious or inquisitive user can see it too.

The solution is to expose on your server what someone should be able to see and no more. If the content is private for specific users, you'll need to setup some kind of login and authentication when they request it.

mahemoff
  • 44,526
  • 36
  • 160
  • 222