I know how to retrieve user details if he is logged on, using SecurityContextHolder.
// Some code
UserDetails userDetails =
(UserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
So, my question is:
Is it possible to retrieve information about not currently logged user, for example by User Id only?
And how can I update the information about users if they are currently offline?
The one populating your SecurityContext is usually a UserDetailsService, which you have to implement yourself or you take one of the existing ones.
I'm not sure I fully understand your question, but in theory you can simply use your UserDetailsService (or the services it itself uses to load a user), to get all the details you want. So, if you have a JPAUserDetailsService, this will likely call a repository and there's nothing stopping you from using that repository yourself.
What exactly is it that you are trying to do?
Related
I need to implement a PasswordEncoder that generates salted passwords. The salts are user-specific (UUIDs) and stored in the corresponding User objects.
As such, I need access to either the User directly or the UserDetails object that holds a reference. Very easy to retrieve IF I had the name of the user trying to log in.
And therein lies the issue. I cannot seem to get a hold of it.
As far as the SecurityContext is concerned, we are still dealing with an anonymousUser.
I know there should be a UsernamePasswordAuthenticationToken lying around, somewhere, but I cannot inject that as it's not a bean. And to define a wrapper bean holding it, I would need to figure out where to find it in the first place.
How do I get the name of the user trying to log in?
Would greatly appreciate the help. :)
(Sidenote: Please don't recommend me to "not do that" or to migrate the passwords and start using a BCryptPasswordEncoder or something along these lines. It's something we would very much like to do at some point in the future but for the time being are not allowed to.)
You won't be able to do this with a PasswordEncoder alone as the abstraction assumes that you can encode the password using only the plain text password (or compare using the hashed password). However, if you use a custom AuthenticationProvider (which is what calls the PasswordEncoder), you will have access to the incoming Authentication object including the username. More info here.
The call to PasswordEncoder.matches(...) is made by the additionalAuthenticationChecks(...) method of DaoAuthenticationProvider, which does have access to the username value (principal).
If you need access to that, you need to subclass DaoAuthenticationProvider and override (replace) the method, and make sure Spring uses your subclass when configuring.
The title tries to explain the scenario:
This customer has a login functionality that allows users with the same name but on different locations (stores).
At the login page the user informs userName, password and the required store.
Using Spring Security (with JPA) I created an UserDetailsService implementation but this interface always receive an userName (and the store was essential to differ from another users).
Giving this situation I have two questions:
How do I inform the spring security about the additional field? (store)
How do I implement an UserDetailsService with this info?
Is that even possible? I've been doing some research but the solutions weren't clear.
Thank you guys, you are the best =D
Your question is not all clear to me. Do you have a unique login for multiple stores? Then you don't need to give the store to your UserDetailsService implementation. I would simply load the user information using its username and if the users are not authorized for all the stores, you could use the GrantedAuthority to define where the users is authorized, e.g. ROLE_STORE_ID1, ROLE_STORE_ID2, etc.
If you have multiple stores where users are not shared, then you could simply create a configurable custom implementation of UserDetailsService, instantiate one per store and uses the correct instance depending on the store the user is accessing.
I hope this will help.
How do I conditionally serve different JSON objects from a Spring (3.1) backend? I am using Spring Security but I don't understand how I can serve different representations of an object?
I am only interested in the security logic, the other things I already have in place.
If a user named Sylvester is logged in with the role admin then he will recieve a bigger JSON object (more data) then a Arnold with the role user.
Do I have to use the authentication object see if the user has a particular role? Or are there some annotations or some other magic to do this?
In your logic you need to check current loggedIn user's role, and based on role you can return different response.
Yes you need authentication object, that must be implementing UserDetails interface and should have basic user info including its role/privileges.
This post seems to duplicate this question for the major part. Have a look at it and more precisely at this blog post, which gives a nice solution, but you will probably have to include or adapt 3rd-party code.
I'm learning Spring Security and I have few quick questions respect UserDetailsService:
1- When loadUserByUsername is actually called or invoked? After authentication? Only once per login?
2- After login, will Spring put the actual logged user into httpSession?
3- Which is the recommended way to populate the collection of <GrantedAuthority> of UserDetails?
Eagle fetch them so when loadUserByUsername is called, the returned user already has it's "ROLES"
Implement another custom filter like UsernamePasswordAuthenticationFilter populate after success login?
Neither of aboveā¦
It is typically called by an AuthenticationProvider instance in order to authenticate a user. For example, when a username and password is submitted, a UserdetailsService is called to find the password for that user to see if it is correct. It will also typically provide some other information about the user, such as the authorities and any custom fields you may want to access for a logged in user (email, for instance). That is the main usage pattern. You can grep the code to see exactly where it is called.
As explained in the manual:
There is often some confusion about UserDetailsService. It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework. In particular, it does not authenticate the user, which is done by the AuthenticationManager. In many cases it makes more sense to implement AuthenticationProvider directly if you require a custom authentication process.
Yes. A SecurityContext instance is stored in the session once the user has been authenticated.
If you need to implement a custom UserDetailsService then it will depend on your requirements and how they are stored. Typically you would load them at the same time as the other user information. It's not something you would likely do in a filter. As explained in the above quotation from the manual, if you are actually implementing a different authentication mechanism then you should implement AuthenticationProvider directly. It isn't compulsory to have a UserDetailsService in your app. You can think of it as a strategy that is used by certain built-in features.
I have a three-part question related to JBoss 5 Authentication (in the Web/EJB containers):
Is there a way to propogate an
identity other than the username
that was specified during login? For
example, using the
DatabaseServerLoginModule, I want to
authenticate the user with a
username/password but return the
user's id, and not username, when
ejbContext.getCallerPrincipal() or
httpRequest.getUserPrincipal() is
called.
Even better, I want to make a custom
login module which returns a User
object (probably an entity which was
loaded from the database). However,
even if I wrap that User object up
nicely in a Principal subclass in my
login module, the EJB-layer never
gets that object. Instead, the
EJB-layer always gets a
SimplePrincipal when
getCallerPrincipal is called.
I want to be able to trigger a login
programmatically, as described in
WebAuthentication. However, I need
to do this without knowing the
password. Imagine a customer service
interface where a customer service
agent can login to the application
as an end-user. They would click a
"login-as" button and we should be
able to programmatically log them in
as a user, without ever knowing the
user's password (the customer
service agent is already
authenticated himself). You could
also have this same scenario with
"forgot password" which uses an
alternate login mechanism to
authenticate the user and then
programatically logs them in.
Thanks!
1) Not that familiar with the DatabaseServerLoginModule but shouldn't the user's id also be their username? Usernames should be unique at least?
(Well after reading the rest of your question maybe this is not helpful...)
Answering my own question from two years ago: since the time I wrote this question, we've switched over to Spring Security and found it to be much more flexible than what's available in JBoss alone. My recommendation to anyone looking for a real solution to this problem is to give up on the container-provided authentication and take a good look at Spring Security.