i got a question about the rendering behaviour of react. Please correct me if I'm wrong, im new to React and Web Development.
Afaik the default rendering of a react SPA happens on the client side, right?
So this means the whole JSX code in the src directory will be downloaded on the first visit of the page (see image of the Chrome WebDeveloper Tools Source Tab), right?
Let's assume i would develop an admin area where only authorized users should have access to, e.g. through JWT, the JS-Code still contains information about the admin area, even if it's not rendered, a guy with the corresponding knowledge could get access to the area because all information about the admin area is already downloaded to the client computer, right?
Sure i can protect sensitive data through the api and JWT Token, but what about if i don't want the client to know about the admin area content? Is there a best practice for some kind of this case, e.g. a mix of client-side (default user content) and server-side (admin area content) rendering? What would be the best way to do this? What are the advantages and disatvantages of client-/ or server-side rendering?
Thank you &&
please be kind, as already mentioned i'm knew to React and WebDev &&
sorry for my english, i try to improve it continuously.
Afaik the default rendering of a react SPA happens on the client side, right?
Not necessarily. It depends on how you set up the project.
So this means the whole JSX code in the src directory will be downloaded on the first visit of the page
Not necessarily. e.g. see Webpack code splitting.
Sure i can protect sensitive data through the api and JWT Token, but what about if i don't want the client to know about the admin area content?
Don't put the content in the app. Keep it in the data that is protected by your JWT.
Or make your customer facing application and your admin application different apps in the first place.
What are the advantages and disatvantages of client-/ or server-side rendering?
Server-side rendering is faster on initial load, works when JS fails, and is better food for search engines.
Client-side rendering is faster on subsequent page loads.
It's not really a factor in security.
Related
Note: I am kind of new to web development so please help me through any misconceptions I might have.
I am trying to learn the MERN stack. As an example, I am trying to make a two page site with a homepage and an about page. I made a ./public folder and added an index.html and an about.html to that folder. Then I started by learning some basic express where I have this line which will let the server serve static files from the ./public folder:
// set static folder
app.use(express.static(path.join(__dirname, 'public', )));
After I felt good about this, I wanted to add React to my existing project. This is where I ran into some confusion. It seems like React doesn't allow multiple pages in my website; I saw this SO post. So, React is good for building single page applications. I also saw this YouTube video where the first three minutes explain the difference between traditional multiple-page applications and React SPAs. He stated that all the pages will be sent at one time and the react-router will intercept any page requests and re-render the browser with the pages it already received on the first page load.
So, finally we get to my question. Going back to my example, suppose my about page is VERY large, with a lot of text and images. Isn't that potentially wasteful if I load the homepage, but the server has to send the entire website including the large about page, even though I might never even click on the about page? Once it is all loaded, I understand that the client has a smooth experience going from one page to the next without having to contact the server. But doesn't it mean that the client experiences long initial wait times. And, isn't this wasting server resources by sending pages the user might never click on. And the problem only seems to get worse the more unique pages the website has.
"He stated that all the pages will be sent at one time and the react-router will intercept any page requests and re-render the browser with the pages it already received on the first page load."
This is an oversimplification that is at the root of your misunderstanding.
Your react app is going to be a small amount of HTML that acts as the document root, and then a fair amount of CSS and JS. This JS React app will execute to generate your pages based on how you have configured your views and wired them to any data model. Generally with a SPA like this, you will load one view at a time, and it will, if applicable, make a request to the server for any data it needs to render, which will generally be returned as JSON. Once the JSON is received, it will get parsed in the browser into the data model and the UI will update to reflect the new state of the data model. Critically, each view (if wired correctly) will only fetch data from the server when the view loads; furthermore, any images or other assets in the UI will only be loaded when the UI renders them, so there will be no prefetching that wastes resources.
Because the react components can basically act as templates, you can actually save bandwidth in this way. Say you had 100 product pages on your site that were identical except for the product information. If you were to serve a new HTML document for each page there would be duplicated bandwidth in the markup sent each time. However, in React you can define a single <ProductPage /> component that will fetch only the product information and load it into the markup template each time, removing the issue of sending duplicate HTML.
There are also additional ways to split up your react app using tricks like lazy loading, to only fetch the salient JS when it is about to be used.
So, no, using a React app does not mean that it fetches all the HTML pages and assets for the site all at once. While one could write a React app in a wasteful manner, most properly structured React apps should be smaller than the rendered totality of the site.
I am currently working on a project whose backend I will be writing using Flask (cannot change that), and the frontend will be developed using React by someone else (cannot change that too). I am currently working on the login functionality and I have a few questions. I am really just beginning backend development, so please excuse me if I have some redundant questions or beginner-level questions.
I am curious as to how the login-system as a whole will be handled, not just in terms of actual login - but more so when it comes to restricting access from non-logged in users.
The tutorials and online courses I have taken on Flask have done one of 2 approaches.
The first approach was using Flask-Login to login a user and ensure that they are logged in as they navigate to different websites. This was pretty straightforward to understand and relatively easy to implement. However, (and please correct me if I'm wrong), this would require all the navigation and redirecting to be handled server-side. Therefore, we would not be utilizing React's ability to create single-page websites (instead relying on hyperlinks from each page to the next), which is far from ideal and something that we'd like to avoid if possible.
The second approach was using JWT tokens. Again correct me if I'm wrong, but we would only be able to check that the JWT token is correct if it is included in an HTTP request, which again makes creating single-page websites not feasible. Another issue with JWT is that the tokens expire fairly quickly (around 15 minutes as far as my research tells me), which is not suitable for our project because it would require users to be logged in for a longer duration. I have read about refreshing JWT tokens, but I would like to know more about the feasibility of such a process given the short expiration time (we would have to do a lot of refreshes).
My main question is:
How can we create single-page websites while preventing non-logged in users from accessing restricted pages?
But also please feel free to give me any feedback or concerns about what I have talked about.
Thank you in advance and sorry for the long post
Just use JWT, you can add the token to the header of the HTTP request and you can set the lifetime (JWT_EXPIRATION_DELTA) of the token - check this link https://pythonhosted.org/Flask-JWT
I creating a Web App that using Nuxt.js, with Server-Side Rendering.
I don't want expose my backend data, so I tried to use asyncData and Axios to request to my backend server.
But the Nuxt.js exposed my backend data to client with window.__NUXT__.data variable.
I tried remove this by using render:route hook, But It says
[Vue warn]: The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside p, or missing . Bailing hydration and performing full client-side render.
So I tried remove the script that making not matching error, But It makes stop working script at my site.
So the question: How to disable the client hydration(client-side virtual DOM tree rendering)? or How to stop exposing raw data?
I used asyncData with this code:
asyncData ({ params, error }: { params: { id: string }, error: Function }) {
return axios.post('(backend)', data).then(res => res.data ? ({ data: res.data }) : error({ statusCode: 400, message: 'Bad request' }));
}
You cannot stop the hydration of your SSR'ed content (not yet at least, it is planned to server only static content pretty soon tho).
Nuxt is aimed to add SSR to your day to day VueJS SPA. If you don't want the hydration, you're probably using the wrong framework here anyway.
Astro may be a better fit, to name just one. You could find more here too.
The DOM mismatch issue is explained here (reasons + solution).
How to hide things on the client side?
Short answer: you can't.
Long answer available here.
If you want to display something on a page, you'll need data.
Nowadays we're using SPAs to have a local state in the browser. Since it's local and under your eyes, the state is living in your browser, so you can't really hide it and also, why would you do that?
If you want to hide the data, maybe don't send it initially or send an image at least.
You could also make some obfuscation, but this will just be a band-aid and not really good on semantics/performance/etc...
If you have some sensitive data that you want to show only to admins or so, you could use some auth and rights checking. More details above, in the long answer.
If you really really want to hide data on plain sight, that is, you want to send data on client-side without exposing it, then you do not have a full solution for that as it is, but there are ways to achieve what you need, choose your preference based on your intent.
Not sending data to the client if you do not want to expose it
Yes, I know you have asked for the diametrically opposite, but, before you read the really, really unconventional and often difficult approaches, first, let's ponder on whether you really need this indeed. The alternative would be to just not send this data to the client at all, but rather work with this sensitive data on the server. It is the scenario you will need 99.9999% of the cases of web-development. (the number is my subjective estimation, not the result of a representative statistical research)
Email, chat, SMS, paper mail, smoke signals, morse messages
You may need to send that information for the client, but this does not automatically mean that you will need to send it to the client-side of your website. You could send the information using some other channel, just make sure that it's trusted and reliable. For this reason I don't really recommend the use of smoke signals.
iframe
Now to the technicalities. Modern browsers protect against the scenario when you have webpage1 opening webpage2 in an iframe if they happen to have a different domain. So, you can create a domain that's different from the one your main page uses and show whatever you want to the client by calling a page of your brand new second domain (via HTTPS, of course), using minimized Javascript and closures. If you need communication between your iframe and your main page, then you can use messaging between the two, see Communication between tabs or windows.
A possible objection may be that one can still see the network tab of his/her browser where the actual received data is being shown as well as the possibility to debug Javascript. Well, bad luck. We cannot send the data to the client without sending it to the client. If this caveat is too much of a risk, then read on.
Encode the content you want to avoid from exposure
Yup, it will create a lot of difficulties and sometimes you will wish you never did it, but you can encode your top secret data and even if the user has access to it, he/she will have no idea what it is. But in this case you will need to face the problem of encrypting/decrypting your data whenever you use it.
You can use visual representation of your data
Like an image, an svg or some other kind of generated captcha-like content, but don't send it a file, because a third-party watcher may just download it. If you generate that inside an iframe, then your data is difficult to mine. Oh, wait, but what if the hacker looks at your screen from behind your chair?
Write your own browser (extension?)
You can implement a browser or a combination of browser extensions that will handle this and use HTTPS. But what if the spy has a lucky day and deciphers it? What if you have a virus?
Bottom-line
By the sheer fact that you are sending data to the client-side you will have to accept some risks. There is no way around it. You can reduce those risks, but it's always safer not sending the data than sending it.
As my App frontend would be in angular. Below is a flow I have considered for the webapp.
User types in the browser http://www.example.com
Server serves a dummy page with no HTML with the only javascript in angular
Now in the code client makes an ajax http get request to may be http://www.example.com/start
Now if the user is logged in server sends a JSON response with the user info
for angular to route into the users homepage. Otherwise, an appropriate response is sent and angular routes into the sites normal homepage with options to log in.
As I am new in angular , I was asking is this a good design and if not how do experts do it?
My problem is not the authentication , my problem is , when I serve static page I have to pass the user info to the client somehow. When client types it in a browser url bar , I don't have any way to capture the response in a javascript code. That's why I have to send a dummy page first so that I can capture create an ajax request to capture the responses in javascript and act accodringly
And also in the angular $http.get does angular automatically sends the previous session info(cookies) or I have to explicitly send it ?
I am using express,nodejs as server in my backend.
Server serves a dummy page with no HTML with the only javascript in angular
You should really read a little bit about AngularJS before you start trying to build out a frontend implementation with it - most specific single-page application design.
This is a great tutorial for building a single page app with AngularJS.
Essentially, you'll need to render some HTML just to load the Angular application and controller(s) required to validate a user's logged in status.
Borrowing some principles from mobile-first design, if you design your interfaces to first look great without data - you'll have a decent experience between #3 and #4 while your AngularJS controller decides whether to redirect the user or adjust $scope to affect the UI in some way based on your business logic.
You can use a ton of different treatments for #3 to communicate to the user the status of the application (in terms of verifying their login, re-routing them to some secure area, or declining their access)
It's definitely possible to do this, but I would recommend against it. Depending on your user base, there are still enough places in the world and devices with network latency and poor rendering capability, so I would not recommend a completely 'empty' page load w/o javascript. At a minimum, have some static welcome text or something that gets replaced when your angular app is done loading.
The cookies should get passed if you configure it correctly, but I tend to use token-based auth for single page apps.
I am attempting to develop a pure javascript web application using Dojo. The problem I face is one of restricting access to portions of the application. Authenticated users should be able to access everything, whereas non authenticated users should only be able to access a login screen.
The issue is that nothing (that I am aware of) will stop a user from opening up a browser javascript terminal and entering something like: app.displayRestrictedContent(); and thus gaining access to a screen intended for authenticated users.
I have implemented an ajax based login; all ajax calls are secured with a session. So while the non-authenticated user can load a restricted screen, they wont be able to fetch data for it. But still, It seems wrong for this screen to be arbitrarily accessible.
Am I trying to do the impossible? It seems silly to write code such as if (user.auth) app.displayRestrictedContent(); when it's so easily circumvented. And this leads me to believe I am missing something rather obvious to everybody else. I can't find much information at all on pure javascript based apps and authentication models.
But still, It seems wrong for this screen to be arbitrarily accessible.
Because it's client-side code. Anything you write in js, or get compiled to js, expect it to be readable by the users.
Am I trying to do the impossible?
you can dynamically load js modules after the user authenticates. So at first, just load 1 login module. When the user logins, if successful, the server return a list of js modules to load, if not, return empty list. It also helps improve load time when the users come to your website.
I'm by no means an expert, but here are some thoughts I've made on this. I don't think you've missed anything (if so, I have too) - I think this is a pretty fundamental issue with all client applications, whether it's a compiled executable or a Javascript.
Of course, the compiled executable is not particularly hampered by it, because it's been made into machine code which is very difficult to read or decompile into anything useful. With Javascript however, the application is often served exactly as you wrote it, and so it's easy to modify and reason about.
That brings me to the first semi-solution: obfuscating your Javascript. If you use Dojo's build tool with the shrinksafe parameter, all unnecessary whitespace is removed and all identifiers are shortened, making the code quite difficult to read. I called this a semi-solution, some may say even that is giving it too much credit - I myself still think it's worth doing. After all, the shrunk code downloads faster too!
The second measure I take in my apps is to separate the different parts into "build layers". For example, in my build profile, I'll have something like
dependencies = {
..
layers: [
{ name: "../myApp/Core.js", resourceName: "myApp.Core",
dependencies: ["myApp.Core", "myApp.Foobar"]
},
{ name: "../myApp/modules/Login.js", resourceName: "myApp.modules.Login",
dependencies: ["myApp.modules.Login", "myApp.modules.LoginUi"...],
layerDependencies: ["../myApp/Core.js"]
},
{ name: "../myApp/modules/Secret.js", resourceName: "myApp.modules.Secret",
dependencies: ["myApp.modules.Secret", "myApp.modules.SecretUi"],
layerDependencies: ["../myApp/Core.js"],
authentication: 42
}
]
}
Now, instead of serving the built JS files directly as static files, I let the requests go through a controller in my server-side application, which checks if the JS layer requires authentication and whether or not the user is logged in with the necessary access.
This does have certain cons. The JS files aren't cached, and if I had all my JS in one build layer, the application would probably load slightly faster. There's of course also a limit to how nuanced it's worthwhile to make the layers. More layers mean more hassle, but also more finely grained module access.
I'd be interested to hear others chime in on this as well. It's a good question.
When a user successfully logins the server should provide him with a session token. The Afterwards, whenever the user requests a resource (either via just redirecting the browser or via AJAX) he shows the server his session token (either by storing it in a cookie and sending it automatically on all requests or by explicitely passing it in the body of an AJAX request)
The server can then use session tokens from the users to control authorizations server-side, rejecting any request with an invalid or outdated token.
https://en.wikipedia.org/wiki/HTTP_cookie#Session_management