Spring Boot-登录后返回用户对象 [英] Spring boot - return user object after log in
问题描述
我有一个配置为这样的WebSecurityConfigurerAdapter的spring boot应用程序-
http.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/user/*", "/habbit/*").authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.usernameParameter("email")
.passwordParameter("pass")
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.invalidateHttpSession(true);
我是否可以添加类似我自己的控制器的内容,以便在成功通过身份验证后返回自定义对象,其中包含有关已身份验证用户的一些详细信息?
更新: 为了清楚起见,我使用一个有角度的应用程序作为客户端. 目前,我需要从客户端向服务器发出2个请求: 1.向/login URL发出POST请求以进行身份验证. 2. GET请求以检索经过身份验证的用户数据.
我的目标是让第一个请求返回给我用户信息,因此我不必发出第二个DNS请求. 当前,第一个请求仅对用户进行身份验证,在服务器上创建会话,并发回带有无数据的"200 OK"状态响应.我希望它返回有关登录用户的成功数据.
回答:
正确答案在注释中,因此我将在此处写下: 我需要从successHandler重定向到控制器,控制器又返回当前登录的用户信息(在我的情况下,控制器位于url'/user/me'中:
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
clearAuthenticationAttributes(request);
getRedirectStrategy().sendRedirect(request, response, "/user/me");
}
如果我正确地理解了您的问题,我可以建议采取另一种方法.
首先,您必须实现类,其中将包含用户信息.此类必须从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
}
下一步,您已经创建了自己的接口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;
}
}
如您所见,此类只有一个方法,您可以在其中加载和设置自定义用户详细信息.请注意,我用@Service
批注标记了该类.但是您可以在Java-config或XML上下文中注册它.
现在,要在成功通过身份验证后访问用户数据,可以使用下一种方法,当Spring将在控制器的方法中自动传递主体时:
@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());
}
}
或另一种方式:
@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());
}
}
该方法可以在Spring无法自动通过主体的其他地方使用.
要在成功通过身份验证后转到特定地址,可以使用SimpleUrlAuthenticationSuccessHandler
.只需在您的配置中创建它即可:
@Bean
public SavedRequestAwareAuthenticationSuccessHandler successHandler() {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("/succeslogin");
return successHandler;
}
并在您的配置中使用它:
http.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.usernameParameter("email")
.passwordParameter("pass")
.successHandler(successHandler())
之后,您可以创建控制器,该控制器将从指定的网址发送响应:
@Controller
@RequestMapping("/sucesslogin")
public class SuccessLoginController{
@RequestMapping(method = RequestMethod.POST)
public String index(ModelMap model, Principal principal){
//here you can return view with response
}
}
当然,您不仅可以返回视图,而且还可以返回JSON响应(使用@ResponseBody
注释)或其他方式,这取决于您的前端.
希望这会有所帮助.
I have a spring boot application with WebSecurityConfigurerAdapter configured like this -
http.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/user/*", "/habbit/*").authenticated()
.and()
.formLogin()
.loginProcessingUrl("/login")
.permitAll()
.usernameParameter("email")
.passwordParameter("pass")
.successHandler(authenticationSuccessHandler)
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout()
.logoutUrl("/logout")
.invalidateHttpSession(true);
Can I add something like my own controller that would, after successful authentication, return back a custom object with some details about the authenticated user?
Update: To clarity, i'm using an angular application as the client. Currently I need to make 2 requests form my client to the server: 1. POST request to /login URL for authentication. 2. GET request to retrieve authenticated user data.
My aim is to have the 1st request return to me user information so I don't have to make the 2dn request. Currently the 1st request only authenticates the user, creates a session on the server and send back a '200 OK' status response with no data. I want it to return a success response with data about the logged in user.
Answered:
The correct answer is in comments so i will write it here: I needed to redirect from my successHandler to my controller which in turn returns the currently logged in user info ( in my case controller is in url '/user/me':
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws ServletException, IOException {
clearAuthenticationAttributes(request);
getRedirectStrategy().sendRedirect(request, response, "/user/me");
}
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.
这篇关于Spring Boot-登录后返回用户对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!