package com.mossle.security.util;
import java.net.InetAddress;
import java.util.Date;
import javax.annotation.Resource;
import com.mossle.api.audit.AuditConnector;
import com.mossle.api.audit.AuditDTO;
import com.mossle.core.auth.LoginEvent;
import com.mossle.security.impl.SpringSecurityUserAuth;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent;
import org.springframework.security.authentication.event.AuthenticationFailureCredentialsExpiredEvent;
import org.springframework.security.authentication.event.AuthenticationFailureDisabledEvent;
import org.springframework.security.authentication.event.AuthenticationFailureExpiredEvent;
import org.springframework.security.authentication.event.AuthenticationFailureLockedEvent;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
public class SpringSecurityListener implements ApplicationListener,
ApplicationContextAware {
private static Logger logger = LoggerFactory
.getLogger(SpringSecurityListener.class);
private AuditConnector auditConnector;
private ApplicationContext ctx;
public void onApplicationEvent(ApplicationEvent event) {
try {
if (event instanceof InteractiveAuthenticationSuccessEvent) {
this.logLoginSuccess(event);
}
if (event instanceof AuthenticationFailureBadCredentialsEvent) {
this.logBadCredential(event);
}
if (event instanceof AuthenticationFailureLockedEvent) {
this.logLocked(event);
}
if (event instanceof AuthenticationFailureDisabledEvent) {
this.logDisabled(event);
}
if (event instanceof AuthenticationFailureExpiredEvent) {
this.logAccountExpired(event);
}
if (event instanceof AuthenticationFailureCredentialsExpiredEvent) {
this.logCredentialExpired(event);
}
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
}
public void logLoginSuccess(ApplicationEvent event) throws Exception {
InteractiveAuthenticationSuccessEvent interactiveAuthenticationSuccessEvent = (InteractiveAuthenticationSuccessEvent) event;
Authentication authentication = interactiveAuthenticationSuccessEvent
.getAuthentication();
String tenantId = this.getTenantId(authentication);
Object principal = authentication.getPrincipal();
String userId = null;
if (principal instanceof SpringSecurityUserAuth) {
userId = ((SpringSecurityUserAuth) principal).getId();
} else {
userId = authentication.getName();
}
AuditDTO auditDto = new AuditDTO();
auditDto.setUserId(userId);
auditDto.setAuditTime(new Date());
auditDto.setAction("login");
auditDto.setResult("success");
auditDto.setApplication("lemon");
auditDto.setClient(getUserIp(authentication));
auditDto.setServer(InetAddress.getLocalHost().getHostAddress());
auditDto.setTenantId(tenantId);
auditConnector.log(auditDto);
// 登录成功,再发送一个消息,以后这里的功能都要改成listener,不用直接写接口了。解耦更好一些。
ctx.publishEvent(new LoginEvent(authentication, userId, this
.getSessionId(authentication), "success", "default", tenantId));
}
public void logBadCredential(ApplicationEvent event) throws Exception {
AuthenticationFailureBadCredentialsEvent authenticationFailureBadCredentialsEvent = (AuthenticationFailureBadCredentialsEvent) event;
Authentication authentication = authenticationFailureBadCredentialsEvent
.getAuthentication();
logger.info("{}", authentication);
String tenantId = this.getTenantId(authentication);
Object principal = authentication.getPrincipal();
String userId = null;
if (principal instanceof SpringSecurityUserAuth) {
userId = ((SpringSecurityUserAuth) principal).getId();
} else {
userId = authentication.getName();
}
AuditDTO auditDto = new AuditDTO();
auditDto.setUserId(userId);
auditDto.setAuditTime(new Date());
auditDto.setAction("login");
auditDto.setResult("failure");
auditDto.setApplication("lemon");
auditDto.setClient(getUserIp(authentication));
auditDto.setServer(InetAddress.getLocalHost().getHostAddress());
auditDto.setDescription(authenticationFailureBadCredentialsEvent
.getException().getMessage());
auditDto.setTenantId(tenantId);
auditConnector.log(auditDto);
ctx.publishEvent(new LoginEvent(authentication, userId, this
.getSessionId(authentication), "badCredentials", "default",
tenantId));
}
public void logLocked(ApplicationEvent event) throws Exception {
AuthenticationFailureLockedEvent authenticationFailureLockedEvent = (AuthenticationFailureLockedEvent) event;
Authentication authentication = authenticationFailureLockedEvent
.getAuthentication();
logger.info("{}", authentication);
String tenantId = this.getTenantId(authentication);
Object principal = authentication.getPrincipal();
String userId = null;
if (principal instanceof SpringSecurityUserAuth) {
userId = ((SpringSecurityUserAuth) principal).getId();
} else {
userId = authentication.getName();
}
AuditDTO auditDto = new AuditDTO();
auditDto.setUserId(userId);
auditDto.setAuditTime(new Date());
auditDto.setAction("login");
auditDto.setResult("failure");
auditDto.setApplication("lemon");
auditDto.setClient(getUserIp(authentication));
auditDto.setServer(InetAddress.getLocalHost().getHostAddress());
auditDto.setDescription(authenticationFailureLockedEvent.getException()
.getMessage());
auditDto.setTenantId(tenantId);
auditConnector.log(auditDto);
ctx.publishEvent(new LoginEvent(authentication, userId, this
.getSessionId(authentication), "locked", "default", tenantId));
}
public void logDisabled(ApplicationEvent event) throws Exception {
AuthenticationFailureDisabledEvent authenticationFailureDisabledEvent = (AuthenticationFailureDisabledEvent) event;
Authentication authentication = authenticationFailureDisabledEvent
.getAuthentication();
logger.info("{}", authentication);
String tenantId = this.getTenantId(authentication);
Object principal = authentication.getPrincipal();
String userId = null;
if (principal instanceof SpringSecurityUserAuth) {
userId = ((SpringSecurityUserAuth) principal).getId();
} else {
userId = authentication.getName();
}
AuditDTO auditDto = new AuditDTO();
auditDto.setUserId(userId);
auditDto.setAuditTime(new Date());
auditDto.setAction("login");
auditDto.setResult("failure");
auditDto.setApplication("lemon");
auditDto.setClient(getUserIp(authentication));
auditDto.setServer(InetAddress.getLocalHost().getHostAddress());
auditDto.setDescription(authenticationFailureDisabledEvent
.getException().getMessage());
auditDto.setTenantId(tenantId);
auditConnector.log(auditDto);
ctx.publishEvent(new LoginEvent(authentication, userId, this
.getSessionId(authentication), "disabled", "default", tenantId));
}
public void logCredentialExpired(ApplicationEvent event) throws Exception {
AuthenticationFailureCredentialsExpiredEvent authenticationFailureCredentialsExpiredEvent = (AuthenticationFailureCredentialsExpiredEvent) event;
Authentication authentication = authenticationFailureCredentialsExpiredEvent
.getAuthentication();
logger.info("{}", authentication);
String tenantId = this.getTenantId(authentication);
Object principal = authentication.getPrincipal();
String userId = null;
if (principal instanceof SpringSecurityUserAuth) {
userId = ((SpringSecurityUserAuth) principal).getId();
} else {
userId = authentication.getName();
}
AuditDTO auditDto = new AuditDTO();
auditDto.setUserId(userId);
auditDto.setAuditTime(new Date());
auditDto.setAction("login");
auditDto.setResult("failure");
auditDto.setApplication("lemon");
auditDto.setClient(getUserIp(authentication));
auditDto.setServer(InetAddress.getLocalHost().getHostAddress());
auditDto.setDescription(authenticationFailureCredentialsExpiredEvent
.getException().getMessage());
auditDto.setTenantId(tenantId);
auditConnector.log(auditDto);
ctx.publishEvent(new LoginEvent(authentication, userId, this
.getSessionId(authentication), "credentialExpired", "default",
tenantId));
}
public void logAccountExpired(ApplicationEvent event) throws Exception {
AuthenticationFailureExpiredEvent authenticationFailureExpiredEvent = (AuthenticationFailureExpiredEvent) event;
Authentication authentication = authenticationFailureExpiredEvent
.getAuthentication();
logger.info("{}", authentication);
String tenantId = this.getTenantId(authentication);
Object principal = authentication.getPrincipal();
String userId = null;
if (principal instanceof SpringSecurityUserAuth) {
userId = ((SpringSecurityUserAuth) principal).getId();
} else {
userId = authentication.getName();
}
AuditDTO auditDto = new AuditDTO();
auditDto.setUserId(userId);
auditDto.setAuditTime(new Date());
auditDto.setAction("login");
auditDto.setResult("failure");
auditDto.setApplication("lemon");
auditDto.setClient(getUserIp(authentication));
auditDto.setServer(InetAddress.getLocalHost().getHostAddress());
auditDto.setDescription(authenticationFailureExpiredEvent
.getException().getMessage());
auditDto.setTenantId(tenantId);
auditConnector.log(auditDto);
ctx.publishEvent(new LoginEvent(authentication, userId, this
.getSessionId(authentication), "accountExpired", "default",
tenantId));
}
// ~
public String getUserIp(Authentication authentication) {
if (authentication == null) {
return "";
}
Object details = authentication.getDetails();
if (!(details instanceof WebAuthenticationDetails)) {
return "";
}
WebAuthenticationDetails webDetails = (WebAuthenticationDetails) details;
return webDetails.getRemoteAddress();
}
public String getSessionId(Authentication authentication) {
if (authentication == null) {
return "";
}
Object details = authentication.getDetails();
if (!(details instanceof WebAuthenticationDetails)) {
return "";
}
WebAuthenticationDetails webDetails = (WebAuthenticationDetails) details;
return webDetails.getSessionId();
}
public String getTenantId(Authentication authentication) {
if (authentication == null) {
return "";
}
Object principal = authentication.getPrincipal();
if (principal instanceof SpringSecurityUserAuth) {
return ((SpringSecurityUserAuth) principal).getTenantId();
} else {
return "";
}
}
@Resource
public void setAuditConnector(AuditConnector auditConnector) {
this.auditConnector = auditConnector;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.ctx = applicationContext;
}
}