Package com.jeecms.cms.web

Source Code of com.jeecms.cms.web.AdminContextInterceptor

package com.jeecms.cms.web;

import static com.jeecms.common.web.Constants.MESSAGE;
import static com.jeecms.core.action.front.LoginAct.PROCESS_URL;
import static com.jeecms.core.action.front.LoginAct.RETURN_URL;

import java.util.List;
import java.util.Set;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.UrlPathHelper;

import com.jeecms.cms.entity.main.CmsSite;
import com.jeecms.cms.entity.main.CmsUser;
import com.jeecms.cms.manager.main.CmsSiteMng;
import com.jeecms.cms.manager.main.CmsUserMng;
import com.jeecms.common.web.CookieUtils;
import com.jeecms.common.web.session.SessionProvider;
import com.jeecms.common.web.springmvc.MessageResolver;
import com.jeecms.core.manager.AuthenticationMng;

/**
* CMS上下文信息拦截器
*
* 包括登录信息、权限信息、站点信息
*
* @author liufang
*
*/
public class AdminContextInterceptor extends HandlerInterceptorAdapter {
  private static final Logger log = Logger
      .getLogger(AdminContextInterceptor.class);
  public static final String SITE_PARAM = "_site_id_param";
  public static final String SITE_COOKIE = "_site_id_cookie";
  public static final String PERMISSION_MODEL = "_permission_key";

