Thymeleaf get current logged in username as String - spring

I am new to Thymeleaf and currently working on a user management tool with Springboot. First of all the account need to be logged in to see the personal data. My problem is, to get the current logged in username, which is an email in my case and call the Rest-API with the url "/{email}" with Getmapping?
My idea was to Get the securitycontextholder.getcontext().getprincipal() and pass it to a Request call . Finally display the data
this is my GetMappping from the controller layer
#GetMapping("/{email}")
public ResponseEntity getApplicantByEmail(#PathVariable String email){
return new ResponseEntity(applicantService.getApplicantByEmail(email), HttpStatus.OK);
}

You can make the current user available to the Thymeleaf model by introducing #ControllerAdvice:
#ControllerAdvice
public class CurrentUserAdvice {
#ModelAttribute("currentEmailAddress")
public String emailAddress(Authentication authentication) {
return authentication.getName();
}
}
This will make the model attribute currentEmailAddress available in Thymeleaf templates.
If you have a custom domain object as the principal in Authentication, you can make the entire user available in the model using the same pattern:
#ControllerAdvice
public class CurrentUserAdvice {
#ModelAttribute("currentUser")
public MyUser user(#AuthenticationPrincipal MyUser user) {
return user;
}
}

Related

Spring Security - How to get authenticated object in non-secure and secure pages?

