commit 50d78bafe4f8d392437568dea1d4560373211692 Author: pioneer Date: Tue Dec 6 16:33:57 2022 +0800 open diff --git a/README.md b/README.md new file mode 100644 index 0000000..a51a5ce --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# open-JSD-10269 + +JSD-10269 单点集成\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100755 index 0000000..dbdc881 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,27 @@ + + + com.fr.plugin.xx.yuyuan.cas + + yes + 1.7 + 10.0 + 2018-07-31 + fr.open + + + [2022-06-10]【1.1】newport自行维护https。
+ [2022-06-10]【1.2】登出地址修改。
+ [2022-06-10]【1.3】登出地址修改。
+ [2022-06-11]【1.4】暂存地址适配。
+ [2022-06-13]【1.5】http和https适配。
+ [2022-06-13]【1.6】跳转问题。
+ [2022-06-15]【1.7】跳转问题。
+ ]]>
+ + + + + + +
\ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/AuthFilter.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/AuthFilter.java new file mode 100644 index 0000000..1d7f5e4 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/AuthFilter.java @@ -0,0 +1,281 @@ +package com.fr.plugin.xx.yuyuan.cas; + +import com.fr.decision.authority.base.constant.type.authority.ViewAuthorityType; +import com.fr.decision.authority.data.User; +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.decision.webservice.utils.ControllerFactory; +import com.fr.decision.webservice.utils.WebServiceUtils; +import com.fr.decision.webservice.v10.login.LoginService; +import com.fr.decision.webservice.v10.user.UserService; +import com.fr.json.JSONObject; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.yuyuan.cas.conf.CasSsoConfig; +import com.fr.plugin.xx.yuyuan.cas.utils.CommonUtils; +import com.fr.plugin.xx.yuyuan.cas.utils.HttpUtil; +import com.fr.plugin.xx.yuyuan.cas.utils.LogUtils; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.stable.StringUtils; +import com.fr.stable.fun.Authorize; +import com.fr.swift.util.Strings; +import com.fr.web.utils.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + + +/** + * @author xx + * @since 2021/12/04 + */ +@FunctionRecorder +@Authorize(callSignKey = Constants.PLUGIN_ID) +public class AuthFilter extends AbstractGlobalRequestFilterProvider { + + + @Override + public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) { + CasSsoConfig config = CasSsoConfig.getInstance(); + if (!config.configFinished()) { + CommonUtils.next(req, res, chain); + return; + } + if (req.getRequestURI().endsWith("/cas/logout")) { + LogUtils.debug4plugin("/cas/logout url request {}", req.getRequestURL() + req.getQueryString()); + handleLogout(req, res); + } + String code = req.getParameter("code"); + if (CommonUtils.isLogin(req)) { + if (!this.hasAuth(req)) { + noAuth(req, res); + return; + } + String loginUrl = WebUtils.getHTTPRequestParameter(req, "loginUrl"); + String currentUrl = CommonUtils.getCachedParam(loginUrl); + if (StringUtils.isNotBlank(currentUrl) && StringUtils.isNotBlank(code)){ + try { + res.sendRedirect(changePort(currentUrl)); + return; + } catch (IOException e) { + LogUtils.error(e.getMessage(), e); + } + } + CommonUtils.next(req, res, chain); + return; + } + String checkUrl = req.getRequestURI(); + if (checkUrl.contains("ajax")) { + CommonUtils.next(req, res, chain); + return; + } + + if (StringUtils.isNotBlank(code)) { + String yuYuan_sysCode = WebUtils.getHTTPRequestParameter(req, "yuyuan_syscode"); + String client_id = WebUtils.getHTTPRequestParameter(req, "client_id"); + String client_secret = config.getClientSecret(); + String loginUrl = WebUtils.getHTTPRequestParameter(req, "loginUrl"); + String currentUrl = CommonUtils.getCachedParam(loginUrl); + String getToken = getAccessToken(client_id, client_secret, code, yuYuan_sysCode); + LogUtils.debug4plugin("get access token res is {}", getToken); + if (StringUtils.isBlank(getToken)) { + setError(res, "获取token失败"); + return; + } + JSONObject JsonToken = new JSONObject(getToken); + String access_token = JsonToken.getString("access_token"); + String userName = this.getUserName(access_token, yuYuan_sysCode); + LogUtils.debug4plugin("get user name res is {}", userName); + if (StringUtils.isBlank(userName)) { + setError(res, "获取user info 失败"); + return; + } + JSONObject JsonUser = new JSONObject(userName); + String userAccount = JsonUser.getString("email"); + if (!CommonUtils.checkUser(userAccount)) { + noUser(req, res, userAccount); + } + CommonUtils.login(userAccount, req, res); + try { + LogUtils.debug4plugin("login success redirect url is {}", currentUrl); + if (StringUtils.isNotBlank(currentUrl)) { + res.sendRedirect(this.changePort(currentUrl)); + } + } catch (IOException e) { + LogUtils.error(e.getMessage(), e); + } + return; + } + String noAuthHtml = config.getCodeUrl(); + String username = config.getSysCode(); + String url = config.getClientId(); + String currentUrl = config.getResponseType(); + String state = config.getState(); + String redirect = config.getNewPort(); + String loginUrl = getUrl(req); + String id = UUID.randomUUID().toString(); + CommonUtils.cacheParams(id, loginUrl); + noAuthHtml = noAuthHtml + "&yuyuan_syscode=" + username + "&client_id=" + url + "&response_type=" + currentUrl + "&state=" + state + "&redirect=" + req.getScheme() + "://" + redirect + "/webroot/decision&loginUrl=" + id; + LogUtils.debug4plugin("redirect login url is {}", noAuthHtml); + try { + res.sendRedirect(noAuthHtml); + } catch (IOException e) { + LogUtils.error(e.getMessage(), e); + } + } + + private boolean hasAuth(HttpServletRequest req) { + User user = null; + try { + user = UserService.getInstance().getUserByRequestCookie(req); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + if (req.getRequestURL().toString().contains("entry/access") && user != null) { + LogUtils.debug4plugin("check url {} auth by user [{}]", getUrl(req), user.getUserName()); + int len = req.getRequestURL().toString().split("/").length; + String entryId = req.getRequestURL().toString().split("/")[len - 1]; + if (Strings.isEmpty(entryId)) { + return true; + } else { + LogUtils.error("id = " + entryId); + + try { + boolean hasPrivilege = ControllerFactory.getInstance().getEntryController(user.getId()).doesUserHasEntityAuth(user.getId(), entryId, ViewAuthorityType.TYPE); + LogUtils.error("hasPrivilege = " + hasPrivilege); + return hasPrivilege; + } catch (Exception var7) { + LogUtils.error("出错啦:", var7); + return false; + } + } + } else { + return true; + } + } + + private void noAuth(HttpServletRequest req, HttpServletResponse res) { + CasSsoConfig config = CasSsoConfig.getInstance(); + String noAuthHtml = config.getNoAuthUrl(); + String username = config.getCasLogout(); + String url = config.getSysCode(); + String currentUrl = getUrl(req); + LogUtils.debug4plugin("noAuthHtml = " + noAuthHtml); + try { + res.sendRedirect(noAuthHtml + "?yuyuan_syscode=" + url + "&service=" + URLDecoder.decode(currentUrl, "UTF-8") + "&logout_url=" + username); + } catch (IOException e) { + LogUtils.error(e.getMessage(), e); + } + + } + + private void noUser(HttpServletRequest req, HttpServletResponse res, String user) { + CasSsoConfig config = CasSsoConfig.getInstance(); + String noAuthHtml = config.getNoUserUrl(); + String username = config.getLogoutUrl(); + String url = config.getSysCode(); + String currentUrl = WebUtils.getHTTPRequestParameter(req, "loginUrl"); + LogUtils.debug4plugin("用户[{}]在FR平台中不存在", user); + try { + res.sendRedirect(noAuthHtml + "?yuyuan_syscode=" + url + "&service=" + URLDecoder.decode(currentUrl, "UTF-8") + "&logout_url=" + username); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + } + + private void handleLogout(HttpServletRequest req, HttpServletResponse res) { + LoginService.getInstance().crossDomainLogout(req, res, StringUtils.EMPTY); + CasSsoConfig instance = CasSsoConfig.getInstance(); + String logoutUrl = instance.getLogoutUrl(); + String checkSysCode = instance.getSysCode(); + String redirect = WebUtils.getHTTPRequestParameter(req, "service"); + logoutUrl = logoutUrl + "?yuyuan_syscode=" + checkSysCode + "&service=" + redirect; + LogUtils.debug4plugin("logoutUrl is {}", logoutUrl); + try { + res.sendRedirect(logoutUrl); + } catch (IOException e) { + LogUtils.error(e.getMessage(), e); + } + } + + private String getUrl(HttpServletRequest req) { + String requestURL = req.getRequestURL().toString(); + String queryString = req.getQueryString(); + if (StringUtils.isNotBlank(queryString)) { + requestURL += "?" + queryString; + } + return requestURL; + } + + + @Override + public String filterName() { + return "sso"; + } + + @Override + public String[] urlPatterns() { + if (!PluginContexts.currentContext().isAvailable()) { + LogUtils.error("未注册或禁用"); + return new String[]{"/neverbeused"}; + } + return new String[]{ + "/decision", + "/decision/view/report", + "/decision/view/form", + "/decision/v10/entry/access/*" + }; + } + + private String changePort(String url) { + String checkPort = url.substring(url.indexOf("://") + 3, url.indexOf("/webroot/decision")); + LogUtils.debug4plugin("get current domain is {}", checkPort); + String newPort = CasSsoConfig.getInstance().getNewPort(); + if (url.contains(checkPort) && !newPort.equals(checkPort)) { + url = url.replace(checkPort, newPort); + } + LogUtils.debug4plugin("change port res is {}", url); + return url; + } + + private String getAccessToken(String client_id, String client_secret, String code, String yuYuan_sysCode) { + Map param = new HashMap(); + param.put("client_id", client_id); + param.put("client_secret", client_secret); + param.put("code", code); + param.put("grant_type", "authorization_code"); + String tokenUrl = CasSsoConfig.getInstance().getTokenUrl() + "?yuyuan_syscode=" + yuYuan_sysCode; + return HttpUtil.doFormPost(tokenUrl, null, param, null); + } + + private String getUserName(String access_token, String yuYuan_sysCode) { + Map param = new HashMap(); + param.put("access_token", access_token); + String userUrl = CasSsoConfig.getInstance().getUserUrl() + "?yuyuan_syscode=" + yuYuan_sysCode; + return HttpUtil.doFormPost(userUrl, null, param, null); + } + + private void setError(HttpServletResponse res, String reason) { + try { + PrintWriter printWriter = WebUtils.createPrintWriter(res); + Map map = new HashMap<>(); + map.put("result", InterProviderFactory.getProvider().getLocText("Fine-Engine_Error_Page_Result")); + map.put("reason", reason); + map.put("solution", InterProviderFactory.getProvider().getLocText("Fine-Engine_Please_Contact_Platform_Admin")); + String page = WebServiceUtils.parseWebPageResourceSafe("com/fr/web/controller/decision/entrance/resources/unavailable.html", map); + printWriter.write(page); + printWriter.flush(); + printWriter.close(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + +} diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/Constants.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/Constants.java new file mode 100644 index 0000000..1af6ea8 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/Constants.java @@ -0,0 +1,12 @@ +package com.fr.plugin.xx.yuyuan.cas; + +/** + * @author xx + * @date 2020/5/14 + */ +public class Constants { + public static final String PLUGIN_ID = "com.fr.plugin.xx.yuyuan.cas"; + + public static final String PLUGIN_NAME= "cas单点升级"; + +} diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/LRGT.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/LRGT.java new file mode 100644 index 0000000..1396353 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/LRGT.java @@ -0,0 +1,27 @@ +package com.fr.plugin.xx.yuyuan.cas; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.xx.yuyuan.cas.conf.CasSsoConfig; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + +/** + * @author xx + * @since 2022/01/13 + */ +public class LRGT extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + CasSsoConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + } + @Override + public void beforeUninstall(PluginContext pluginContext) { + } + + @Override + public void afterInstall(PluginContext var1) { + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/Logout.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/Logout.java new file mode 100644 index 0000000..610982b --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/Logout.java @@ -0,0 +1,26 @@ +package com.fr.plugin.xx.yuyuan.cas; + +import com.fr.decision.fun.impl.AbstractLogInOutEventProvider; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.plugin.xx.yuyuan.cas.conf.CasSsoConfig; +import com.fr.stable.StringUtils; + +/** + * @Author xx + * @Date 2022/6/9 + * @Description + **/ +public class Logout extends AbstractLogInOutEventProvider { + @Override + public String logoutAction(LogInOutResultInfo result) { + CasSsoConfig instance = CasSsoConfig.getInstance(); + if (!instance.configFinished()) { + return StringUtils.EMPTY; + } + String logoutUrl = instance.getLogoutUrl(); + String checkSysCode = instance.getSysCode(); + String redirect = instance.getNewPort(); + logoutUrl = logoutUrl + "?yuyuan_syscode=" + checkSysCode + "&service="+result.getRequest().getScheme()+"://" + redirect + "/webroot/decision"; + return logoutUrl; + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/conf/CasSsoConfig.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/conf/CasSsoConfig.java new file mode 100644 index 0000000..4515c52 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/conf/CasSsoConfig.java @@ -0,0 +1,211 @@ +package com.fr.plugin.xx.yuyuan.cas.conf; + +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.stable.StringUtils; + + +/** + * @author xx + * @since 2021/12/04 + */ +@Visualization(category = "CAS单点") +@EnableMetrics +public class CasSsoConfig extends DefaultConfiguration { + + private static volatile CasSsoConfig config = null; + + public static CasSsoConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(CasSsoConfig.class); + } + return config; + } + + @Identifier(value = "debugSwitch", name = "插件调试开关", description = "日志调试模式", status = Status.SHOW) + private Conf debugSwitch = Holders.simple(true); + + + public Boolean getDebugSwitch() { + return this.debugSwitch.get(); + } + + public void setDebugSwitch(Boolean debugSwitch) { + this.debugSwitch.set(debugSwitch); + } + + @Identifier(value = "codeUrl", name = "跳转登录地址", description = "跳转登录地址", status = Status.SHOW) + private Conf codeUrl = Holders.simple(StringUtils.EMPTY); + + public String getCodeUrl() { + return codeUrl.get(); + } + + public void setCodeUrl(String codeUrl) { + this.codeUrl.set(codeUrl); + } + + @Identifier(value = "tokenUrl", name = "获取token地址", description = "获取token地址", status = Status.SHOW) + private Conf tokenUrl = Holders.simple(StringUtils.EMPTY); + + public String getTokenUrl() { + return tokenUrl.get(); + } + + public void setTokenUrl(String tokenUrl) { + this.tokenUrl.set(tokenUrl); + } + + @Identifier(value = "userUrl", name = "获取用户地址", description = "获取用户地址", status = Status.SHOW) + private Conf userUrl = Holders.simple(StringUtils.EMPTY); + + public String getUserUrl() { + return userUrl.get(); + } + + public void setUserUrl(String userUrl) { + this.userUrl.set(userUrl); + } + + @Identifier(value = "logoutUrl", name = "登出接口地址", description = "登出接口地址", status = Status.SHOW) + private Conf logoutUrl = Holders.simple(StringUtils.EMPTY); + + public String getLogoutUrl() { + return logoutUrl.get(); + } + + public void setLogoutUrl(String logoutUrl) { + this.logoutUrl.set(logoutUrl); + } + + @Identifier(value = "noUserUrl", name = "无用户页面地址", description = "无用户页面地址", status = Status.SHOW) + private Conf noUserUrl = Holders.simple(StringUtils.EMPTY); + + public String getNoUserUrl() { + return noUserUrl.get(); + } + + public void setNoUserUrl(String noUserUrl) { + this.noUserUrl.set(noUserUrl); + } + + @Identifier(value = "noAuthUrl", name = "无权限页面地址", description = "无权限页面地址", status = Status.SHOW) + private Conf noAuthUrl = Holders.simple(StringUtils.EMPTY); + + public String getNoAuthUrl() { + return noAuthUrl.get(); + } + + public void setNoAuthUrl(String noAuthUrl) { + this.noAuthUrl.set(noAuthUrl); + } + + @Identifier(value = "casLogout", name = "fr_cas_logout", description = "fr_cas_logout", status = Status.SHOW) + private Conf casLogout = Holders.simple(StringUtils.EMPTY); + + public String getCasLogout() { + return casLogout.get(); + } + + public void setCasLogout(String casLogout) { + this.casLogout.set(casLogout); + } + + @Identifier(value = "yuyuan_syscode", name = "yuyuan_syscode", description = "yuyuan_syscode", status = Status.SHOW) + private Conf sysCode = Holders.simple(StringUtils.EMPTY); + + public String getSysCode() { + return sysCode.get(); + } + + public void setSysCode(String sysCode) { + this.sysCode.set(sysCode); + } + + @Identifier(value = "response_type", name = "response_type", description = "response_type", status = Status.SHOW) + private Conf responseType = Holders.simple("code"); + + public String getResponseType() { + return responseType.get(); + } + + public void setResponseType(String responseType) { + this.responseType.set(responseType); + } + + @Identifier(value = "client_id", name = "client_id", description = "client_id", status = Status.SHOW) + private Conf clientId = Holders.simple(StringUtils.EMPTY); + + public String getClientId() { + return clientId.get(); + } + + public void setClientId(String clientId) { + this.clientId.set(clientId); + } + + @Identifier(value = "client_secret", name = "client_secret", description = "client_secret", status = Status.SHOW) + private Conf clientSecret = Holders.simple(StringUtils.EMPTY); + + public String getClientSecret() { + return clientSecret.get(); + } + + public void setClientSecret(String clientSecret) { + this.clientSecret.set(clientSecret); + } + + @Identifier(value = "state", name = "state", description = "state", status = Status.SHOW) + private Conf state = Holders.simple(StringUtils.EMPTY); + + public String getState() { + return state.get(); + } + + public void setState(String state) { + this.state.set(state); + } + + @Identifier(value = "newPort", name = "newPort", description = "newPort", status = Status.SHOW) + private Conf newPort = Holders.simple(StringUtils.EMPTY); + + public String getNewPort() { + return newPort.get(); + } + + public void setNewPort(String newPort) { + this.newPort.set(newPort); + } + + @Override + public Object clone() throws CloneNotSupportedException { + CasSsoConfig cloned = (CasSsoConfig) super.clone(); + cloned.debugSwitch = (Conf) debugSwitch.clone(); + cloned.codeUrl = (Conf) codeUrl.clone(); + cloned.tokenUrl = (Conf) tokenUrl.clone(); + cloned.userUrl = (Conf) userUrl.clone(); + cloned.sysCode = (Conf) sysCode.clone(); + cloned.clientId = (Conf) clientId.clone(); + cloned.clientSecret = (Conf) clientSecret.clone(); + cloned.responseType = (Conf) responseType.clone(); + cloned.state = (Conf) state.clone(); + cloned.newPort = (Conf) newPort.clone(); + cloned.logoutUrl = (Conf) logoutUrl.clone(); + cloned.noUserUrl = (Conf) noUserUrl.clone(); + cloned.noAuthUrl = (Conf) noAuthUrl.clone(); + cloned.casLogout = (Conf) casLogout.clone(); + return cloned; + } + + + public boolean configFinished() { + return StringUtils.isNotBlank(codeUrl.get()) && StringUtils.isNotBlank(tokenUrl.get()) + && StringUtils.isNotBlank(userUrl.get()) && StringUtils.isNotBlank(sysCode.get()) + && StringUtils.isNotBlank(clientId.get()) && StringUtils.isNotBlank(clientSecret.get()) + && StringUtils.isNotBlank(noAuthUrl.get()) && StringUtils.isNotBlank(noUserUrl.get()) + && StringUtils.isNotBlank(state.get()) && StringUtils.isNotBlank(newPort.get()); + + } +} diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/CommonUtils.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/CommonUtils.java new file mode 100644 index 0000000..6527255 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/CommonUtils.java @@ -0,0 +1,153 @@ +package com.fr.plugin.xx.yuyuan.cas.utils; + +import com.fr.data.NetworkHelper; +import com.fr.decision.authority.data.User; +import com.fr.decision.mobile.terminal.TerminalHandler; +import com.fr.decision.webservice.utils.DecisionServiceConstants; +import com.fr.decision.webservice.utils.DecisionStatusService; +import com.fr.decision.webservice.v10.login.LoginService; +import com.fr.decision.webservice.v10.login.TokenResource; +import com.fr.decision.webservice.v10.user.UserService; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.stable.web.Device; +import com.fr.web.utils.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.Properties; + +/** + * @author xx + * @since 2021/8/24 + */ +public class CommonUtils { + + public static String getProperty(Properties props, String key, String defaultValue, boolean allowBlank) { + String value = props.getProperty(key); + if (StringUtils.isNotBlank(value)) { + return value; + } else { + if (allowBlank) { + LogUtils.warn("Property[" + key + "] value is blank."); + return defaultValue; + } else { + throw new IllegalArgumentException("Property[" + key + "] cann't be blank."); + } + } + } + + public static String getProperty(Properties props, String key, boolean allowBlank) { + return getProperty(props, key, null, allowBlank); + } + + public static String getProperty(Properties props, String key) { + return getProperty(props, key, null, true); + } + + public static boolean isLogin(HttpServletRequest request) { + String oldToken = TokenResource.COOKIE.getToken(request); + return oldToken != null && checkTokenValid(request, (String) oldToken); + } + + private static boolean checkTokenValid(HttpServletRequest req, String token) { + try { + Device device = NetworkHelper.getDevice(req); + LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, device)); + return true; + } catch (Exception ignore) { + } + return false; + } + + /** + * 跳转到过滤器链中的下一个过滤器 + * + * @param request + * @param response + * @param chain + */ + public static void next(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { + try { + chain.doFilter(request, response); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + } + + public static void login(String username, HttpServletRequest request, HttpServletResponse response) { + try { + User user = UserService.getInstance().getUserByUserName(username); + String token = LoginService.getInstance().login(request, response, user.getUserName()); + request.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("sso >> Failed to login with[" + username + "]", e); + } + } + + public static boolean checkUser(String username) { + try { + User user = UserService.getInstance().getUserByUserName(username); + return user != null; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + return false; + } + + + public static boolean isMobileDevice(HttpServletRequest request) { + if (WebUtils.getDevice(request).isMobile()) { + LogUtils.debug4plugin("current request is is mobile request ,url is {}", request.getRequestURI()); + return true; + } + String requestHeader = request.getHeader("user-agent"); + String[] deviceArray = new String[]{"android", "iphone", "ipad", "ios", "windows phone", "wechat"}; + if (requestHeader == null) { + return false; + } + requestHeader = requestHeader.toLowerCase(); + for (int i = 0; i < deviceArray.length; i++) { + if (requestHeader.toLowerCase().contains(deviceArray[i])) { + LogUtils.debug4plugin("current request:{} is mobile request!", request.getRequestURI()); + return true; + } + } + String op = WebUtils.getHTTPRequestParameter(request, "op"); + return StringUtils.isNotBlank(op) && StringUtils.equals("h5", op); + } + + public static void cacheParams(String key, Map values) { + try { + DecisionStatusService.originUrlStatusService().put(key, values); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + public static void cacheParams(String key, String values) { + try { + DecisionStatusService.originUrlStatusService().put(key, values); + } catch (Exception e) { + LogUtils.error(e.getMessage(),e); + } + } + public static String getCachedParam(String key) { + try { + return DecisionStatusService.originUrlStatusService().get(key); + } catch (Exception e) { + return StringUtils.EMPTY; + } + } + + public static String getCachedParam(String key, String name) { + try { + Map values = DecisionStatusService.originUrlStatusService().get(key); + return values.get(name); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/HttpUtil.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/HttpUtil.java new file mode 100644 index 0000000..328d56f --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/HttpUtil.java @@ -0,0 +1,330 @@ +package com.fr.plugin.xx.yuyuan.cas.utils; + +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.http.HttpResponse; +import com.fr.third.org.apache.http.HttpStatus; +import com.fr.third.org.apache.http.NameValuePair; +import com.fr.third.org.apache.http.client.HttpClient; +import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.config.Registry; +import com.fr.third.org.apache.http.config.RegistryBuilder; +import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.ssl.SSLContexts; +import com.fr.third.org.apache.http.conn.ssl.TrustStrategy; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; +import com.fr.third.org.apache.http.impl.client.HttpClientBuilder; +import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import com.fr.third.org.apache.http.message.BasicNameValuePair; +import com.fr.third.org.apache.http.util.EntityUtils; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author xx + * @Date 2020/12/05 + * @Description + **/ +public class HttpUtil { + + private static HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + System.out.println("Warning: URL Host: " + urlHostName + " vs. " + + session.getPeerHost()); + return true; + } + }; + + /** + * 发送get请求 + * + * @param url + * @param param + * @param header + * @return + * @throws IOException + */ + public static String sendGet(String url, Map param, Map header) { + String result = ""; + BufferedReader in = null; + String urlNameString = url; + try { + if (param != null) { + urlNameString += "?"; + urlNameString += param.entrySet() + .stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining("&")); + } + + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + HttpURLConnection connection; + if (url.startsWith("https")) { + trustAllHttpsCertificates(); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + connection = (HttpURLConnection) realUrl.openConnection(); + } else { + connection = (HttpURLConnection) realUrl.openConnection(); + } + //设置超时时间 + connection.setDoInput(true); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(5000); + connection.setReadTimeout(15000); + // 设置通用的请求属性 + if (header != null) { + Iterator> it = header.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + System.out.println(entry.getKey() + ":::" + entry.getValue()); + connection.setRequestProperty(entry.getKey(), entry.getValue()); + } + } + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 建立实际的连接 + connection.connect(); + // 定义 BufferedReader输入流来读取URL的响应,设置utf8防止中文乱码 + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + if (in != null) { + in.close(); + } + }catch (Exception e){ + FineLoggerFactory.getLogger().error(e,"get url error ,url is:{},error is {}",urlNameString,e.getMessage()); + } + return result; + } + + public static String sendPost(String url,Map header, JSONObject body) { + PrintWriter out = null; + BufferedReader in = null; + String result = StringUtils.EMPTY; + String res = StringUtils.EMPTY; + try { + String urlNameString = url; + + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + HttpURLConnection conn; + if (url.startsWith("https")) { + trustAllHttpsCertificates(); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + conn = (HttpURLConnection) realUrl.openConnection(); + } else { + conn = (HttpURLConnection) realUrl.openConnection(); + } + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Content-Type","application/json;;charset=UTF-8"); + //conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=----footfoodapplicationrequestnetwork"); + if(header != null){ + header.forEach((k, v) -> { + conn.setRequestProperty(k, v); + }); + } + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + //获取请求头 + + // 获取URLConnection对象对应的输出流 + out = new PrintWriter(conn.getOutputStream()); + StringBuffer buffer = new StringBuffer(); + + // 发送请求参数 + if(body != null){ + out.print(body.toString()); + } + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader( + new InputStreamReader(conn.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + res = result; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + //使用finally块来关闭输出流、输入流 + finally{ + try{ + if(out!=null){ + out.close(); + } + if(in!=null){ + in.close(); + } + } + catch(IOException e){ + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + } + return res; + } + + private static void trustAllHttpsCertificates() throws Exception { + javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; + javax.net.ssl.TrustManager tm = new miTM(); + trustAllCerts[0] = tm; + SSLContext sc = SSLContext.getInstance("SSL","SunJSSE"); + sc.init(null, trustAllCerts, null); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } + + + public static String doFormPost(String url,Map header, Map map, String chartset) { + //声明返回结果 + String result = ""; + UrlEncodedFormEntity entity = null; + HttpResponse httpResponse = null; + HttpClient httpClient = null; + try { + // 创建连接 + httpClient = getHttpsClient(); + ; + + // 设置请求头和报文 + HttpPost httpPost = new HttpPost(url); + if (header != null) { + header.forEach((k, v) -> { + httpPost.setHeader(k, v.toString()); + }); + } + //设置参数 + List list = new ArrayList(); + Iterator iterator = map.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry elem = (Map.Entry) iterator.next(); + list.add(new BasicNameValuePair(elem.getKey(), elem.getValue())); + } + entity = new UrlEncodedFormEntity(list, chartset == null ? "UTF-8" : chartset); + httpPost.setEntity(entity); + //执行发送,获取相应结果 + httpResponse = httpClient.execute(httpPost); + if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + result = EntityUtils.toString(httpResponse.getEntity()); + } else { + FineLoggerFactory.getLogger().error("Http post form code is {},message is {}", httpResponse.getStatusLine().getStatusCode(), EntityUtils.toString(httpResponse.getEntity())); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return result; + + } + + private static CloseableHttpClient getHttpsClient() { + RegistryBuilder registryBuilder = RegistryBuilder.create(); + ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory(); + registryBuilder.register("http", plainSF); + // 指定信任密钥存储对象和连接套接字工厂 + try { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + // 信任任何链接 + TrustStrategy anyTrustStrategy = new TrustStrategy() { + + @Override + public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException { + // TODO Auto-generated method stub + return true; + } + }; + SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build(); + LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + registryBuilder.register("https", sslSF); + } catch (KeyStoreException e) { + throw new RuntimeException(e); + } catch (KeyManagementException e) { + throw new RuntimeException(e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + Registry registry = registryBuilder.build(); + // 设置连接管理器 + PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry); + // 构建客户端 + return HttpClientBuilder.create().setConnectionManager(connManager).build(); + + } + + /** + * encode url by UTF-8 + * @param url url before encoding + * @return url after encoding + */ + public static String encodeUrl(String url){ + String eurl = url; + try { + eurl = URLEncoder.encode(url,"UTF-8"); + } catch (UnsupportedEncodingException e) { + } + return eurl; + } + + private static class miTM implements javax.net.ssl.TrustManager, + javax.net.ssl.X509TrustManager { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public boolean isServerTrusted( + java.security.cert.X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted( + java.security.cert.X509Certificate[] certs) { + return true; + } + + @Override + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) + throws CertificateException { + return; + } + + @Override + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) + throws CertificateException { + return; + } + } +} diff --git a/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/LogUtils.java b/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/LogUtils.java new file mode 100644 index 0000000..47e12ba --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/yuyuan/cas/utils/LogUtils.java @@ -0,0 +1,122 @@ +package com.fr.plugin.xx.yuyuan.cas.utils; + +import com.fr.log.FineLoggerFactory; +import com.fr.log.FineLoggerProvider; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.yuyuan.cas.Constants; +import com.fr.plugin.xx.yuyuan.cas.conf.CasSsoConfig; +import com.fr.stable.StringUtils; + +/** + * @author xx + * @since 2021/12/04 + */ +public final class LogUtils { + private static final String DEBUG_PREFIX = "[插件调试] "; + private static String LOG_PREFIX = Constants.PLUGIN_NAME; + private static final String PLUGIN_VERSION; + + private static final FineLoggerProvider LOGGER = FineLoggerFactory.getLogger(); + + static { + String version = PluginContexts.currentContext().getMarker().getVersion(); + if (StringUtils.isNotBlank(version)) { + PLUGIN_VERSION = "[v" + version + "] "; + } else { + PLUGIN_VERSION = "[unknown version] "; + } + + LOG_PREFIX = LOG_PREFIX + PLUGIN_VERSION; + } + + public static void setPrefix(String prefix) { + if (prefix != null) { + LOG_PREFIX = prefix; + } + } + + public static boolean isDebugEnabled() { + return LOGGER.isDebugEnabled(); + } + + public static void debug(String s) { + LOGGER.debug(LOG_PREFIX + s); + } + + public static void debug(String s, Object... objects) { + LOGGER.debug(LOG_PREFIX + s, objects); + } + + public static void debug(String s, Throwable throwable) { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + + public static void debug4plugin(String s) { + if (CasSsoConfig.getInstance().getDebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s); + } else { + LOGGER.debug(LOG_PREFIX + s); + } + } + + public static void debug4plugin(String s, Object... objects) { + if (CasSsoConfig.getInstance().getDebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, objects); + } else { + LOGGER.debug(LOG_PREFIX + s, objects); + } + } + + public static void debug4plugin(String s, Throwable throwable) { + if (CasSsoConfig.getInstance().getDebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, throwable); + } else { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + } + + + public static boolean isInfoEnabled() { + return LOGGER.isInfoEnabled(); + } + + public static void info(String s) { + LOGGER.info(LOG_PREFIX + s); + } + + public static void info(String s, Object... objects) { + LOGGER.info(LOG_PREFIX + s, objects); + } + + public static void warn(String s) { + LOGGER.warn(LOG_PREFIX + s); + } + + public static void warn(String s, Object... objects) { + LOGGER.warn(LOG_PREFIX + s, objects); + } + + public static void warn(String s, Throwable throwable) { + LOGGER.warn(LOG_PREFIX + s, throwable); + } + + public static void warn(Throwable throwable, String s, Object... objects) { + LOGGER.warn(throwable, LOG_PREFIX + s, objects); + } + + public static void error(String s) { + LOGGER.error(LOG_PREFIX + s); + } + + public static void error(String s, Object... objects) { + LOGGER.error(LOG_PREFIX + s, objects); + } + + public static void error(String s, Throwable throwable) { + LOGGER.error(LOG_PREFIX + s, throwable); + } + + public static void error(Throwable throwable, String s, Object... objects) { + LOGGER.error(throwable, LOG_PREFIX + s, objects); + } +}