package com.app.mvc.acl.filter; import com.app.mvc.acl.domain.SysUser; import com.app.mvc.acl.service.SysCoreService; import com.app.mvc.acl.util.RequestHolder; import com.app.mvc.beans.JsonMapper; import com.app.mvc.beans.Result; import com.app.mvc.common.SpringHelper; import com.app.mvc.config.GlobalConfig; import com.app.mvc.config.GlobalConfigKey; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.util.AntPathMatcher; import org.springframework.util.PathMatcher; 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 java.io.IOException; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentSkipListSet; /** * Created by jimin on 16/2/6. */ @Slf4j public class AclControlFilter implements Filter { private static Set<String> exclusionUrlSet = new ConcurrentSkipListSet<String>(); private final PathMatcher pathMatcher = new AntPathMatcher(); @Override public void init(FilterConfig config) throws ServletException { // 获取权限校验范围内的白名单url String exclusionUrls = config.getInitParameter("exclusionUrls"); String[] exclusionUrlArray = StringUtils.split(exclusionUrls, ","); for (String exclusionUrl : exclusionUrlArray) { exclusionUrlSet.add(exclusionUrl.trim()); } } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String servletPath = request.getServletPath(); Map requestMap = request.getParameterMap(); // 权限校验范围内的白名单URL不过滤 if (exclusionUrlSet.contains(servletPath)) { chain.doFilter(req, resp); return; } Set<String> whiteList = GlobalConfig.getSetValue(GlobalConfigKey.ACCESS_WHITELIST); whiteList.add(getNoAuthPage()); for (String ignoreUrlPattern : whiteList) { if (pathMatcher.match(ignoreUrlPattern, servletPath)) { chain.doFilter(req, resp); return; } } SysUser sysUser = RequestHolder.getCurrentUser(); if (sysUser == null) { log.info("someone visit {}, but not login, need to check the url setting. parameter:{}", servletPath, JsonMapper.obj2String(requestMap)); noAuth(request, response); return; } SysCoreService sysCoreService = SpringHelper.popBean(SysCoreService.class); if (!sysCoreService.hasUrlAcl(servletPath)) { log.info("{} visit {}, but no auth. parameter:{}", sysUser.getUsername(), servletPath, JsonMapper.obj2String(requestMap)); noAuth(request, response); return; } log.info("{} visit {}, succeed. parameter:{}", sysUser.getUsername(), servletPath, JsonMapper.obj2String(requestMap)); chain.doFilter(req, resp); return; } /** * 无权处理 */ public void noAuth(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String servletPath = request.getServletPath(); request.setAttribute("currentUrl", servletPath); String requestAccept = request.getHeader("accept"); String contentType = "text/html"; // 无权限访问的页面 String noAuthPage = getNoAuthPage(); //判断请求类型 if (StringUtils.isNotEmpty(requestAccept)) { if (StringUtils.contains(requestAccept, "application/json") || StringUtils.contains(requestAccept, "text/javascript") || StringUtils .contains(requestAccept, "text/json")) { contentType = "application/json"; } } response.setHeader("Content-Type", contentType + "; charset=UTF-8"); if (contentType.equals("text/html")) { clientRedirect(response, noAuthPage); } else if (contentType.equals("application/json")) { Result result = Result.fail("没有访问权限,如需要访问,请联系管理员!"); response.getWriter().print(JsonMapper.obj2String(result)); } else { clientRedirect(response, noAuthPage); } } private String getNoAuthPage() { return GlobalConfig.getStringValue(GlobalConfigKey.NO_AUTH_PAGE, "/sys/user/noAuth.do"); } /** * 客户端的重定向,将页面重定向为 path?ret=encodeURIComponent(window.location.href) */ public static void clientRedirect(HttpServletResponse response, String path) throws IOException { response.setHeader("Content-Type", "text/html"); response.getWriter().println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" + "<head>\n" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"/>\n" + "<title>跳转中...</title>\n" + "</head>\n" + "<body>\n" + "跳转中,请稍候...\n" + "<script type=\"text/javascript\">//<![CDATA[\n" + "window.location.href='" + path + "?ret='+encodeURIComponent(window.location.href);\n" + "//]]></script>\n" + "</body>\n" + "</html>\n"); } @Override public void destroy() { } }