I have a Spring-boot/Thymeleaf application with two ends point:
1: /int/: requires sso/authorization;
2. /ext/: public pages, everyone can access;
Using a PreAuthenticationFilter, I was able to secure /int/* pages. When an user tries to access the /ext/* pages, I'd like to be able to tell in the controller if the user has previously been authenticated (by accessing a secured page). Currently I save the authenticated Principal object in the HTTP session in UserDetailsService's loadUserDetails(). Just curious if this is the right way (or a better way) to do it.
You can get your authenticated object via #AuthenticationPrincipal annotation instead of getting the object from httpsession and casting it back to your object for every controller method.
Let me give you an example, given login page is a public page and User object as below:
User Class:
public class User implement UserDetails {
String contact;
Integer age;
}
Controller:
#GetMapping(value = "/login")
ModelAndView login(#AuthenticationPrincipal User user) {
if (user == null) {
return new ModelAndView("/login");
} else {
return new ModelAndView(new RedirectView("/home"));
}
}

Accessing UserDetails object from controller in Spring using Spring security [duplicate]

This question already has answers here:
How to get active user's UserDetails
(9 answers)
Closed 5 years ago.
I would like to access some user details from session. I am using spring security and custom authentication by overriding loadUserByUsername(String username) method.
I am returning a user and would like to access it from within my controller. I tried the principal object but i can not reach to the companyId field of my ESecurityUser object.
Any help would be appreciated..
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
ESecurityUser user = new ESecurityUser();
user.setUsername("hello");
user.setPassword("world");
user.setCompanyId(199);
Set<EAuthority> authorities = new HashSet<EAuthority>();
EAuthority authority = new EAuthority();
authority.setAuthority("ROLE_ADMIN");
authorities.add(authority);
user.setAuthorities(authorities);;
return user;
}
Sample Controller Code
#RequestMapping("")
public String toPeriodicAdReport(#ModelAttribute("advertFormHelper") AdvertFormHelper advertFormHelper,
Model model,Principal principal) {
//What to write here so that i can access to authenticated user`s companyId field..
return "Test";
}
You can use the annotation #AuthenticationPrincipal to directly access ESecurityUser.
#RequestMapping("")
public String toPeriodicAdReport(#ModelAttribute("advertFormHelper") AdvertFormHelper advertFormHelper,
Model model, #AuthenticationPrincipal ESecurityUser principal) {
principal.getCompanyId();
return "Test";
}
You were not far...
The Principal that the SpringMVC machinery passed to a controller method is the Authentication token that identifies the user. You must use its getDetails() method to extract the ESecurityUser that you returned from your loadUserByUsername
Your code could become:
#RequestMapping("")
public String toPeriodicAdReport(#ModelAttribute("advertFormHelper") AdvertFormHelper advertFormHelper,
Model model,Principal principal) {
ESecurityUser user = (ESecurityUser) ((Authentication) principal).getDetails();
// stuff...
return "Test";
}
ESecurityUser e = (ESecurityUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
This is working for me..

How to retrive logged in user data in spring mvc and hibernate

I need to get current loggedin user's details along entertain session.Is there any poissible to do it in Spring and hibernate
I am new to spring and hibernate...Help me guys.
There are serveral ways in which you can accomplish this. In a controller you can inject a Pricipal as a parameter.
#RequestMapping()
public void getPricipal(Principal principal) {
Customer c = (Customer) pricipal;
}
You should also be able to inject the UserDetails directly as well. Spring will resolve it for you. Your Customer class must implement UserDetails
#RequestMapping()
public void getPricipal(Customer customer) {
}
As for having all details, you should be able to access the firstname, lastname etc, if you've implemented your own UserDetailsService where you return your custom UserDetails (Customer).

Spring Session: Update Logged in user object in redis immediately

I have two web applications (A and B).
The first web application (A) is used as a reverse proxy using spring-cloud.
I'm using spring-session to store the sessions in a redis database for both applications.
The problem
When I modify a field (e.g name) of the current (logged in) user, the current logged in user object is not updated immediately and as a result, when I'm trying to retrieve current logged in user in a next call (via #AuthenticationPrincipal) I get a non-updated user object.
My custom user details object:
public class CustomUserDetails extends my.package.User implements org.springframework.security.core.userdetails.UserDetails, java.io.Serializable {
// ...
}
How can I update the current user object immediately?
Recently I've had the similar issue and I resolved it in the following manner:
1.Created a custom Authentication class
public class MyCustomAuthentication implements Authentication {
private UserDetails userDetails;
public MyCustomAuthentication(UserDetails userDetails) {
this.userDetails = userDetails;
}
...
#Override
public Object getDetails() { return userDetails; }
#Override
public Object getPrincipal() { return userDetails; }
#Override
public boolean isAuthenticated() { return true; }
...
}
update userDetails object with some fresh data (I guess, 'name' in your case)
Set new authentication created from userDetails in SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(new MyCustomAuthentication(userDetails));
Hope you will find that helpful.

How to integrate spring security and spring social to have the same execution flow in both cases?

I am using spring security for the authentication purposes in my project wherein after successful authentication, I get the principal object inside which the various details are stored.
This principal object is passed to various methods which allow the entries to be reflected in the database against the current user. In short, principal helps me in giving principal.getName() everywhere i need it.
But now when I login through spring social then I do not have principal object of Principal in hand, instead I have implemented MyPrincipal class --->
public class MyPrincipal implements Principal {
public String name;
public boolean flag;
public boolean isflag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public void setName(String name) {
this.name = name;
}
#Override
public String getName() {
return name;
}
}
Then in the social login handler, I am adding the current username and flag value to myPrincipal object, and forwarding the user to the same home page where the spring security forwards in case of normal login.
MyPrincipal myPrincipal = new MyPrincipal();
myPrincipal.name = username;
myPrincipal.socialFlag = true;
modelMap.addAttribute("myPrincipal", myPrincipal);
return new ModelAndView("forward:/home");
Adding this object in session by annotating class with
#SessionAttributes({"myPrincipal"})
Now from here on-wards I want the flow to be handed over to the home page with all the functionality working for the user correctly. But each method is taking Principal principal as argument, just like this -->
#RequestMapping(value = {"/home"}, method = RequestMethod.POST)
#ResponseBody
public ModelAndView test(ModelMap modelMap, Principal principal) {
String name = principal.getName();
}
There are two different things going around in both cases-
Normal login is giving me principal directly but social login is giving me it in session attributes.
I do not want to pass principal as parameters even in case of normal spring security login, instead here also I want to put it in session attribute.
How can I do this and where to make the changes when I have implemented my own authentication provider.
I don't think I fully understand...However, in general it shouldn't be necessary to pass principal instances around. Use org.springframework.security.core.context.SecurityContextHolder.getContext() to get a hold of the context then call SecurityContext.getAuthentication().getPrincipal() or SecurityContext.getAuthentication().getDetails().

Resources