Authorizations.java 11.6 KB
package com.xiniunet.web.filter;

import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.fastjson.JSON;
import com.xiniunet.common.utils.properties.PropertyGetter;
import com.xiniunet.foundation.request.FilePathGetRequest;
import com.xiniunet.foundation.response.FilePathGetResponse;
import com.xiniunet.foundation.service.FoundationService;
import com.xiniunet.framework.base.Page;
import com.xiniunet.framework.log.LogUtil;
import com.xiniunet.framework.security.Passport;
import com.xiniunet.framework.util.CookieUtil;
import com.xiniunet.framework.util.SettingUtil;
import com.xiniunet.framework.util.auth.AuthUtil;
import com.xiniunet.framework.util.auth.ExtUser;
import com.xiniunet.framework.util.auth.LocalData;
import com.xiniunet.master.domain.system.Tenant;
import com.xiniunet.master.domain.system.User;
import com.xiniunet.master.request.system.AuthGetListRequest;
import com.xiniunet.master.request.system.SysProductFindRequest;
import com.xiniunet.master.request.system.TenantGetRequest;
import com.xiniunet.master.request.system.UserGetRequest;
import com.xiniunet.master.response.system.SysProductFindResponse;
import com.xiniunet.master.response.system.TenantGetResponse;
import com.xiniunet.master.response.system.UserGetResponse;
import com.xiniunet.master.service.MasterService;
import com.xiniunet.security.domain.ApplicationInstallBean;
import com.xiniunet.security.request.ApplicationGetAllListByTenantIdRequest;
import com.xiniunet.security.request.PassportGetRequest;
import com.xiniunet.security.response.ApplicationGetAllListByTenantIdResponse;
import com.xiniunet.security.response.PassportGetResponse;
import com.xiniunet.security.service.SecurityService;
import com.xiniunet.supporting.sso.SSOConstant;
import com.xiniunet.supporting.sso.SSOHelper;
import com.xiniunet.web.helper.SecurityHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * Created on 2014/8/17.
 * @author 吕浩
 * @since 0.1.0
 */
public class Authorizations implements Filter {
    ServletContext context;
    ApplicationContext appContext;
    SecurityHelper securityHelper;
    MasterService masterService;
    FoundationService foundationService;
    SecurityService securityService;
    Map<String, Page> pageMap;

