package com.moon.server.service.sys; import com.alibaba.fastjson.JSON; import com.moon.server.entity.all.*; import com.moon.server.entity.sys.ResEntity; import com.moon.server.entity.sys.ResLogEntity; import com.moon.server.entity.sys.UserEntity; import com.moon.server.helper.AsyncHelper; import com.moon.server.helper.HttpHelper; import com.moon.server.helper.StringHelper; import com.moon.server.helper.WebHelper; import com.moon.server.interceptor.AuthInterceptor; import com.moon.server.service.all.PermsService; import com.moon.server.service.all.RedisService; import com.moon.server.service.all.SysService; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.TimerTask; import java.util.concurrent.TimeUnit; /** * 代理服务类 * @author WWW * @date 2023-07-11 */ @Service public class ProxyService { @Resource RedisService redisService; @Resource private SysService sysService; @Resource private PermsService permsService; @Resource private ResLogService resLogService; public static final String ILLEGAL_RESOURCE = JSON.toJSONString(new ResponseMsg(HttpStatus.UNAUTHORIZED, "没有资源访问权限")); /** * URL代理 */ public void proxyUrl(String token, int resId, boolean isRest, HttpServletRequest req, HttpServletResponse res) throws Exception { // 3.获取用户 UserEntity ue = getUser(req, res, token); if (null == ue) { return; } // 9.获取资源实体,status:0-禁用,1-启用原始地址,2-启用代理地址 ResEntity entity = getResEntity(ue, resId); if (null == entity || StaticData.I2 != entity.getStatus() || StringHelper.isNull(entity.getProxy()) || StringHelper.isNull(entity.getUrl())) { WebHelper.writeStr2Page(res, ILLEGAL_RESOURCE); return; } insertLog(req, ue, resId); String url = getUrl(req, ue, entity, token, isRest); res.setHeader("token", token); forward(req, res, entity, url); } /** * 获取用户 */ private UserEntity getUser(HttpServletRequest req, HttpServletResponse res, String token) { String key = RedisCacheKey.permsProxy(token); Object obj = redisService.get(key); if (obj instanceof UserEntity) { return (UserEntity) obj; } UserEntity ue = sysService.tokenService.getUserByToken(token); if (null == ue) { WebHelper.writeStr2Page(res, AuthInterceptor.NO_LOGIN); return null; } if (!check(req, res, ue, token)) { return null; } redisService.put(key, ue, SettingData.CACHE_EXPIRE, TimeUnit.MINUTES); return ue; } /** * 检查 */ private boolean check(HttpServletRequest req, HttpServletResponse res, UserEntity ue, String token) { // 4.获取IP String ip = WebHelper.getIpAddress(req); if (StringHelper.isEmpty(ip)) { return WebHelper.writeStr2Page(res, AuthInterceptor.IP_NULL); } // 5.检查黑名单 if (!checkBlackList(ip, req)) { return WebHelper.writeStr2Page(res, AuthInterceptor.BLACK_LIST); } // 6.admin跳过权限检测 if (StaticData.ADMIN.equals(ue.getUid())) { return true; } // 7.检查白名单和IP一致性 if (!checkWhiteList(ip, req)) { if (!ip.equals(sysService.tokenService.getEntityByToken(token).getIp())) { return WebHelper.writeStr2Page(res, AuthInterceptor.ILLEGAL_TOKEN); } } // 8.检查用户ID是否禁用 if (sysService.tokenService.isUidDisable(ue)) { return WebHelper.writeStr2Page(res, AuthInterceptor.USER_LOCK); } return true; } /** * 检查黑名单 */ private boolean checkBlackList(String ip, HttpServletRequest request) { List blackList = sysService.blacklistService.selectIpList(1); if (blackList == null || blackList.isEmpty()) { return true; } return !blackList.contains(ip); } /** * 检查白名单 */ private boolean checkWhiteList(String ip, HttpServletRequest request) { List whiteList = sysService.blacklistService.selectIpList(2); if (whiteList == null || whiteList.isEmpty()) { return false; } return whiteList.contains(ip); } /** * 检查资源权限 */ private ResEntity getResEntity(UserEntity ue, int resId) { List rs = StaticData.ADMIN.equals(ue.getUid()) ? permsService.selectAllRes() : permsService.selectRes(ue.getUid()); if (null == rs || rs.isEmpty()) { return null; } // List list = rs.stream().filter(resEntity -> resEntity.getId() == resId).collect(Collectors.toList()) for (ResEntity entity : rs) { if (resId == entity.getId()) { return entity; } } return null; } /** * 插入日志 */ private void insertLog(HttpServletRequest req, UserEntity ue, int resId) { String ip = WebHelper.getIpAddress(req); ResLogEntity entity = new ResLogEntity(); entity.setResid(resId); entity.setType(getRequestType(req.getMethod())); entity.setIp(ip); entity.setUrl(req.getRequestURL().toString()); entity.setCreateUser(ue.getId()); AsyncHelper helper = new AsyncHelper(); helper.execute(new TimerTask() { @Override public void run() { resLogService.insert(entity); } }); } /** * 获取请求类别 */ private int getRequestType(String method) { // 请求类:1-GET,2-POST,3-PUT,4-DELETE,5-TRACE,6-HEAD,7-OPTIONS,8-CONNECT'; switch (method) { case "GET": return 1; case "POST": return 2; case "PUT": return 3; case "DELETE": return 4; case "TRACE": return 5; case "HEAD": return 6; case "OPTIONS": return 7; case "CONNECT": return 8; default: return -1; } } /** * 获取Url */ private String getUrl(HttpServletRequest req, UserEntity ue, ResEntity entity, String token, boolean isRest) { String proxyUrl = entity.getProxy().replace("{token}", token); int end = req.getRequestURL().indexOf(proxyUrl) + proxyUrl.length(); String url = entity.getUrl() + req.getRequestURL().substring(end); // category:0-其他,1-GisServer,2-GeoServer,3-数简 if (StaticData.I2 == entity.getCategory()) { url = getGeoServerUrl(req, ue, entity, url); } else if (StaticData.I3 == entity.getCategory()) { if (null != req.getQueryString()) { url = url + (url.contains("?") ? "&" : "?") + req.getQueryString(); } if (isRest) { url = url.replace("/v6/wmts/", "/v6/rest/"); } if (!StringHelper.isNull(entity.getArgs())) { url = url + (url.contains("?") ? "&" : "?") + entity.getArgs(); } } return url; } /** * 获取GeoServer地址 */ private String getGeoServerUrl(HttpServletRequest req, UserEntity ue, ResEntity entity, String url) { if (null == req.getQueryString()) { return url; } String str = req.getQueryString(), layers = req.getParameter("layers"); if (!StaticData.GET_CAPABILITIES.equals(req.getParameter(StaticData.REQUEST)) && null != layers) { int start = str.indexOf("layers"); int end = str.indexOf("&", start); layers = filterGeoLayers(ue, layers); str = str.replace(str.substring(start, end > -1 ? end : str.length()), "layers=" + layers); } else { entity.setBak(StaticData.GET_CAPABILITIES); } return url + (url.contains("?") ? "&" : "?") + str; } /** * 过滤GeoServer图层 */ private String filterGeoLayers(UserEntity ue, String layers) { List tabs = StaticData.ADMIN.equals(ue.getUid()) ? permsService.selectAllTabs() : permsService.selectTabs(ue.getUid()); if (null == tabs || tabs.isEmpty()) { return ""; } StringBuilder sb = new StringBuilder(); String[] strs = layers.split(StaticData.COMMA); for (String str : strs) { if (tabs.contains(str)) { sb.append(str).append(","); } } sb.deleteCharAt(sb.length() - 1); return sb.toString(); } /** * 转发请求 */ private void forward(HttpServletRequest request, HttpServletResponse response, ResEntity entity, String url) throws Exception { HttpHelper httpHelper = new HttpHelper(); httpHelper.service(request, response, entity, url); } }