I want to keep track (with persistency) of users interactions with a microservice application developed with spring boot, so that i could consult them if something happened even maybe a year later.. One solution i found was use event sourcing and the problem was gone.. but due to some constraints i cannot go with that solution (in this project) so i was wondering..
Question
How can I track all user interactions and persist them in a spring boot microservice application?
if all the interactions that you want to track are sent to the server, then you can persist them in the database when the request is received in the server. To know who is the user you must need a way to identify him, for example, by using a token if the user is authenticated.
However, although this can be a solution the usual way to do this is using google analytics https://analytics.google.com/analytics/web/provision/#/provision
or snowplow https://snowplowanalytics.com/
Any of them track the actions done by the user in the frontend of the application
Related
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.
I'm using back4app as my back-end for my android application. My concern is that I don't see how I can stop hackers from spamming user creation in my database.
Since the client key and app ID is shipped with the app itself, anyone can use it and keep creating fake users.
Also if I disable user creation from application, there's no way for my actual users to sign up. I hope I was able to explain my situation properly.
How can I guard my application against this unintended usage?
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 got a spring application set up with spring security. I've got my service methods annotated with #PreAuthorize(...). So everyone from the web needs some specific rights to access those methods, which is fine.
But now I've got a new use case. There's a #Scheduled method running to do some checks and send messages. Currently only people with ROLE_USER are allowed to send messages. But now also the application itself has to send those messages.
How should I manage to have some kind of invisible user (= the application), which is logged in all the time and has specific rights? Or maybe "all rights" would be nice as well, so it just ignores all those security annotations.
Or maybe I don't need a "user" at all?
Thanks for your help!
EDIT: The main 2 questions are:
Should I create a real user for the application? Means: An entry in the user table of the database? How did you solve this? Maybe you do simply use the user account of the admin user (which is a real person)?
If I now have this "system" user. What's the best way to "use" it? For example I'd use #Autowired User systemUser to access this user wherever I need it. (Of course there's some point in the application config where I create a bean with this specific user).
EDIT2: Some more thoughts:
I think in the future I want to send messages from different subsystems of the application. So it's no choice to use the admin user, because I need a few different users with different names.
I was faced with similar problem and the solution I implemented was an internal and an "external" service implementation. The external one has the internal one autowired in. Any application-internal component, like your scheduled job, would have the internal service wired in. Any Web-exposed components would have the secured "external" service wired in, which would have the #PreAuthorize etc. annotations in place, but otherwise would act just as a delegate to the internal service.
I also log, before passing message onto the internal service, the principal of the authentication object which was used for authorization. You know you'll have one available in the SecurityContext, so pick it out and just make a note in your logs of someone external invoking internal services. I do the below (your principal could be non-username, but still, wanted to share):
final String currentUser = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
I think that all the answers you provided are fairly common solutions, so it depends very much on your requirements. The app I'm working on has some intense audit requirements so we have a user set up for the application itself to use when it needs to invoke services through a scheduler. This allows us to log against a given principle. Perhaps you should clarify your requirements?
I am developing a feature in my app where I need to store the state of a particular series of actions between 2 users, just like an ajax based chat service.
The scenario is as follows:
A user can is able to see which other users are online and then challenge one of them. The other user receives the challenge and accepts it. Now both the users are given 5 questions each and the match starts simultaneously for them (almost simultaneously) Then as a user navigates thru the question or solves it, the state is updated on the other user screen as well.
Essentially this is very similar to a chat system like say facebook chat. I am able to see who all are online. I send a chat msg to my friend who can then respond to that and that response is seen on my chat window.
I believe all this can be achieved by using ajax. I can easily make ajax calls to .asmx webservices and retrieve objects for a particular user as Session can be accessed there. However, I am wondering where to maintain state because session is for a particular user and I want my particular object to be accessible for two particular users.
Where do I store the state? Or taking the example of Ajax based chat, where should I store what message User1 entered and when Uer1 entered how is it shown to user2?
I was thinking application object but read it is not recmmended.
What do you recommend for such a thing?
If you're trying to do "near real-time" message passing you might want to take a look at HTTP polling (a.k.a. long polling). I won't use SQL for temporal message passing and short-term state transitions like I've seen in the past. If running on a single web server just keep the state in session or in the ASP.NET Cache. If running on multiple web servers take a look at distributed caches like memcached, Velocity (Win 2008), or NCache. Then serve the cached data to the AJAX requests which are sitting and waiting (because of long-polling). The key design issue is the design of the cache keys (no pun intended), which would need to include the user's ID for user-specific event data.
P.S. There are frameworks for large-scale, near real-time message distribution that solve scaling issues which are hit when hundreds of clients are participating in long-polling at the same time. The broad name for those frameworks are 'Comet', and they are most useful when broadcasting the same messages to many clients.