package com.norteksoft.acs.service.security;
import java.io.IOException;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.BadCredentialsException;
import org.springframework.security.concurrent.SessionRegistry;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.event.authentication.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.ui.cas.CasProcessingFilter;
import org.springframework.security.ui.rememberme.RememberMeServices;
import org.springframework.security.util.SessionUtils;
import com.norteksoft.acs.service.organization.UserManager;
import com.norteksoft.acs.service.syssetting.SecuritySetManager;
import com.norteksoft.acs.web.filter.SessionFailFilter;
import com.norteksoft.product.util.ContextUtils;
import com.norteksoft.product.util.PropUtils;
public class ProcessingFilter extends CasProcessingFilter{
private boolean invalidateSessionOnSuccessfulAuthentication = false;
private boolean migrateInvalidatedSessionAttributes = true;
private SessionRegistry sessionRegistry;
private RememberMeServices rememberMeServices = null;
private UserManager userManager;
private SecuritySetManager securitySetManager;
@SuppressWarnings("unchecked")
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success: " + authResult.toString());
}
SecurityContextHolder.getContext().setAuthentication(authResult);
if (logger.isDebugEnabled()) {
logger.debug("Updated SecurityContextHolder to contain the following Authentication: '" + authResult + "'");
}
if (invalidateSessionOnSuccessfulAuthentication) {
HttpSession session = request.getSession(false);
if(session != null){
// //替换新建的session
// String originalSessionId = session.getId();
// String mappingId = SingleSignOutFilter.getMappingId(originalSessionId);
SessionUtils.startNewSessionIfRequired(request, migrateInvalidatedSessionAttributes, sessionRegistry);
// SessionMappingStorage sessionMappingStorage = SingleSignOutFilter.getSessionMappingStorage();
// session = request.getSession(false);
// sessionMappingStorage.addSessionById(mappingId, session);
}
}
// 添加登录日志 ================================================
addLoginLog(request, authResult);
// =============================================================
String targetUrl = determineTargetUrl(request);
//用ticket自动登陆 zzl
Map<String,String[]> map=request.getParameterMap();
Set<String> parameters =map.keySet();
if(parameters!=null&&!parameters.isEmpty()){
if(parameters.contains("url")&¶meters.contains("ticket")){
String url="";//路径
StringBuilder paramet=new StringBuilder();//参数
for (String parameter : parameters) {
if(!parameter.equals("ticket")){
if(parameter.equals("url")){
url=map.get(parameter)[0];
}else{
paramet.append("&"+parameter+"="+map.get(parameter)[0]);
}
}
}
targetUrl=url+paramet.toString();
}
}
// =============================================================
if(targetUrl.indexOf("type=rtxLogin") > -1){
targetUrl = targetUrl.replaceAll("type=rtxLogin", "");
}
if(targetUrl.indexOf("type=auto") > -1){//?type=auto&name=aaa&pwd=ddd
targetUrl = targetUrl.replaceAll("type=auto&", "");
String temp=targetUrl.substring(targetUrl.indexOf("?")+1, targetUrl.indexOf("&")+1);
targetUrl = targetUrl.replaceAll(temp, "");
if(targetUrl.indexOf("&")>-1){
temp=targetUrl.substring(targetUrl.indexOf("?")+1, targetUrl.indexOf("&")+1);
}else{
temp=targetUrl.substring(targetUrl.indexOf("?")+1, targetUrl.length());
}
targetUrl = targetUrl.replaceAll(temp, "");
}
if(request.getParameter("spring-security-redirect") != null
&& !request.getParameter("spring-security-redirect").equals("")){
targetUrl = request.getParameter("spring-security-redirect");
}
if (logger.isDebugEnabled()) {
logger.debug("Redirecting to target URL from HTTP Session (or default): " + targetUrl);
}
onSuccessfulAuthentication(request, response, authResult);
rememberMeServices.loginSuccess(request, response, authResult);
// Fire event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
}
String tgt = request.getParameter("tgt");
if(tgt!=null){
Cookie c = new Cookie("CASTGC", tgt);
c.setPath("/");
//c.setDomain(".norteksoft.com");
response.addCookie(c);
}
sendRedirect(request, response, targetUrl);
}
public void setInvalidateSessionOnSuccessfulAuthentication(boolean invalidateSessionOnSuccessfulAuthentication) {
this.invalidateSessionOnSuccessfulAuthentication = invalidateSessionOnSuccessfulAuthentication;
}
public void setMigrateInvalidatedSessionAttributes(boolean migrateInvalidatedSessionAttributes) {
this.migrateInvalidatedSessionAttributes = migrateInvalidatedSessionAttributes;
}
public void setSessionRegistry(SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
}
public RememberMeServices getRememberMeServices() {
return rememberMeServices;
}
public void setRememberMeServices(RememberMeServices rememberMeServices) {
this.rememberMeServices = rememberMeServices;
}
/**
* 设置session失效时间
* @param request
* @param authResult
*/
private void addLoginLog(HttpServletRequest request, Authentication authResult){
Object object = ContextUtils.getBean("securitySetManager");
if(object instanceof SecuritySetManager){
Integer minutes = ((SecuritySetManager)object).getLoginTimeoutValues(ContextUtils.getCompanyId());
HttpSession session = request.getSession(false);
//没有设置session过期时间则设置为半小时,否则取设置的值
if(session != null){
if(minutes == null) session.setMaxInactiveInterval(30*60 + SessionFailFilter.ADDITION_ACTIVE_TIME);
else session.setMaxInactiveInterval(minutes*60 + SessionFailFilter.ADDITION_ACTIVE_TIME);
}
}
}
@Override
protected void onSuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, Authentication authResult)
throws IOException {
super.onSuccessfulAuthentication(request, response, authResult);
Integer overdue = securitySetManager.getPasswordIsOverdue(ContextUtils.getUserId(), ContextUtils.getCompanyId());
if(overdue != null){
request.setAttribute("overdue", overdue);
}
}
@Override
protected void onUnsuccessfulAuthentication(HttpServletRequest request,
HttpServletResponse response, AuthenticationException failed)
throws IOException {
request.setAttribute("LOGINERROR", "LOGINERROR");
super.onUnsuccessfulAuthentication(request, response, failed);
Object obj = failed.getExtraInformation();
if(obj instanceof com.norteksoft.acs.entity.security.User){
if(!((com.norteksoft.acs.entity.security.User)obj).isEnabled()){
request.setAttribute("ACS_USER_ENABLED", "true");
}
}
Object name = request.getParameter("j_username");
if(failed instanceof BadCredentialsException && name != null && name.toString().trim().length() > 0){
com.norteksoft.acs.entity.organization.User user = userManager.getUserByLoginName(name.toString());
if(user != null){
//用户目前登陆失败的次数
Integer counts = user.getFailedCounts();
if(counts == null) counts = 0;
counts += 1;
//系统设置的允许用户登录失败的次数
Integer allowedCounts = securitySetManager.getLoginFailedCounts(user.getCompanyId());
if(allowedCounts == null) allowedCounts = 3;
Date startTiem = user.getLoginStart();
if(startTiem == null) startTiem = new Timestamp(new Date().getTime());
//一小时内的登录
if(new Date().getTime() - startTiem.getTime() < 3600000){
if(counts >= allowedCounts){
user.setAccountLocked(false);
user.setFailedCounts(0);
}else{
//用户第一次登录失败时间
if(counts == 1)
user.setLoginStart(new Timestamp(new Date().getTime()));
user.setFailedCounts(counts);
}
userManager.saveUser(user);
}else{//若是一小时后再登陆,则从新设置开始登陆时间、失败次数
user.setLoginStart(new Timestamp(new Date().getTime()));
user.setFailedCounts(1);
userManager.saveUser(user);
}
}
}
}
@Override
protected void sendRedirect(HttpServletRequest request,
HttpServletResponse response, String url) throws IOException {
if(request.getAttribute("overdue") != null){
url = "/portal/update-password.action?overdue="+ request.getAttribute("overdue") +"&name=" + URLEncoder.encode(ContextUtils.getUserName(),"utf-8") +"&url=" + url+ "&id=" + ContextUtils.getUserId()
+"&resourceCtx="+PropUtils.getProp("host.resources");;
}
Object ajaxUrl = request.getParameter("ajaxURL");
if(ajaxUrl != null && !"".equals(ajaxUrl.toString().trim())){
url = ajaxUrl.toString();
Object exception = request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
if(exception instanceof Exception){
if(url.contains("?")){
url += "&error_message=\"" + ((Exception)exception).getMessage() + "\"";
}else{
url += "?error_message=\"" + ((Exception)exception).getMessage() + "\"";
}
}
}
if(request.getAttribute("ACS_USER_ENABLED") != null){
url = url+"&forbidden=true";
}
super.sendRedirect(request, response, url);
}
@Required
public void setUserManager(UserManager userManager) {
this.userManager = userManager;
}
@Required
public void setSecuritySetManager(SecuritySetManager securitySetManager) {
this.securitySetManager = securitySetManager;
}
}