  @Override
  public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler) throws Exception {
    // 获得站点
    CmsSite site = getSite(request, response);
    CmsUtils.setSite(request, site);
    // Site加入线程变量
    CmsThreadVariable.setSite(site);

    // 获得用户
    CmsUser user = null;
    if (adminId != null) {
      // 指定管理员(开发状态)
      user = cmsUserMng.findById(adminId);
      if (user == null) {
        throw new IllegalStateException("User ID=" + adminId
            + " not found!");
      }
    } else {
      // 正常状态
      Integer userId = authMng
          .retrieveUserIdFromSession(session, request);
      if (userId != null) {
        user = cmsUserMng.findById(userId);
      }
    }
   
    // 此时用户可以为null
    CmsUtils.setUser(request, user);
   
    // User加入线程变量
    CmsThreadVariable.setUser(user);

    String uri = getURI(request);
    // 不在验证的范围内
    if (exclude(uri)) {
      return true;
    }
    // 用户为null跳转到登陆页面
    if (user == null) {
      response.sendRedirect(getLoginUrl(request));
      return false;
    }
    // 用户不是管理员,提示无权限。
    if (!user.getAdmin()) {
      request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
          "login.notAdmin"));
      response.sendError(HttpServletResponse.SC_FORBIDDEN);
      return false;
    }
   
    // 不属于该站点的管理员,提示无权限。
    if (!user.getSites().contains(site)) {
      request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
          "login.notInSite"));
      response.sendError(HttpServletResponse.SC_FORBIDDEN);
      return false;
    }
   
    boolean viewonly = user.getViewonlyAdmin();
    // 没有访问权限,提示无权限。
    if (auth && !user.isSuper()
        && !permistionPass(uri, user.getPerms(), viewonly)) {
      request.setAttribute(MESSAGE, MessageResolver.getMessage(request,
          "login.notPermission"));
      response.sendError(HttpServletResponse.SC_FORBIDDEN);
      return false;
    }
    return true;
  }

  @Override
  public void postHandle(HttpServletRequest request,
      HttpServletResponse response, Object handler, ModelAndView mav)
      throws Exception {
    CmsUser user = CmsUtils.getUser(request);
    // 不控制权限时perm为null,PermistionDirective标签将以此作为依据不处理权限问题。
    if (auth && user != null && !user.isSuper() && mav != null
        && mav.getModelMap() != null && mav.getViewName() != null
        && !mav.getViewName().startsWith("redirect:")) {
      mav.getModelMap().addAttribute(PERMISSION_MODEL, user.getPerms());
    }
  }

  @Override
  public void afterCompletion(HttpServletRequest request,
      HttpServletResponse response, Object handler, Exception ex)
      throws Exception {
    // Sevlet容器有可能使用线程池,所以必须手动清空线程变量。
    CmsThreadVariable.removeUser();
    CmsThreadVariable.removeSite();
  }

  private String getLoginUrl(HttpServletRequest request) {
    StringBuilder buff = new StringBuilder();
    if (loginUrl.startsWith("/")) {
      String ctx = request.getContextPath();
      if (!StringUtils.isBlank(ctx)) {
        buff.append(ctx);
      }
    }
    buff.append(loginUrl).append("?");
    buff.append(RETURN_URL).append("=").append(returnUrl);
    if (!StringUtils.isBlank(processUrl)) {
      buff.append("&").append(PROCESS_URL).append("=").append(
          getProcessUrl(request));
    }
    return buff.toString();
  }

  private String getProcessUrl(HttpServletRequest request) {
    StringBuilder buff = new StringBuilder();
    if (loginUrl.startsWith("/")) {
      String ctx = request.getContextPath();
      if (!StringUtils.isBlank(ctx)) {
        buff.append(ctx);
      }
    }
    buff.append(processUrl);
    return buff.toString();
  }

  /**
   * 按参数、cookie、域名、默认。
   *
   * @param request
   * @return 不会返回null,如果站点不存在,则抛出异常。
   */
  private CmsSite getSite(HttpServletRequest request,
      HttpServletResponse response) {
    CmsSite site = getByParams(request, response);
    if (site == null) {
      site = getByCookie(request);
    }
    if (site == null) {
      site = getByDomain(request);
    }
    if (site == null) {
      site = getByDefault();
    }
    if (site == null) {
      throw new RuntimeException("cannot get site!");
    } else {
      return site;
    }
  }

  private CmsSite getByParams(HttpServletRequest request,
      HttpServletResponse response) {
    String p = request.getParameter(SITE_PARAM);
    if (!StringUtils.isBlank(p)) {
      try {
        Integer siteId = Integer.parseInt(p);
        CmsSite site = cmsSiteMng.findById(siteId);
        if (site != null) {
          // 若使用参数选择站点,则应该把站点保存至cookie中才好。
          CookieUtils.addCookie(request, response, SITE_COOKIE, site
              .getId().toString(), null, null);
          return site;
        }
      } catch (NumberFormatException e) {
        log.warn("param site id format exception", e);
      }
    }
    return null;
  }

  private CmsSite getByCookie(HttpServletRequest request) {
    Cookie cookie = CookieUtils.getCookie(request, SITE_COOKIE);
    if (cookie != null) {
      String v = cookie.getValue();
      if (!StringUtils.isBlank(v)) {
        try {
          Integer siteId = Integer.parseInt(v);
          return cmsSiteMng.findById(siteId);
        } catch (NumberFormatException e) {
          log.warn("cookie site id format exception", e);
        }
      }
    }
    return null;
  }

  private CmsSite getByDomain(HttpServletRequest request) {
    String domain = request.getServerName();
    if (!StringUtils.isBlank(domain)) {
      return cmsSiteMng.findByDomain(domain, true);
    }
    return null;
  }

  private CmsSite getByDefault() {
    List<CmsSite> list = cmsSiteMng.getListFromCache();
    if (list.size() > 0) {
      return list.get(0);
    } else {
      return null;
    }
  }

  private boolean exclude(String uri) {
    if (excludeUrls != null) {
      for (String exc : excludeUrls) {
        if (exc.equals(uri)) {
          return true;
        }
      }
    }
    return false;
  }

  private boolean permistionPass(String uri, Set<String> perms,
      boolean viewOnly) {
    String u = null;
    int i;
    for (String perm : perms) {
      if (uri.startsWith(perm)) {
        // 只读管理员
        if (viewOnly) {
          // 获得最后一个 '/' 的URI地址。
          i = uri.lastIndexOf("/");
          if (i == -1) {
            throw new RuntimeException("uri must start width '/':"
                + uri);
          }
          u = uri.substring(i + 1);
          // 操作型地址被禁止
          if (u.startsWith("o_")) {
            return false;
          }
        }
        return true;
      }
    }
    return false;
  }

  /**
   * 获得第三个路径分隔符的位置
   *
   * @param request
   * @throws IllegalStateException
   *             访问路径错误,没有三(四)个'/'
   */
  private static String getURI(HttpServletRequest request)
      throws IllegalStateException {
    UrlPathHelper helper = new UrlPathHelper();
    String uri = helper.getOriginatingRequestUri(request);
    String ctxPath = helper.getOriginatingContextPath(request);
    int start = 0, i = 0, count = 2;
    if (!StringUtils.isBlank(ctxPath)) {
      count++;
    }
    while (i < count && start != -1) {
      start = uri.indexOf('/', start + 1);
      i++;
    }
    if (start <= 0) {
      throw new IllegalStateException(
          "admin access path not like '/jeeadmin/jspgou/...' pattern: "
              + uri);
    }
    return uri.substring(start);
  }

  private SessionProvider session;
  private AuthenticationMng authMng;
  private CmsSiteMng cmsSiteMng;
  private CmsUserMng cmsUserMng;
  private Integer adminId;
  private boolean auth = true;
  private String[] excludeUrls;

  private String loginUrl;
  private String processUrl;
  private String returnUrl;

  @Autowired
  public void setSession(SessionProvider session) {
    this.session = session;
  }

  @Autowired
  public void setCmsSiteMng(CmsSiteMng cmsSiteMng) {
    this.cmsSiteMng = cmsSiteMng;
  }

  @Autowired
  public void setCmsUserMng(CmsUserMng cmsUserMng) {
    this.cmsUserMng = cmsUserMng;
  }

  @Autowired
  public void setAuthMng(AuthenticationMng authMng) {
    this.authMng = authMng;
  }

  public void setAuth(boolean auth) {
    this.auth = auth;
  }

  public void setExcludeUrls(String[] excludeUrls) {
    this.excludeUrls = excludeUrls;
  }

  public void setAdminId(Integer adminId) {
    this.adminId = adminId;
  }

  public void setLoginUrl(String loginUrl) {
    this.loginUrl = loginUrl;
  }

  public void setProcessUrl(String processUrl) {
    this.processUrl = processUrl;
  }

  public void setReturnUrl(String returnUrl) {
    this.returnUrl = returnUrl;
  }

}
TOP

Related Classes of com.jeecms.cms.web.AdminContextInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.