Spring启动 - 登录后返回用户对象

Tom*_*mas 10 spring spring-security spring-boot

我有一个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);
Run Code Online (Sandbox Code Playgroud)

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

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

我的目标是让第一个请求返回给我用户信息,所以我不必提出2dn请求.目前,第一个请求仅对用户进行身份验证,在服务器上创建会话并发送回没有数据的"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");
    }
Run Code Online (Sandbox Code Playgroud)

Ken*_*kov 10

如果我理解你的问题,我可以建议下一步.

首先,您必须实现包含用户信息的类.该类必须继承自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
}
Run Code Online (Sandbox Code Playgroud)

下一步,您已创建自己的接口实现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;
    }

}
Run Code Online (Sandbox Code Playgroud)

如您所见,此类只有一种方法,您可以在其中加载和设置自定义用户详细信息.注意,我用@Service注释标记了这个类.但您可以在Java-config或XML上下文中注册它.

现在,要在成功验证后访问您的用户数据,您可以使用下一种方法,当Spring将自动在控制器的方法中传递principal:

@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

或另一种方式:

@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());
    }
}
Run Code Online (Sandbox Code Playgroud)

此方法可以在其他地方使用,其中Spring不会自动传递主体.

要在成功验证后转到特定地址,您可以使用SimpleUrlAuthenticationSuccessHandler.只需在您的配置中创建它:

@Bean
public SavedRequestAwareAuthenticationSuccessHandler successHandler() {
    SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
    successHandler.setTargetUrlParameter("/succeslogin");
    return successHandler;
}
Run Code Online (Sandbox Code Playgroud)

并在您的配置中使用它:

http.formLogin()
    .loginProcessingUrl("/login")
    .permitAll()
    .usernameParameter("email")
    .passwordParameter("pass")
    .successHandler(successHandler())
Run Code Online (Sandbox Code Playgroud)

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

}
Run Code Online (Sandbox Code Playgroud)

原因是,您不仅可以返回视图,还可以返回JSON响应(使用@ResponseBody注释)或其他内容,这取决于您的前端.希望这会有所帮助.


Sim*_*wig 8

在接受的答案中,您需要两次调用才能获取所需的数据。像这样在自定义 AjaxAuthenticationSuccessHandler 中简单地在登录后返回数据。

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

    };
}
Run Code Online (Sandbox Code Playgroud)

并注册成功处理程序:

http.successHandler(ajaxAuthenticationSuccessHandler())
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

12800 次

最近记录:

9 年 前