Spring boot - 登录后返回用户对象

2024-01-24

我有一个 Spring Boot 应用程序,其 WebSecurityConfigurerAdapter 配置如下 -

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);

我是否可以添加类似我自己的控制器的东西,在成功进行身份验证后,返回一个自定义对象,其中包含有关经过身份验证的用户的一些详细信息?

Update:为了清楚起见,我使用角度应用程序作为客户端。 目前我需要从客户端向服务器发出 2 个请求: 1. POST 请求到 /login URL 进行身份验证。 2. GET 请求检索经过身份验证的用户数据。

我的目标是让第一个请求返回给我用户信息,这样我就不必发出第二个请求。 目前,第一个请求仅对用户进行身份验证,在服务器上创建会话并发回“200 OK”状态响应no data。我希望它返回成功响应有数据关于登录用户。

回答:

正确答案在评论中,所以我将其写在这里: 我需要从 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 配置或 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不自动传递principal的地方。

要在身份验证成功后转到特定地址,您可以使用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())

之后您可以创建控制器,它将从指定的 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
     }

}

当然,您不仅可以返回视图,还可以返回 JSON 响应(使用@ResponseBody注解),或者其他什么,取决于你的前端。 希望这会有所帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring boot - 登录后返回用户对象 的相关文章

随机推荐