I have a spring boot application with WebSecurityConfigurerAdapter configured like this -
http.csrf().disable()
.exceptionHandling()
In the accepted answer you need two calls to get the data you want. Simply return the data after the login in a custom AjaxAuthenticationSuccessHandler like this.
@Bean
public AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler() {
return new AjaxAuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.getWriter().write(new ObjectMapper().writeValueAsString(new UserAuthenticationResponse(authentication.getName(), 123l)));
response.setStatus(200);
}
};
}
and register the successhandler:
http.successHandler(ajaxAuthenticationSuccessHandler())
If I understand your problem right, I can suggest next way.
First of all you have to implement class, that will contain user information. This class must be inherited from org.springframework.security.core.userdetails.User
:
public class CustomUserDetails extends User {
public CustomUserDetails(String username, String password,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
//for example lets add some person data
private String firstName;
private String lastName;
//getters and setters
}
Next step, you have create you own implementation of interface org.springframework.security.core.userdetails.UserDetailsService
:
@Service
public class CustomUserDetailService implements UserDetailsService{
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException{
if(StringUtils.isEmpty(userName))
throw new UsernameNotFoundException("User name is empty");
//if you don't use authority based security, just add empty set
Set<GrantedAuthority> authorities = new HashSet<>();
CustomUserDetails userDetails = new CustomUserDetails(userName, "", authorities);
//here you can load user's data from DB or from
//any other source and do:
//userDetails.setFirstName(firstName);
//userDetails.setLastName(lastName);
return userDetails;
}
}
As you see, this class has just one method, where you can load and set custom user details. Note, that I marked this class with @Service
annotation. But you can register it in your Java-config or XML context.
Now, to access your user data after successful authentication, you can use next approach, when Spring will automatically pass principal in controller's method:
@Controller
public class MyController{
@RequestMapping("/mapping")
public String myMethod(Principal principal, ModelMap model){
CustomUserDetails userDetails = (CustomUserDetails)principal;
model.addAttribute("firstName", userDetails.getFirstName());
model.addAttribute("lastName", userDetails.getLastName());
}
}
Or another one way:
@Controller
public class MyController{
@RequestMapping("/mapping")
public String myMethod(ModelMap model){
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
CustomUserDetails userDetails = (CustomUserDetails)auth.getPrincipal();
model.addAttribute("firstName", userDetails.getFirstName());
model.addAttribute("lastName", userDetails.getLastName());
}
}
This method can be used in other places, where Spring does not pass principal automatically.
To go to specific address after successful authentication you can use SimpleUrlAuthenticationSuccessHandler
. Just create it in your config:
@Bean
public SavedRequestAwareAuthenticationSuccessHandler successHandler() {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("/succeslogin");
return successHandler;
}
and use it in your configuration:
http.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.usernameParameter("email")
.passwordParameter("pass")
.successHandler(successHandler())
after that you can create controller, that will send response from speciafied url:
@Controller
@RequestMapping("/sucesslogin")
public class SuccessLoginController{
@RequestMapping(method = RequestMethod.POST)
public String index(ModelMap model, Principal principal){
//here you can return view with response
}
}
Of cause, you can return not only view, but JSON response (using @ResponseBody
annotation), or something else, depends on you front-end.
Hope this will be helpful.