我确切地说,我是一个法国学生在第一年的Java开发。
我正在开发一个多模块应用程序,使用:Sping Boot 、Spring安全、Hibernate、Spring Data 、Spring MVC和Thymeleaf。
我想在会话中设置用户,或者至少在登录时设置userId。这样我就不必在每次需要时都手动将其放入会话或模型中。
但是由于我使用了缺省的SpringSecurity登录和身份验证配置,我真的不知道如何或在哪里调用这样一个方法:
void putUserInHttpSession( HttpSession httpSession ) {
httpSession.setAttribute( "user" , getManagerFactory().getUserManager().findByUserName( SecurityContextHolder.getContext().getAuthentication().getName()) );
}
我可以做它eahc的时候,我需要它,但我发现它相当丑陋,不只是这样做,在登录!
以下是我认为你可能需要帮助我的东西(那将是太棒了!!!:)
我的Web安全配置类:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Setting Service to find User in the database.
// And Setting PassswordEncoder
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.csrf().disable();
// /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers(
"/user/**")
.access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers(
"/admin/**")
.access("hasRole('ROLE_ADMIN')");
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/public/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/public/login").defaultSuccessUrl("/public/showAtlas")//
.failureUrl("/public/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
//Config for Logout Page
.and()
.logout().logoutUrl("/public/logout").logoutSuccessUrl("/public/logoutSuccessful");
http.authorizeRequests().antMatchers(
"/public/**").permitAll();
// The pages does not require login
}
}
我的用户详细信息服务实现类:
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private ManagerFactory managerFactory;
// private HttpSession httpSession;
/**
* The authentication method uses the user email, since it is easier to remember for most users
* @param input
* @return a UserDetails object
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername( String input) throws UsernameNotFoundException {
User user = new User();
if( input.contains( "@" )){
user = this.managerFactory.getUserManager().findByEmail( input );
}
else {
user = this.managerFactory.getUserManager().findByUserName( input );
}
if (user == null) {
throw new UsernameNotFoundException( "User with email " + input + " was not found in the database" );
}
// [ROLE_USER, ROLE_ADMIN,..]
List<String> roleNames = this.managerFactory.getRoleManager().findRoleByUserName(user.getUserName());
List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>();
if (roleNames != null) {
for (String role : roleNames) {
// ROLE_USER, ROLE_ADMIN,..
GrantedAuthority authority = new SimpleGrantedAuthority(role);
grantList.add(authority);
}
}
return (UserDetails) new org.springframework.security.core.userdetails.User(user.getUserName(),
user.getPassword(), grantList);
}
}
我的简单登录控制器:
@Controller
public class LoginController{
@GetMapping("/public/login")
public String login(Model model ){
return "view/login";
}
@GetMapping("/public/logoutSuccessful")
public String logout(Model model) {
return "view/logoutSuccessful";
}
那么,有没有一种简单的方法可以在登录时将user或userId放入httpSession中呢?
非常感谢你们!
解决方案
创建自定义验证成功处理程序
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private ManagerFactory managerFactory;
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
String userName = "";
HttpSession session = request.getSession();
Collection< GrantedAuthority > authorities = null;
if(authentication.getPrincipal() instanceof Principal ) {
userName = ((Principal)authentication.getPrincipal()).getName();
session.setAttribute("role", "none");
}else {
User userSpringSecu = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
session.setAttribute("role", String.valueOf( userSpringSecu.getAuthorities()));
session.setAttribute( "connectedUser" , managerFactory.getUserManager().findByUserName( userSpringSecu.getUsername() ) );
}
response.sendRedirect("/public/showAtlas" );
}
}
然后自动连接此类并将其添加到WebSecurityConfigurerAdapter中
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Setting Service to find User in the database.
// And Setting PassswordEncoder
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.csrf().disable();
// /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers(
"/user/**")
.access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers(
"/admin/**")
.access("hasRole('ROLE_ADMIN')");
// http.exceptionHandling().accessDeniedPage( "/error/403" );
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/public/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/public/login")
.defaultSuccessUrl("/public/showAtlas")//
.successHandler( customAuthenticationSuccessHandler )
.failureUrl("/public/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
//Config for Logout Page
.and()
.logout().logoutUrl("/public/logout").logoutSuccessUrl("/public/logoutSuccessful");
http.authorizeRequests().antMatchers(
"/public/**").permitAll();
// The pages does not require login
}
}
2条答案
按热度按时间rhfm7lfc1#
假设您希望在成功登录时将用户添加到会话中,您可以创建如下所示的
AuthenticationSuccessHandler
并使用successHandler(new AuthenticationSuccessHandlerImpl())
进行注册**更新:**如果我们创建对象
AuthenticationSuccessHandlerImpl
,它将不会被spring管理,因此autowire
将被添加到您的Securityconfig
中,并如下所示使用它。在这里,将
AuthenticationSuccessHandler
自动连接到您的WebSecurityConfig
并使用它Web安全配置.java
AuthenticationSuccessHandlerImpl.java
希望这对你有帮助。
v64noz0r2#
让我补充以上两个解决方案。我的经验表明,以下语句引发了以下异常:
例外情况:
在研究了Using a request scoped bean outside of an actual web request之后,我能够删除它。也就是说,我已经覆盖了类中的onStartup方法,该方法扩展了AbstractAnnotationConfigDispatcherServletInitializer类。