我在Spring的上下文中有这个监听器:
package listeners;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.stereotype.Component;
import services.UserService;
import services.security.CustomUserDetails;
/**
*
* @author sergio
*/
@Component
public class AuthenticationSuccessEventHandler{
private static Logger logger = LoggerFactory.getLogger(AuthenticationSuccessEventHandler.class);
@Autowired
private UserService userService;
@EventListener({AuthenticationSuccessEvent.class, InteractiveAuthenticationSuccessEvent.class})
public void processAuthenticationSuccessEvent(AbstractAuthenticationEvent e) {
logger.info("Autenticación realizada ....");
// Actualizamos la útltima fecha de acceso
String username = ((CustomUserDetails) e.getAuthentication().getPrincipal()).getUsername();
logger.info("Actualizando último acceso para user: " + username);
userService.updateLastLoginAccess(username, new Date());
}
}
根据Spring调试消息,这在上下文中成功创建。
DEBUG DefaultListableBeanFactory:448 - Creating instance of bean 'authenticationSuccessEventHandler'
2016-12-11 11:33:29 DEBUG InjectionMetadata:72 - Registered injected element on class [listeners.AuthenticationSuccessEventHandler]: AutowiredFieldElement for private services.UserService listeners.AuthenticationSuccessEventHandler.userService
当我在应用程序中正确进行身份验证时,Spring Security不会发布任何事件,因此不会调用此事件侦听器。
我的Spring Security配置就是这个
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/signup").anonymous()
.antMatchers("/admin/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/admin/login").permitAll()
.usernameParameter("username").passwordParameter("password")
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout"))
.logoutSuccessUrl("/admin/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
}
SecurityWebApplicationInitializer
package config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
/**
*
* @author sergio
*/
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
我正在使用 Spring Security 4.2.0.RELEASE。
答案 0 :(得分:10)
您可能需要注册事件发布基础结构(例如,通过配置DefaultAuthenticationEventPublisher)。
@Configuration
@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
...
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationEventPublisher(authenticationEventPublisher())
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public DefaultAuthenticationEventPublisher authenticationEventPublisher() {
return new DefaultAuthenticationEventPublisher();
}
}
答案 1 :(得分:0)
这就是我实现它的方式。
1)在您的Application类中,公开您的应用程序侦听器,如
@Bean
public ApplicationListener applicationListener(){
return new AuthSuccessApplicationListener();
}
2)例如实现AuthSuccessApplicationListener
public class AuthSuccessApplicationListener implements
ApplicationListener<InteractiveAuthenticationSuccessEvent>{
@Autowired(required=false)
HttpSession httpSession;
@Autowired
Environment env;
/**
* Handle an application event.
*
* @param appEvent the event to respond to
*/
@Override
public void onApplicationEvent(InteractiveAuthenticationSuccessEvent appEvent) {
if (appEvent!=null) {
LdapUserDetailsImpl ldapUserDetailsImpl = (LdapUserDetailsImpl) appEvent.getAuthentication().getPrincipal();
try {
if (ldapUserDetailsImpl != null) {
logger.info("Session Created for " + ldapUserDetailsImpl.getUsername());
if (httpSession.getAttribute("adminUser") == null) {
// check user is admin and set into session
if (isAdminUser(ldapUserDetailsImpl.getUsername())) {
httpSession.setAttribute("adminUser", "ADMIN_USER");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>(auth.getAuthorities());
// Add the ROLE_ADMIN into Authorities
authorities.add(new SimpleGrantedAuthority(SecurityConfig.ADMIN));
// Create a new Authentication based on current principal and authorities and set into Security Context
Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(), auth.getCredentials(), authorities);
SecurityContextHolder.getContext().setAuthentication(newAuth);
}
}
}
} catch (Exception e) {
logger.error("Exception occurred : " + e.getMessage());
}
}
}