    @SuppressWarnings("unchecked")
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        context = filterConfig.getServletContext();
        appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);

        securityHelper = appContext.getBean(SecurityHelper.class);
        masterService = appContext.getBean(MasterService.class);
        foundationService = appContext.getBean(FoundationService.class);
        securityService = appContext.getBean(SecurityService.class);

        try {
            pageMap = (Map<String, Page>) appContext.getBean("pageMap");
        } catch (Exception e) {
            pageMap = new HashMap<>();
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /* 获取要访问的路径 */
        HttpServletRequest hsr = (HttpServletRequest) request;
        String path = hsr.getRequestURI();        //格式为:  /system/role/create.htm

		/* 验证过滤器例外文件(css || js || 图片),当文件名包含这些内容时,将直接放行,不予过滤。 */
        String[] suffixes = {".css", ".js", "$", ".jpg", ".gif", ".png", ".ttf", ".woff", ".ico", ".xls", "PaymentNotify.do","url.do","scan.do"};
        for (String suffix : suffixes) {
            if (path.contains(suffix)) {
                chain.doFilter(request, response);
                return;
            }
        }

        //  API 跳转放行
        if(path.equals("/router")){
            chain.doFilter(request, response);
            return;
        }

        path = AuthUtil.transUrl(path);

        String deployMode = SettingUtil.getDeployMode();

        Long passportId = null;
        try {
            passportId = Long.parseLong(SSOHelper.attrToken(hsr).getUid());
        } catch (Exception e){
            passportId = CookieUtil.getPassportId(hsr.getCookies(), deployMode);        // 通过Cookie获取Passport的ID
        }

        if(passportId==null||passportId==0){
            if(request.getParameter("token")!=null&&!"".equals(request.getParameter("token"))){
                passportId = Long.valueOf(request.getParameter("token"));
            }
        }


        // 获取identityId
        /*Long identityId = Long.parseLong(SSOHelper.attrToken(hsr, SSOConstant.TOKEN_TYPE_IDENTITY).getUid());*/

        Passport passport = null;
        ExtUser extUser = null;
        Page page = pageMap.get(path);
        List<String> applicationCodeList = new ArrayList<>();

        if (passportId != null) {
            PassportGetRequest passportGetRequest = new PassportGetRequest();
            passportGetRequest.setId(passportId);

            PassportGetResponse passportGetResponse = securityHelper.getPassport(passportGetRequest);
            passport = passportGetResponse.getPassport();
            if(passport == null || passport.getRevokeType() != null
                    || passport.getExpireTime().getTime() < System.currentTimeMillis()) {
                // 注销单点登录
                SSOHelper.clearRedirectLogin(hsr, (HttpServletResponse) response);
                return;
            }
            /*if(passport == null) {

                LogUtil.debugLog("passport is null!!");
                // 如果未找到Passport,清空passport信息.
                Cookie cookie = new Cookie(CookieUtil.getPassportCookieName(deployMode), "logout");
                cookie.setPath("/");
                cookie.setDomain("xiniunet.com");
                cookie.setMaxAge(-1);
                ((HttpServletResponse)response).addCookie(cookie);

                // 如果当前不是401页面,保存当前URL,用于登录后跳转.(排除401页面是避免跳转死循环)
                if(!path.endsWith("401.htm")) {
                    ((HttpServletResponse) response).addCookie(getReturnCookie(hsr.getRequestURL().toString()));
                }

                ((HttpServletResponse) response).sendError(401);
                return;
            }*/
            extUser = JSON.parseObject(JSON.toJSONString(passport), ExtUser.class);

            extUser.setPassportId(passportId);

            // 查询用户信息
            UserGetRequest userGetRequest = new UserGetRequest(passport.getUserId());
            UserGetResponse userGetResponse = masterService.getUser(userGetRequest, passport);
            User user = userGetResponse.getUser();
            if (user != null) {
                extUser.setUserName(user.getName());
                extUser.setNickName(user.getNickName());
                extUser.setType(user.getSourceType());

                // 查询头像地址
                FilePathGetRequest pathGetRequest = new FilePathGetRequest();
                pathGetRequest.setId(user.getAvatarId());
                FilePathGetResponse pathGetResponse = foundationService.getFilePath(pathGetRequest, passport);
                extUser.setAvatar(pathGetResponse.getUrl());
            }

            // 查询承租人信息
            TenantGetResponse tenantGetResponse = masterService.getTenant(new TenantGetRequest(), passport);
            Tenant tenant = tenantGetResponse.getTenant();
            if (tenant != null) {
                extUser.setTenantNumber(tenant.getNumber());
                extUser.setTenantName(StringUtils.isBlank(tenant.getNameAlt())?tenant.getName():tenant.getNameAlt());

                // 查询Logo地址
                FilePathGetRequest pathGetRequest = new FilePathGetRequest();
                pathGetRequest.setId(tenant.getLogoId());
                FilePathGetResponse pathGetResponse = foundationService.getFilePath(pathGetRequest, passport);
                extUser.setLogo(pathGetResponse.getUrl());
            }

            Long productId = 100000L;
            List<String> functionList = new ArrayList<>();
            // 通过Code查询产品信息
            SysProductFindRequest codeRequest = new SysProductFindRequest();
            if(page != null && page.getProductCode() != null) {
                codeRequest.setCode(page.getProductCode());
            } else {
                codeRequest.setCode(PropertyGetter.getFromFile("product.code"));
            }
            SysProductFindResponse codeResponse = masterService.findSysProduct(codeRequest,new Passport());
            if(CollectionUtils.isNotEmpty(codeResponse.getResult())) {
                productId = codeResponse.getResult().get(0).getId();
            }

            // 查询当前用户在当前产品下的所有功能列表
            if(productId != null) {
                AuthGetListRequest authRequest = new AuthGetListRequest();
                authRequest.setProductId(productId);
                functionList = masterService.getAuthList(authRequest, passport).getResult();
            }
            extUser.setFunctionList(functionList);

            // 查询承租人所有的应用列表
            ApplicationGetAllListByTenantIdRequest applicationRequest = new ApplicationGetAllListByTenantIdRequest();
            applicationRequest.setId(passport.getTenantId());
            ApplicationGetAllListByTenantIdResponse applicationResponse
                    = securityService.getApplicationAllListByTenantId(applicationRequest, passport);
            if( ! applicationResponse.hasError()) {
                if(applicationResponse.getTotalCount() > 0) {
                    for(ApplicationInstallBean bean : applicationResponse.getResult()) {
                        applicationCodeList.add(bean.getApplicationCode());
                    }
                }
            }
        }

        // 保存在本地线程变量中
        LocalData.setCurrentPage(page);
        LocalData.setPages(pageMap);
        LocalData.setCurrentUser(extUser);
        LocalData.setCurrentPassport(passport);
        LocalData.setCurrentApplicationCodeList(applicationCodeList);

        hsr.setAttribute("_passport", passport);

        if(page != null) {
            // 兼容老的权限认证方法
            int code = AuthUtil.hasPermission(path);
            if(code == 200) {
                chain.doFilter(request, response);
            } else {
                if(code == 401) {
                    if(hsr.getQueryString() != null) {
                        ((HttpServletResponse) response).addCookie(getReturnCookie(hsr.getRequestURL().toString() + "?" + hsr.getQueryString()));
                    } else {
                        ((HttpServletResponse) response).addCookie(getReturnCookie(hsr.getRequestURL().toString()));
                    }
                }
                ((HttpServletResponse) response).sendError(code);
            }
        } else {
            chain.doFilter(request, response);
        }
    }

    @SuppressWarnings("deprecation")
    private Cookie getReturnCookie(String value) {
        Cookie cookie = new Cookie("RETURN_URL", URLEncoder.encode(value));
        cookie.setPath("/");
        cookie.setDomain("xiniunet.com");
        cookie.setMaxAge(-1);
        return cookie;
    }

    @Override
    public void destroy() {
    }
}