//$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.beangle.security.monitor.web;
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.beangle.security.monitor.Authentication;
import org.beangle.security.monitor.AuthenticationException;
import org.beangle.security.monitor.OnlineActivity;
import org.beangle.security.monitor.auth.provider.sso.SsoAuthentication;
import org.beangle.security.monitor.auth.ui.UserDetailsSource;
import org.beangle.security.monitor.auth.web.WebUserDetailsSource;
import org.beangle.security.monitor.SecurityManager;
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 SecurityManager manager;
private String loginFailPath = null;
private String noAuthorityPath = null;
private String expiredPath = null;
/** 功能点提取类名 */
private String resourceExtractorClassName = DefaultResourceExtractor.class.getName();
private ResourceExtractor resourceExtractor;
private Set<String> freeResources = new HashSet<String>();
private UserDetailsSource userDetailsSource = new WebUserDetailsSource();
public void init(FilterConfig cfg) throws ServletException {
@SuppressWarnings("unchecked")
Enumeration<String> en = cfg.getInitParameterNames();
while (en.hasMoreElements()) {
String property = 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));
if (null != noAuthorityPath) {
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 == manager) {
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(session.getServletContext());
manager = (SecurityManager) wac.getBean("securityManager", SecurityManager.class);
}
// 避免login没有权限,出现死循环
if (!freeResources.contains(resource) && !manager.isPublicResource(resource)) {
OnlineActivity info = manager.getAuthenticationManager().getSessionController()
.getOnlineActivity(session.getId());
if (null == info) {
Authentication auth = null;
// remember me
// if (manager.isEnableRememberMe()) {
// auth = manager.getRememberMeService().autoLogin(httpRequest);
// }
if (null == auth) {
auth = new SsoAuthentication(httpRequest);
auth.setDetails(userDetailsSource.buildDetails(httpRequest));
}
try {
manager.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()) {
manager.logout(session);
// 记录访问失败的URL
session.setAttribute(PREVIOUS_URL, httpRequest.getRequestURL() + "?"
+ httpRequest.getQueryString());
redirectTo((HttpServletRequest) request, (HttpServletResponse) response,
expiredPath);
return;
} else {
info.refreshLastRequest();
boolean pass = manager.isAuthorized(info.getUserid(), resource);
if (pass) {
logger.debug("user {} access {} success", info.getPrincipal(), resource);
} else {
logger.info("user {} cannot access [{}]", info.getPrincipal(), resource);
reportNoAuthority((HttpServletRequest) request, (HttpServletResponse) response);
return;
}
}
} else {
logger.debug("free or public resource {} was accessed", resource);
}
chain.doFilter(request, response);
}
private void reportNoAuthority(HttpServletRequest request, HttpServletResponse response)
throws IOException {
if (null == noAuthorityPath) {
response.getWriter().append("no authority");
} else {
redirectTo((HttpServletRequest) request, (HttpServletResponse) response,
noAuthorityPath);
}
}
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;
}
}