//$Id: CheckAuthorityFilter.java,v 1.6 2007/01/13 07:06:51 chaostone Exp $
/*
*
* Copyright c 2005-2009
* Licensed under the Apache License, Version 2.0 (the "License")
* http://www.apache.org/licenses/LICENSE-2.0
*
*/
/********************************************************************************
* @author duyaming,duantihua
*
* MODIFICATION DESCRIPTION
*
* Name Date Description
* ============ ============ ============
* duyaming 2005-10-21 Created
* duantihua 2006-2-8 add comment& head
*
********************************************************************************/
package org.beanfuse.security.monitor;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.beanfuse.security.Authentication;
import org.beanfuse.security.AuthenticationException;
import org.beanfuse.security.online.OnlineActivity;
import org.beanfuse.security.providers.sso.SsoAuthentication;
import org.beanfuse.security.web.DefaultResourceExtractor;
import org.beanfuse.security.web.ResourceExtractor;
import org.beanfuse.security.web.SimpleResourceExtractor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
/**
* 权限过滤器<br>
*
* @author chaostone 主要根据请求链接的最后的*.do判断该action是否在用户的权限范围内.
* 不用考虑的权限模块定义在同一级的IgnoreAction.properties文件里.
*/
public class SecurityFilter implements Filter {
private final static Logger logger = LoggerFactory.getLogger(SecurityFilter.class);
public static String PREVIOUS_URL = "previousURL";
private SecurityMonitor monitor;
private String loginFailPath = null;
private String noAuthorityPath = null;
private String expiredPath = null;
/** 功能点提取类名 */
private String resourceExtractorClassName = DefaultResourceExtractor.class.getName();
private ResourceExtractor resourceExtractor;
private Set freeResources = new HashSet();
public void init(FilterConfig cfg) throws ServletException {
Enumeration en = cfg.getInitParameterNames();
while (en.hasMoreElements()) {
String property = (String) en.nextElement();
Object value = cfg.getInitParameter(property);
try {
PropertyUtils.setProperty(this, property, value);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
// 初始化功能点提取器
if (StringUtils.isEmpty(resourceExtractorClassName)) {
resourceExtractorClassName = SimpleResourceExtractor.class.getName();
}
try {
resourceExtractor = (ResourceExtractor) Class.forName(resourceExtractorClassName)
.newInstance();
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
if (StringUtils.isEmpty(expiredPath)) {
expiredPath = loginFailPath;
}
freeResources.add(resourceExtractor.extract(loginFailPath));
freeResources.add(resourceExtractor.extract(expiredPath));
freeResources.add(resourceExtractor.extract(noAuthorityPath));
logger.info("Filter {} configured successfully with free resources {}",
cfg.getFilterName(), freeResources);
}
/**
* 实施过滤
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = ((HttpServletRequest) request);
String resource = resourceExtractor.extract(httpRequest);
request.setAttribute("resourceName", resource);
HttpSession session = httpRequest.getSession(true);
if (null == monitor) {
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(session.getServletContext());
monitor = (SecurityMonitor) wac.getBean("securityMonitor", SecurityMonitor.class);
}
// 避免login没有权限,出现死循环
if (!freeResources.contains(resource) && !monitor.isPublicResource(resource)) {
OnlineActivity info = monitor.getSessionController().getOnlineActivity(session.getId());
if (info != null && null != httpRequest.getRemoteUser()
&& !info.getPrincipal().equals(httpRequest.getRemoteUser())) {
info = null;
}
if (null == info) {
Authentication auth = null;
// remember me
if (monitor.enableRememberMe()) {
auth = monitor.getRememberMeService().autoLogin(httpRequest);
}
if (null == auth) {
auth = new SsoAuthentication(httpRequest);
auth.setDetails(monitor.getUserDetailsSource().buildDetails(httpRequest));
}
try {
monitor.authenticate(auth);
} catch (AuthenticationException e) {
// 记录访问失败的URL
session.setAttribute(PREVIOUS_URL, httpRequest.getRequestURL() + "?"
+ httpRequest.getQueryString());
redirectTo((HttpServletRequest) request, (HttpServletResponse) response,
loginFailPath);
return;
}
} else if (info.isExpired()) {
monitor.logout(session);
// 记录访问失败的URL
session.setAttribute(PREVIOUS_URL, httpRequest.getRequestURL() + "?"
+ httpRequest.getQueryString());
redirectTo((HttpServletRequest) request, (HttpServletResponse) response,
expiredPath);
return;
} else {
info.refreshLastRequest();
boolean pass = monitor.isAuthorized(info.getUserid(), resource);
if (pass) {
logger.debug("user {} access {} success", info.getPrincipal(), resource);
} else {
logger
.info("user {} cannot access resource[{}]", info.getPrincipal(),
resource);
redirectTo((HttpServletRequest) request, (HttpServletResponse) response,
noAuthorityPath);
return;
}
}
} else {
logger.debug("free or public resource {} was accessed", resource);
}
chain.doFilter(request, response);
}
public void redirectTo(HttpServletRequest request, HttpServletResponse response, String path)
throws IOException {
if (!path.startsWith("/")) {
String contextPath = request.getContextPath();
((HttpServletResponse) response).sendRedirect((contextPath.equals("/") ? ""
: (contextPath + "/"))
+ path);
} else {
((HttpServletResponse) response).sendRedirect(path);
}
}
public void destroy() {
}
public String getLoginFailPath() {
return loginFailPath;
}
public void setLoginFailPath(String failRedirect) {
this.loginFailPath = failRedirect;
}
public String getNoAuthorityPath() {
return noAuthorityPath;
}
public void setNoAuthorityPath(String noAuthorityRedirect) {
this.noAuthorityPath = noAuthorityRedirect;
}
public String getExpiredPath() {
return expiredPath;
}
public void setExpiredPath(String expiredPath) {
this.expiredPath = expiredPath;
}
public String getResourceExtractorClassName() {
return resourceExtractorClassName;
}
public void setResourceExtractorClassName(String resourceExtractorClassName) {
this.resourceExtractorClassName = resourceExtractorClassName;
}
}