I have a spring boot application, I'm not really sure how users and threads work
The number of users depends on the application itself or tomcat?
Can I have more than 100,000 users at the same time in the application? What does it depend on?
How can I control the application so that there are no problems with the number of users at the same time?
It depends, my mate!
There are basically 2 most common ways of securing your web application: stateless and stateful.
If you're using stateless (For example JWT, which contains all authentication & authorization information), and every single request is re-authenticated & authorized when it reaches your application, and you don't have to store it anywhere, then you can basically have an infinite number of users logging in at the same time.
If you're using a stateful way to do this (For example the session-id, which is just a random string), then, in this case, you HAVE to store the session data somewhere, so that when you see that session-id in the request, you can use it to retrieve the current state of that session. In this case, it depends on your storage.
Related
I know that Spring Security has a lot of role-based authorization capability. But what if I have two ordinary users accessing data. How do I keep User A from seeing records belonging to User B? For example, keeping User A from seeing the orders created by all other users?
Please note that this is NOT role-based authorization. User A and User B, etc., are all ordinary users, differing only in their identities.
In an existing Spring application I'm currently getting the job done with a filter in each DAO, ensuring that "... and user_id = $1 ..." is part of the queries. This also reduces the volume of fetched data, lowering database access costs.
In the future I will be breaking up my application into microservices. It seems to me that each microservice request must also have the UserDetails information. This sounds like an anti-pattern.
An API gateway would merely be a consumer of the approaches that I previously mentioned. So, is passing the UserDetails information to each microservice my best approach?
I hope the answer is not "create a role for each ordinary user, like "ROLE_USER_A", "ROLE_USER_B", etc.
Thanks,
Jerome.
In an existing Spring application I'm currently getting the job done
with a filter in each DAO, ensuring that "... and user_id = $1 ..." is
part of the queries. This also reduces the volume of fetched data,
lowering database access costs.
This is the correct approach
In the future I will be breaking up my application into microservices. It seems
to me that each microservice request must also have the UserDetails
information. This sounds like an anti-pattern.
There are several approaches you an use here. You could use spring security oauth, and separate the authentication server out into it's own component. Then the credentials will be stored in a central location. This will save you from having to pass the credentials around.
Another approach would be using perimeter security. Basically your gateway service would authenticate each request and then pass the user details to each component.
There are other approaches, but these two are pretty common.
I have 2 applications : the first one is written with ruby (It's redmine) and the second one is a Spring boot app and both are hosted on the same tomcat server.
How can i do that?
Sharing sessions is not allowed. By (servlet spec) definition, a session belongs to a single web application.
Reference: Servlet Spec 4.0, section 7.3:
HttpSession objects must be scoped at the application (or servlet context) level. The underlying mechanism, such as the cookie used to establish the session, can be the same for different contexts, but the object referenced, including the attributes in that object, must never be shared between contexts by the container.
There are ways you can probably work-around this limitation by setting-up shared caches, etc. but it will always be brittle and potentially dangerous from a security or resource-usage perspective.
User database or user data file(nosql) with use of a unique-user-auth-token, accessible by two apps (or 3, 4, 5 ...)
Global concept :
App request connection :
is exist "old auth token" in app storage ?
yes -> app send old and request new or same if not expired
no -> continue
is exist valid auth token on server ?
yes (an app is already connected) -> send validated auth token to app
no -> set new auth token and send to app, new AT is ready for other app
server store what app request connection and is connected
apps are now able to exchange datas via the server.
Sharing Web applications is, at a minimum, Bad Practice (TM): Web Applications are completely separated by design. If both applications easily could reach into each other's session: Imagine what would happen if one would overwrite values that have been set by the other, and both applications expecting different data under the same key name.
If you only need single-sign-on, there's a SingleSignOnValve available that will make sure you'll only need to sign in once (provided that you authenticate through the container, e.g. a Tomcat Realm). Check server.xml for the commented-out-default-value, or the documentation for more information on authentication and the valve.
You might work around it by implementing the UI in both modules and refer back to a common business logic, but this is a level of architectural change too broad to fit into this answer.
The stateless web application seems promising. How to make one? Especially with Spring WebMvc? Any guidelines?
Here are a few things on my mind:
Avoid creating session
Use a centralized storage for state info and share that among web application instances.
ADD 1
I think it is not a question of whether to keep state info or not. State info is always necessary if you want to do something useful. It is actually a question where/how to keep the state info. This article is useful. It mentioned in-proc/out-of-proc session, data cache, and why not to use session.
Related:
Use Spring MVC for Stateless web application development (no response yet)
Stateless Spring MVC
How to make a java web application fully stateless
How do I make my Web Application stateless yet still do something useful?
http://brockallen.com/2012/04/07/think-twice-about-using-session-state/
Here are some contributions. I'm not familiar with Java and Spring, but I believe these guidelines are valid regardless of your technology stack.
Stay away from sessions for authentication
As you anticipated in your question, avoid using a session to authenticate users. Sessions are peremptory and it's very difficult to replicate it consistently in a distributed, scalable infrastructure.
Also, load balancers don't work well with sessions: see Problem with Session State timeing out on Load Balanced Servers.
Use a token-based authentication system
A stateless app will preferably use a token-based authentication system. Firebase is a good example. Map the immutable user ID extracted from the token to the user data persisted in whatever storing mechanism you want to use. Since this user ID won't change, you'll be fine in a distributed database.
Don't confuse stateless with 'data persistence'-less
Sometimes people think that, by mapping a user ID to user data in a database, you are making a stateful app. It's not true. Let me make it clear:
An application that persists user information in a database and has dynamic responses for authenticated users IS NOT NECESSARILY STATEFUL. Stateless means the app won't have to distribute mutable authentication sessions across multiple servers and won't change its internal state to a particular client depending on session data.
The trick of stateless is: once a user validated its token by logging in, the server don't have to distribute anything new across the database servers and it won't change its state to that client. It can extract user info from the token and carry out what's needed to answer the request. If the token expires, the client will require a new authentication, which will generate a new token, but this is isolated from the app server, since the user ID will remain the same.
Use cookies for caching while remaining stateless
If caching in cookies some frequently requested data will improve performance, that's fine, go ahead and cache. Just make sure the cookie isn't connected to any server state and your app will not break if the client loses the cookie.
I´ve started using spring session successfully with one nginx, two tomcats and one redis server to implement clustered sessions and some questions have arisen.
First of all, I mean two completely applications when I talk about different applications, I don´t talk about two instances of the same application.
May I use two or more different spring-session applications to store sessions with only one redis server in production?
These applications can run in different tomcats instances?
How Spring session avoid session id conflict between different applications with one redis server?
Is it necessary to append suffix or prefix id to avoid this problem?
Spring Session does not natively support for scoping sessions at this time. See gh-166 for details on tracking this.
Spring Session generates a secure random id with high level of entropy for session id's so there is extremely low probability that you will get collisions.
This means that you can use the same Redis instance for multiple applications using Spring Session so long as you are ok with the following statement:
A malicious user can use Application A's session id with Application B. Why is this important? Consider the following scenario:
Application A is a public application which any user can create an account for.
Application B is a private application which only users who are invited can sign up.
The malicious user creates an account and authenticates with Application A
The user copies their session id for Application A. They navigate to Application B and paste the session id into their cookies for Application B and are now authenticated.
This might not be a problem for you. For example, good security practice would ensure that the user is properly authorized by looking for an ADMIN role in Application B. Application A would not populate that role, so while the user is authenticated with Application B they are not authorized to use it.
My server needs to log-in to another server (for accessing payment API). Result of successful log-in operation is a session token that is valid for 25 minutes.
Where can I store this session token so that it is available across multiple requests and multiple users? (i.e. user session is not an acceptable solution).
I need some sort of an application state or cache storage.
Just to demonstrate the problem - a file could be used to store this value, but I don't want to deal with concurrency, and security implications this solution comes with. I would prefer an in-memory solution.
You could use either the core JSession or JCache framework objects.
http://docs.joomla.org/JFactory/getSession
http://docs.joomla.org/Using_caching_to_speed_up_your_code
http://docs.joomla.org/Cache