From 56b6af97555f30e48b0de40329abafc401e69ea6 Mon Sep 17 00:00:00 2001 From: "LAPTOP-SB56SG4Q\\86185" Date: Tue, 11 Jan 2022 14:40:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=BC=80=E6=BA=90=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=9D=90=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JSD-8478-需求确认书V1.docx | Bin 0 -> 61240 bytes README.md | 5 +- plugin.xml | 24 ++ .../plugin/xxxx/qshy/JsHandler/JSHandler.java | 15 ++ .../xxxx/qshy/config/InitializeMonitor.java | 21 ++ .../xxxx/qshy/config/PluginSimpleConfig.java | 123 +++++++++ .../qshy/config/WinkPluginSimpleConfig.java | 123 +++++++++ .../handler/ExtendAttrHandlerProvider.java | 13 + .../plugin/xxxx/qshy/handler/GetQsUrl.java | 101 +++++++ .../xxxx/qshy/handler/URLAliasProvide.java | 14 + .../eco/plugin/xxxx/qshy/utils/FRUtils.java | 255 ++++++++++++++++++ .../eco/plugin/xxxx/qshy/utils/HttpUtils.java | 243 +++++++++++++++++ .../plugin/xxxx/qshy/utils/ResponseUtils.java | 94 +++++++ .../com/eco/plugin/xxxx/qshy/utils/Utils.java | 226 ++++++++++++++++ .../com/eco/plugin/xxxx/qshy/js/core.js | 34 +++ 15 files changed, 1290 insertions(+), 1 deletion(-) create mode 100644 JSD-8478-需求确认书V1.docx create mode 100644 plugin.xml create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/JsHandler/JSHandler.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/config/InitializeMonitor.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/config/PluginSimpleConfig.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/config/WinkPluginSimpleConfig.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/handler/ExtendAttrHandlerProvider.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/handler/GetQsUrl.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/handler/URLAliasProvide.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/utils/FRUtils.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/utils/HttpUtils.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/utils/ResponseUtils.java create mode 100644 src/main/java/com/eco/plugin/xxxx/qshy/utils/Utils.java create mode 100644 src/main/resources/com/eco/plugin/xxxx/qshy/js/core.js diff --git a/JSD-8478-需求确认书V1.docx b/JSD-8478-需求确认书V1.docx new file mode 100644 index 0000000000000000000000000000000000000000..89bed78cedb3a5a8ac9252d990cefa92515d0ecc GIT binary patch literal 61240 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ڒS8( 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�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

uD#{f-SG>%WLoA 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index bc29aa3..4c349ec 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-8478 -JSD-8478 全时云会议集成 \ No newline at end of file +JSD-8478 全时云会议集成\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..b4ab71d --- /dev/null +++ b/plugin.xml @@ -0,0 +1,24 @@ + + com.eco.plugin.wink.qshy + + yes + 1.0.7 + 10.0 + 2018-07-31 + wink + + + com.eco.plugin.wink.qshy + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/JsHandler/JSHandler.java b/src/main/java/com/eco/plugin/xxxx/qshy/JsHandler/JSHandler.java new file mode 100644 index 0000000..9998f59 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/JsHandler/JSHandler.java @@ -0,0 +1,15 @@ +package com.eco.plugin.xxxx.qshy.JsHandler; + +import com.fr.stable.fun.impl.AbstractJavaScriptFileHandler; + +public class JSHandler extends AbstractJavaScriptFileHandler { + @Override + public String[] pathsForFiles() { + //实测,不论是在core还是report还是form JS都会全部生效,所以标签可以统一使用core即可,移动端不支持,H5不支持 + // 仅对报表访问生效(含决策平台中的报表),决策平台本身不支持这个接口(有其他接口)。 + return new String[]{ + "com/eco/plugin/xxxx/qshy/js/core.js" + }; + } + +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/config/InitializeMonitor.java b/src/main/java/com/eco/plugin/xxxx/qshy/config/InitializeMonitor.java new file mode 100644 index 0000000..dbf0639 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/config/InitializeMonitor.java @@ -0,0 +1,21 @@ +package com.eco.plugin.xxxx.qshy.config; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + +/** + * @author fr.open + * @version 10.0 + * Created by fr.open on 2021-12-03 + */ +public class InitializeMonitor extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + WinkPluginSimpleConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + + } +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/config/PluginSimpleConfig.java b/src/main/java/com/eco/plugin/xxxx/qshy/config/PluginSimpleConfig.java new file mode 100644 index 0000000..8be58bc --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/config/PluginSimpleConfig.java @@ -0,0 +1,123 @@ +package com.eco.plugin.xxxx.qshy.config; + +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.record.analyzer.EnableMetrics; + +@Visualization(category = "单点登录配置") +@EnableMetrics +public class PluginSimpleConfig extends DefaultConfiguration { + + private static volatile PluginSimpleConfig config = null; + + @Focus(id="com.eco.plugin.xxxx.qshy.config", text = "单点登录配置", source = Original.PLUGIN) + public static PluginSimpleConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(PluginSimpleConfig.class); + } + return config; + } + + @Identifier(value = "username", name = "管理员账户", description = "管理员账户", status = Status.SHOW) + private Conf username = Holders.simple("xxxx"); + + @Identifier(value = "psd", name = "管理员密码", description = "管理员密码", status = Status.SHOW) + private Conf psd = Holders.simple("xxxx"); + + @Identifier(value = "role", name = "登录角色", description = "登录角色", status = Status.SHOW) + private Conf role = Holders.simple("5"); + + @Identifier(value = "appid", name = "应用id", description = "应用id", status = Status.SHOW) + private Conf appid = Holders.simple("6"); + + @Identifier(value = "tokenurl", name = "获取凭证接口", description = "获取凭证接口", status = Status.SHOW) + private Conf tokenurl = Holders.simple("http://xxxx/auth/token/create"); + + @Identifier(value = "authurl", name = "获取authKey接口", description = "获取authKey接口", status = Status.SHOW) + private Conf authUrl = Holders.simple("http://xxxx/account/authkey/get"); + + @Identifier(value = "pcurl", name = "pc会议地址", description = "pc会议地址", status = Status.SHOW) + private Conf pcurl = Holders.simple("https://xxxx/space/html/"); + + @Identifier(value = "h5url", name = "h5会议地址", description = "pc会议地址", status = Status.SHOW) + private Conf h5url = Holders.simple("https://xxxx/mobile/html/"); + + + public String getUsername() { + return username.get(); + } + + public void setUsername(String url) { + this.username.set(url); + } + + public String getPsd() { + return psd.get(); + } + + public void setPsd(String url) { + this.psd.set(url); + } + + public String getRole() { + return role.get(); + } + + public void setRole(String url) { + this.role.set(url); + } + + public String getAppid() { + return appid.get(); + } + + public void setAppid(String url) { + this.appid.set(url); + } + + public String getTokenurl() { + return tokenurl.get(); + } + + public void setTokenurl(String url) { + this.tokenurl.set(url); + } + + public String getAuthUrl() { + return authUrl.get(); + } + + public void setAuthUrl(String url) { + this.authUrl.set(url); + } + + public String getPcurl() { + return pcurl.get(); + } + + public void setPcurl(String url) { + this.pcurl.set(url); + } + + public String getH5url() { + return h5url.get(); + } + + public void setH5url(String url) { + this.h5url.set(url); + } + @Override + public Object clone() throws CloneNotSupportedException { + PluginSimpleConfig cloned = (PluginSimpleConfig) super.clone(); +// cloned.text = (Conf) text.clone(); +// cloned.count = (Conf) count.clone(); +// cloned.price = (Conf) price.clone(); +// cloned.time = (Conf) time.clone(); +// cloned.student = (Conf) student.clone(); + return cloned; + } + +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/config/WinkPluginSimpleConfig.java b/src/main/java/com/eco/plugin/xxxx/qshy/config/WinkPluginSimpleConfig.java new file mode 100644 index 0000000..a0d0197 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/config/WinkPluginSimpleConfig.java @@ -0,0 +1,123 @@ +package com.eco.plugin.xxxx.qshy.config; + +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.record.analyzer.EnableMetrics; + +@Visualization(category = "全时配置") +@EnableMetrics +public class WinkPluginSimpleConfig extends DefaultConfiguration { + + private static volatile WinkPluginSimpleConfig config = null; + + @Focus(id="com.eco.plugin.xxxx.qshy.config", text = "全时配置", source = Original.PLUGIN) + public static WinkPluginSimpleConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(WinkPluginSimpleConfig.class); + } + return config; + } + + @Identifier(value = "username", name = "管理员账户", description = "管理员账户", status = Status.SHOW) + private Conf username = Holders.simple("xxxx"); + + @Identifier(value = "psd", name = "管理员密码", description = "管理员密码", status = Status.SHOW) + private Conf psd = Holders.simple("xxxx"); + + @Identifier(value = "role", name = "登录角色", description = "登录角色", status = Status.SHOW) + private Conf role = Holders.simple("5"); + + @Identifier(value = "appid", name = "应用id", description = "应用id", status = Status.SHOW) + private Conf appid = Holders.simple("6"); + + @Identifier(value = "tokenurl", name = "获取凭证接口", description = "获取凭证接口", status = Status.SHOW) + private Conf tokenurl = Holders.simple("http://xxxx/auth/token/create"); + + @Identifier(value = "authurl", name = "获取authKey接口", description = "获取authKey接口", status = Status.SHOW) + private Conf authUrl = Holders.simple("http://xxxx/account/authkey/get"); + + @Identifier(value = "pcurl", name = "pc会议地址", description = "pc会议地址", status = Status.SHOW) + private Conf pcurl = Holders.simple("https://xxxx/space/html/"); + + @Identifier(value = "h5url", name = "h5会议地址", description = "h5会议地址", status = Status.SHOW) + private Conf h5url = Holders.simple("https://xxxx/mobile/html/"); + + + public String getUsername() { + return username.get(); + } + + public void setUsername(String url) { + this.username.set(url); + } + + public String getPsd() { + return psd.get(); + } + + public void setPsd(String url) { + this.psd.set(url); + } + + public String getRole() { + return role.get(); + } + + public void setRole(String url) { + this.role.set(url); + } + + public String getAppid() { + return appid.get(); + } + + public void setAppid(String url) { + this.appid.set(url); + } + + public String getTokenurl() { + return tokenurl.get(); + } + + public void setTokenurl(String url) { + this.tokenurl.set(url); + } + + public String getAuthUrl() { + return authUrl.get(); + } + + public void setAuthUrl(String url) { + this.authUrl.set(url); + } + + public String getPcurl() { + return pcurl.get(); + } + + public void setPcurl(String url) { + this.pcurl.set(url); + } + + public String getH5url() { + return h5url.get(); + } + + public void setH5url(String url) { + this.h5url.set(url); + } + @Override + public Object clone() throws CloneNotSupportedException { + WinkPluginSimpleConfig cloned = (WinkPluginSimpleConfig) super.clone(); +// cloned.text = (Conf) text.clone(); +// cloned.count = (Conf) count.clone(); +// cloned.price = (Conf) price.clone(); +// cloned.time = (Conf) time.clone(); +// cloned.student = (Conf) student.clone(); + return cloned; + } + +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/handler/ExtendAttrHandlerProvider.java b/src/main/java/com/eco/plugin/xxxx/qshy/handler/ExtendAttrHandlerProvider.java new file mode 100644 index 0000000..1157e44 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/handler/ExtendAttrHandlerProvider.java @@ -0,0 +1,13 @@ +package com.eco.plugin.xxxx.qshy.handler; + +import com.fr.decision.fun.HttpHandler; +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; + +public class ExtendAttrHandlerProvider extends AbstractHttpHandlerProvider { + @Override + public HttpHandler[] registerHandlers() { + return new HttpHandler[]{ + new GetQsUrl() + }; + } +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/handler/GetQsUrl.java b/src/main/java/com/eco/plugin/xxxx/qshy/handler/GetQsUrl.java new file mode 100644 index 0000000..20502c0 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/handler/GetQsUrl.java @@ -0,0 +1,101 @@ +package com.eco.plugin.xxxx.qshy.handler; + +import com.eco.plugin.xxxx.qshy.config.WinkPluginSimpleConfig; +import com.eco.plugin.xxxx.qshy.utils.HttpUtils; +import com.eco.plugin.xxxx.qshy.utils.ResponseUtils; +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.stable.fun.Authorize; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@FunctionRecorder +@Authorize(callSignKey = "com.eco.plugin.xxxx.qshy") +public class GetQsUrl extends BaseHttpHandler { + + + public GetQsUrl() { + } + + @Override + public RequestMethod getMethod() { + return RequestMethod.GET; + } + + @Override + public String getPath() { + return "/getQsUrl"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + if(PluginContexts.currentContext().isAvailable()) { + WinkPluginSimpleConfig psc = WinkPluginSimpleConfig.getInstance(); + + //获取请求参数 + String loginname = req.getParameter("loginname"); + boolean isH5 = Boolean.parseBoolean(req.getParameter("isH5")); + + String token = getToken(psc); + JSONObject authInfo = getAuthKey(token,psc,loginname); + String authKey = authInfo.getString("authKey"); + String userid = authInfo.getString("userId"); + + String url = isH5 ? psc.getH5url() : psc.getPcurl(); + + url+="?uid="+userid+"&token="+authKey; + + ResponseUtils.successResponse(res,url); + } + } + + private static JSONObject getAuthKey(String token, WinkPluginSimpleConfig psc, String loginname) { + String url = psc.getAuthUrl(); + + JSONObject param = new JSONObject(); + param.put("username",psc.getUsername()); + param.put("token", token); + + JSONObject data = new JSONObject(); + data.put("expireTime",-1); + + JSONArray loginnames = new JSONArray(); + loginnames.add(loginname); + + data.put("loginnames",loginnames); + + param.put("data",data); + + String result = HttpUtils.HttpPostJson(url,param.toString(),null); + + JSONObject resultJ = new JSONObject(result); + + return resultJ.getJSONArray("data").getJSONObject(0); + } + + private static String getToken(WinkPluginSimpleConfig psc) { + String url = psc.getTokenurl(); + JSONObject param = new JSONObject(); + param.put("username",psc.getUsername()); + param.put("password", psc.getPsd()); + param.put("role", psc.getRole()); + param.put("appId", psc.getAppid()); + + String result = HttpUtils.HttpPostJson(url,param.toString(),null); + JSONObject resultJ = new JSONObject(result); + return resultJ.getJSONObject("data").getString("token"); + } + + +} + diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/handler/URLAliasProvide.java b/src/main/java/com/eco/plugin/xxxx/qshy/handler/URLAliasProvide.java new file mode 100644 index 0000000..3476573 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/handler/URLAliasProvide.java @@ -0,0 +1,14 @@ +package com.eco.plugin.xxxx.qshy.handler; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; + +public class URLAliasProvide extends AbstractURLAliasProvider { + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/getQsUrl","/getQsUrl",true), + }; + } +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/utils/FRUtils.java b/src/main/java/com/eco/plugin/xxxx/qshy/utils/FRUtils.java new file mode 100644 index 0000000..8b7eae7 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/utils/FRUtils.java @@ -0,0 +1,255 @@ +package com.eco.plugin.xxxx.qshy.utils; + +import com.fr.base.ServerConfig; +import com.fr.base.TableData; +import com.fr.decision.authority.AuthorityContext; +import com.fr.decision.authority.data.User; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.decision.webservice.utils.DecisionServiceConstants; +import com.fr.decision.webservice.v10.login.LoginService; +import com.fr.decision.webservice.v10.login.event.LogInOutEvent; +import com.fr.decision.webservice.v10.user.UserService; +import com.fr.event.EventDispatcher; +import com.fr.file.TableDataConfig; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.stable.query.QueryFactory; +import com.fr.stable.query.restriction.RestrictionFactory; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.util.List; + +public class FRUtils { + /** + * 判断用户是否存在 + * @param userName + * @return + */ + public static boolean isUserExist(String userName){ + if (StringUtils.isEmpty(userName)) { + return false; + } else { + try { + List var1 = AuthorityContext.getInstance().getUserController().find(QueryFactory.create().addRestriction(RestrictionFactory.eq("userName", userName))); + return var1 != null && !var1.isEmpty(); + } catch (Exception var2) { + FineLoggerFactory.getLogger().error(var2.getMessage()); + return false; + } + } + } + + /** + * 判断是否登录FR + * @param req + * @return + */ + public static boolean isLogin(HttpServletRequest req){ + return LoginService.getInstance().isLogged(req); + } + + /** + * 帆软登录 + * @param httpServletRequest + * @param httpServletResponse + * @param userName + * @param url + */ + public static void login(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,String userName,String url){ + + FineLoggerFactory.getLogger().info("FRLOG:用户名:"+userName); + FineLoggerFactory.getLogger().info("FRLOG:跳转链接:"+url); + + + //判断用户名是否为空 + if(!Utils.isNullStr(userName)){ + if(isUserExist(userName)){ + String FRToken = ""; + + try { + //HttpSession session = httpServletRequest.getSession(true); + + FRToken = LoginService.getInstance().login(httpServletRequest, httpServletResponse, userName); + + //httpServletRequest.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME,FRToken); + + //session.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, FRToken); + EventDispatcher.fire(LogInOutEvent.LOGIN,new LogInOutResultInfo(httpServletRequest,httpServletResponse,userName,true)); + FineLoggerFactory.getLogger().info("FRLOG:登陆成功!"); + + if(!Utils.isNullStr(url)){ + httpServletResponse.sendRedirect(url); + } + } catch (Exception e) { + ResponseUtils.failedResponse(httpServletResponse,"登录异常,请联系管理员!"); + FineLoggerFactory.getLogger().info("FRLOG:登录异常,请联系管理员!"); + FineLoggerFactory.getLogger().info("FRLOGException:"+e.getMessage()); + } + }else{ + ResponseUtils.failedResponse(httpServletResponse,"用户在报表系统中不存在!"); + FineLoggerFactory.getLogger().info("FRLOG:用户在报表系统中不存在!"); + } + }else{ + ResponseUtils.failedResponse(httpServletResponse,"用户名不能为空!"); + FineLoggerFactory.getLogger().info("FRLOG:用户名不能为空!"); + } + } + + /** + * 帆软登录 + * @param httpServletRequest + * @param httpServletResponse + * @param token + * @param url + */ + public static void loginByToken(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,String token,String url){ + + FineLoggerFactory.getLogger().info("FRLOG:token:"+token); + FineLoggerFactory.getLogger().info("FRLOG:跳转链接:"+url); + + + //判断用户名是否为空 + if(!Utils.isNullStr(token)){ + writeToken2Cookie(httpServletResponse,token,-1); + + HttpSession session = httpServletRequest.getSession(true); + + httpServletRequest.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME,token); + + session.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token); + + if(!Utils.isNullStr(url)){ + try { + httpServletResponse.sendRedirect(url); + } catch (IOException e) { + ResponseUtils.failedResponse(httpServletResponse,"跳转异常!"); + FineLoggerFactory.getLogger().info("FRLOG:跳转异常!"); + } + } + }else{ + ResponseUtils.failedResponse(httpServletResponse,"token不能为空!"); + FineLoggerFactory.getLogger().info("FRLOG:token不能为空!"); + } + } + + /** + * 获取token + * @param httpServletRequest + * @param httpServletResponse + * @param username + * @return + */ + public static String getToken(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,String username){ + String token = ""; + try { + token = LoginService.getInstance().login(httpServletRequest, httpServletResponse, username); + } catch (Exception e) { + FineLoggerFactory.getLogger().info("FRLOG:获取token失败"+e.getMessage()); + } + + return token; + } + + private static void writeToken2Cookie(HttpServletResponse var1, String var2, int var3) { + try { + if (StringUtils.isNotEmpty(var2)) { + Cookie var4 = new Cookie("fine_auth_token", var2); + long var5 = var3 == -2 ? 1209600000L : (long)var3; + var4.setMaxAge((int)var5); + var4.setPath(ServerConfig.getInstance().getCookiePath()); + var1.addCookie(var4); + Cookie var7 = new Cookie("fine_remember_login", String.valueOf(var3 == -2 ? -2 : -1)); + var7.setMaxAge((int)var5); + var7.setPath(ServerConfig.getInstance().getCookiePath()); + var1.addCookie(var7); + } else { + FineLoggerFactory.getLogger().error("empty token cannot save."); + } + } catch (Exception var8) { + FineLoggerFactory.getLogger().error(var8.getMessage(), var8); + } + + } + + /** + * + * @param httpServletRequest + * @param httpServletResponse + */ + public static void logout(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse) + { + if(!isLogin(httpServletRequest)){ + return ; + } + + try { + LoginService.getInstance().logout(httpServletRequest,httpServletResponse); + } catch (Exception e) { + ResponseUtils.failedResponse(httpServletResponse,"登出异常,请联系管理员!"); + FineLoggerFactory.getLogger().info("FRLOG:登出异常,请联系管理员!"); + FineLoggerFactory.getLogger().info("FRLOGException:"+e.getMessage()); + } + } + + /** + * 打印FR日志 + * @param message + */ + public static void FRLogInfo(String message){ + FineLoggerFactory.getLogger().info("FRLOG:"+message); + } + + /** + * 打印FR日志-error + * @param message + */ + public static void FRLogError(String message){ + FineLoggerFactory.getLogger().error("FRLOG:"+message); + } + + + /** + * 根据用户名获取用户信息 + * @param userName + * @return + */ + public static User getFRUserByUserName(String userName){ + try { + return UserService.getInstance().getUserByUserName(userName); + } catch (Exception e) { + FRLogInfo("获取用户信息异常:"+e.getMessage()); + } + + return null; + } + + /** + * 解密FR密码 + * @param password + * @return + */ +// public static String decryptFRPsd(String password){ +// FRLogInfo("解密密码:"+password); +// return TransmissionTool.decrypt(password); +// } + + /** + * 获取带参数的访问链接 + * @return + */ + public static String getAllUrl(HttpServletRequest httpServletRequest){ + return WebUtils.getOriginalURL(httpServletRequest); + } + + public static TableData getTableData(String serverDataSetName){ + TableData userInfo = TableDataConfig.getInstance().getTableData("serverDataSetName"); + +// DataModel userInfoDM = userInfo.createDataModel(Calculator.createCalculator()); + return userInfo; + } +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/utils/HttpUtils.java b/src/main/java/com/eco/plugin/xxxx/qshy/utils/HttpUtils.java new file mode 100644 index 0000000..540a87d --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/utils/HttpUtils.java @@ -0,0 +1,243 @@ +package com.eco.plugin.xxxx.qshy.utils; + +import com.fr.log.FineLoggerFactory; +import com.fr.third.org.apache.http.HttpEntity; +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.CookieStore; +import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity; +import com.fr.third.org.apache.http.client.methods.HttpGet; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.conn.ssl.NoopHostnameVerifier; +import com.fr.third.org.apache.http.entity.StringEntity; +import com.fr.third.org.apache.http.impl.client.BasicCookieStore; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; +import com.fr.third.org.apache.http.impl.client.HttpClients; +import com.fr.third.org.apache.http.impl.cookie.BasicClientCookie; +import com.fr.third.org.apache.http.message.BasicNameValuePair; +import com.fr.third.org.apache.http.ssl.SSLContexts; +import com.fr.third.org.apache.http.ssl.TrustStrategy; +import com.fr.third.org.apache.http.util.EntityUtils; + +import javax.net.ssl.SSLContext; +import javax.servlet.http.Cookie; +import java.io.UnsupportedEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class HttpUtils { + + /** + * httpGet请求 + * @param url + * @return + */ + public static String httpGet(String url,Cookie[] cookies,Map header){ + FineLoggerFactory.getLogger().info("FRLOG:HttpUtils.get--url:"+url); + + //创建httpClient + CloseableHttpClient httpclient = createHttpClient(cookies); + + HttpGet getMethod = new HttpGet(url); + + if(header != null && header.size() > 0){ + Set keySet = header.keySet(); + + for(String key : keySet){ + getMethod.setHeader(key,header.get(key)); + } + } + + try { + HttpResponse response = httpclient.execute(getMethod); + int status =response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); + String returnResult = EntityUtils.toString(entity, "utf-8"); + + FineLoggerFactory.getLogger().info("FRLOG:HttpUtils.get--status:"+status); + FineLoggerFactory.getLogger().info("FRLOG:HttpUtils.get--returnResult:"+returnResult); + + httpclient.close(); + + if (status == HttpStatus.SC_OK) { + return returnResult; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpUtils.get--exception:"+e.getMessage()); + } + + try { + httpclient.close(); + } catch (Exception e) { + FineLoggerFactory.getLogger().info("FRLOG:http关闭异常:"+e.getMessage()); + } + + return ""; + } + + /** + * HttpPost请求 + * @param postMethod + * @return + */ + private static String HttpPost(HttpPost postMethod){ + CloseableHttpClient httpclient = createHttpClient(null); + + try { + HttpResponse response = httpclient.execute(postMethod); + int status = response.getStatusLine().getStatusCode(); + HttpEntity entity = response.getEntity(); + String returnResult = EntityUtils.toString(entity, "utf-8"); + FineLoggerFactory.getLogger().info("FRLOG:HttpPost:status:"+status); + FineLoggerFactory.getLogger().info("FRLOG:HttpPost:returnResult:"+returnResult); + httpclient.close(); + + if (status == HttpStatus.SC_OK) { + return returnResult; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpPost:exception:"+e.getMessage()); + } + + try { + httpclient.close(); + } catch (Exception e) { + FineLoggerFactory.getLogger().info("FRLOG:http关闭异常:"+e.getMessage()); + } + + return ""; + } + + public static String HttpPostXML(String url, String xmlParam){ + FineLoggerFactory.getLogger().info("FRLOG:HttpPostXML:url:"+url); + + HttpPost postMethod = new HttpPost(url); + + postMethod.setHeader("Content-type", "text/html"); + HttpEntity entity2 = null; + try { + entity2 = new StringEntity(xmlParam); + } catch (UnsupportedEncodingException e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpPostXML:参数异常:"+e.getMessage()); + return ""; + } + + postMethod.setEntity(entity2); + + return HttpPost(postMethod); + } + + public static String HttpPostJson(String url, String param,Map header){ + FineLoggerFactory.getLogger().info("FRLOG:HttpPostJSON:url:"+url); + + HttpPost postMethod = new HttpPost(url); + + postMethod.setHeader("Content-Type","application/json"); + + if(header != null && header.size() > 0){ + Set keySet = header.keySet(); + + for(String key : keySet){ + postMethod.setHeader(key,header.get(key)); + } + } + + if(!Utils.isNullStr(param)){ + HttpEntity entity2 = null; + try { + entity2 = new StringEntity(param); + } catch (UnsupportedEncodingException e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpPostJSON:参数异常:"+e.getMessage()); + return ""; + } + + postMethod.setEntity(entity2); + } + + return HttpPost(postMethod); + } + + public static String HttpPostWWWForm(String url, Map header,Map param){ + FineLoggerFactory.getLogger().info("FRLOG:HttpWWWForm:url:"+url); + + HttpPost postMethod = new HttpPost(url); + + if(header != null && header.size() > 0){ + Set keySet = header.keySet(); + + for(String key : keySet){ + postMethod.setHeader(key,header.get(key)); + } + } + + if(param != null && param.size() > 0){ + List params = new ArrayList(param.size()); + + for(Map.Entry map : param.entrySet()){ + params.add(new BasicNameValuePair(map.getKey(), map.getValue())); + } + + try { + postMethod.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); + } catch (UnsupportedEncodingException e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpWWWForm:异常:"+e.getMessage()); + return ""; + } + } + + return HttpPost(postMethod); + } + + private static CloseableHttpClient createHttpClient(Cookie[] cookies){ + + SSLContext sslContext = null; + try { + sslContext = SSLContexts.custom().loadTrustMaterial(null, new TrustStrategy() { + @Override + public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + return true; + } + }).build(); + } catch (Exception e) { + FRUtils.FRLogInfo("exception:"+e.getMessage()); + } + + CloseableHttpClient httpclient = null; + + if(cookies != null && cookies.length > 0){ + CookieStore cookieStore = cookieToCookieStore(cookies); + + httpclient = HttpClients.custom().setSslcontext(sslContext). + setSSLHostnameVerifier(new NoopHostnameVerifier()).setDefaultCookieStore(cookieStore).build(); + } + else{ + httpclient = HttpClients.custom().setSslcontext(sslContext). + setSSLHostnameVerifier(new NoopHostnameVerifier()).build(); + } + + return httpclient; + } + + /** + * cookies转cookieStore + * @param cookies + * @return + */ + public static CookieStore cookieToCookieStore(Cookie[] cookies){ + CookieStore cookieStore = new BasicCookieStore(); + + if(cookies != null && cookies.length>0){ + for(Cookie cookie : cookies){ + BasicClientCookie cookie1 = new BasicClientCookie(cookie.getName(), cookie.getValue()); + cookieStore.addCookie(cookie1); + } + } + + return cookieStore; + } +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/utils/ResponseUtils.java b/src/main/java/com/eco/plugin/xxxx/qshy/utils/ResponseUtils.java new file mode 100644 index 0000000..c493649 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/utils/ResponseUtils.java @@ -0,0 +1,94 @@ +package com.eco.plugin.xxxx.qshy.utils; + +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; + +public class ResponseUtils { + private static final int SUCCESS = 200; + private static final int FAILED = -1; + + public static void successResponse(HttpServletResponse res, String body) { + response(res, body, SUCCESS); + } + + public static void failedResponse(HttpServletResponse res, String body) { + response(res, body, FAILED); + } + + private static void response(HttpServletResponse res, String body, int code) { + JSONObject object = new JSONObject(); + PrintWriter pw; + try { + object.put("code", code); + object.put("data", body); + pw = WebUtils.createPrintWriter(res); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + return; + } + res.setContentType("application/json;charset=utf-8"); + String result = object.toString(); + pw.println(result); + pw.flush(); + pw.close(); + } + + public static void response(HttpServletResponse res,JSONObject json){ + PrintWriter pw; + try { + pw = WebUtils.createPrintWriter(res); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + return; + } + res.setContentType("application/json;charset=utf-8"); + String result = json.toString(); + pw.println(result); + pw.flush(); + pw.close(); + } + + public static void responseXml(HttpServletResponse res,String xml){ + PrintWriter pw; + try { + pw = WebUtils.createPrintWriter(res); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + return; + } + res.setContentType("text/xml;charset=utf-8"); + pw.println(xml); + pw.flush(); + pw.close(); + } + + public static void setCSRFHeader(HttpServletResponse httpServletResponse){ + httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); + httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,HEAD,PUT,PATCH"); + httpServletResponse.setHeader("Access-Control-Max-Age", "36000"); + httpServletResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Authorization,authorization"); + } + + public static void responseJsonp(HttpServletRequest req, HttpServletResponse res, JSONObject json){ + PrintWriter pw; + try { + pw = WebUtils.createPrintWriter(res); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + return; + } + res.setContentType("text/javascript;charset=utf-8;charset=utf-8"); + String result = json.toString(); + + String jsonp=req.getParameter("callback"); + + pw.println(jsonp+"("+result+")"); + pw.flush(); + pw.close(); + } +} diff --git a/src/main/java/com/eco/plugin/xxxx/qshy/utils/Utils.java b/src/main/java/com/eco/plugin/xxxx/qshy/utils/Utils.java new file mode 100644 index 0000000..516cb8a --- /dev/null +++ b/src/main/java/com/eco/plugin/xxxx/qshy/utils/Utils.java @@ -0,0 +1,226 @@ +package com.eco.plugin.xxxx.qshy.utils; + +import com.fr.base.TemplateUtils; +import com.fr.data.NetworkHelper; +import com.fr.io.utils.ResourceIOUtils; +import com.fr.json.JSONObject; +import com.fr.stable.CodeUtils; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.commons.codec.digest.DigestUtils; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class Utils { + + /** + * 判断字符串是否为空 + * @param str + * @return true 空字符串 false 非空字符串 + */ + public static boolean isNullStr(String str){ + return !(str != null && !str.isEmpty() && !"null".equals(str)); + } + + /** + * 判断字符串是否非空 + * @param str + * @return + */ + public static boolean isNotNullStr(String str){ + return !isNullStr(str); + } + + /** + * MD5加密 + * @param str + * @return + */ + public static String getMd5Str(String str) + { + return DigestUtils.md5Hex(str); + } + + /** + * 帆软shaEncode加密 + */ + + public static String shaEncode(String str){ + return CodeUtils.sha256Encode(str); + } + + /** + * 获取uuid + */ + public static String uuid(){ + return UUID.randomUUID().toString(); + } + + /** + * 替换空字符串 + * @param str + * @param replace + * @return + */ + public static String replaceNullStr(String str,String replace){ + if(isNullStr(str)){ + return replace; + } + + return str; + } + + /** + * 获取请求体 + * @param req + * @return + */ + public static JSONObject getRequestBody(HttpServletRequest req){ + StringBuffer sb = new StringBuffer(); + String line = null; + try { + BufferedReader reader = req.getReader(); + while ((line = reader.readLine()) != null) + sb.append(line); + } catch (Exception e) { + FRUtils.FRLogInfo("getRequestBody:exception:"+e.getMessage()); + } + //将空格和换行符替换掉避免使用反序列化工具解析对象时失败 + String jsonString = sb.toString().replaceAll("\\s","").replaceAll("\n",""); + + JSONObject json = new JSONObject(jsonString); + + return json; + } + + /** + * 获取ip + * @return + */ + public static String getIp(HttpServletRequest req){ + String realIp = req.getHeader("X-Real-IP"); + String fw = req.getHeader("X-Forwarded-For"); + if (StringUtils.isNotEmpty(fw) && !"unKnown".equalsIgnoreCase(fw)) { + int var3 = fw.indexOf(","); + return var3 != -1 ? fw.substring(0, var3) : fw; + } else { + fw = realIp; + if (StringUtils.isNotEmpty(realIp) && !"unKnown".equalsIgnoreCase(realIp)) { + return realIp; + } else { + if (StringUtils.isBlank(realIp) || "unknown".equalsIgnoreCase(realIp)) { + fw = req.getHeader("Proxy-Client-IP"); + } + + if (StringUtils.isBlank(fw) || "unknown".equalsIgnoreCase(fw)) { + fw = req.getHeader("WL-Proxy-Client-IP"); + } + + if (StringUtils.isBlank(fw) || "unknown".equalsIgnoreCase(fw)) { + fw = req.getHeader("HTTP_CLIENT_IP"); + } + + if (StringUtils.isBlank(fw) || "unknown".equalsIgnoreCase(fw)) { + fw = req.getHeader("HTTP_X_FORWARDED_FOR"); + } + + if (StringUtils.isBlank(fw) || "unknown".equalsIgnoreCase(fw)) { + fw = req.getRemoteAddr(); + } + + return fw; + } + } + } + + /** + * 根据key获取cookie + * @param req + * @return + */ + public static String getCookieByKey(HttpServletRequest req,String key){ + Cookie[] cookies = req.getCookies(); + String cookie = ""; + + if(cookies == null || cookies.length <=0){ + return ""; + } + + for(int i = 0; i < cookies.length; i++) { + Cookie item = cookies[i]; + if (item.getName().equalsIgnoreCase(key)) { + cookie = item.getValue(); + } + } + + FRUtils.FRLogInfo("cookie:"+cookie); + + return cookie; + } + + /** + * 判断是否是手机端的链接 + * @param req + * @return + */ + public static boolean isMobile(HttpServletRequest req) { + String[] mobileArray = {"iPhone", "iPad", "android", "windows phone", "xiaomi"}; + String userAgent = req.getHeader("user-agent"); + if (userAgent != null && userAgent.toUpperCase().contains("MOBILE")) { + for(String mobile : mobileArray) { + if(userAgent.toUpperCase().contains(mobile.toUpperCase())) { + return true; + } + } + } + return NetworkHelper.getDevice(req).isMobile(); + } + + /** + * 只编码中文 + * @param url + * @return + */ + public static String encodeCH(String url ){ + Matcher matcher = Pattern.compile("[\\u4e00-\\u9fa5]").matcher(url); + + while(matcher.find()){ + String chn = matcher.group(); + url = url.replaceAll(chn, URLEncoder.encode(chn)); + } + + return url; + } + + /** + * 获取web-inf文件夹下的文件 + * filename /resources/ip4enc.properties + */ + public static InputStream getResourcesFile(String filename){ + return ResourceIOUtils.read(filename); + } + + public static void toErrorPage(HttpServletResponse res,String path,Map parameterMap){ + if(parameterMap == null){ + parameterMap = new HashMap(); + } + + try { + String macPage = TemplateUtils.renderTemplate(path, parameterMap); + WebUtils.printAsString(res, macPage); + }catch (Exception e){ + FRUtils.FRLogError("跳转页面异常"); + } + + } +} diff --git a/src/main/resources/com/eco/plugin/xxxx/qshy/js/core.js b/src/main/resources/com/eco/plugin/xxxx/qshy/js/core.js new file mode 100644 index 0000000..e2b3064 --- /dev/null +++ b/src/main/resources/com/eco/plugin/xxxx/qshy/js/core.js @@ -0,0 +1,34 @@ +;!(function(){ + $.extend(FR,{ + /** + * + * @param 全时的用户名, + * @param password 全时的密码,因为密码需要传到后套,所以传递过程加密 + * @param isH5 是不是移动端h5,全时返回的地址会区分移动端和PC + * @param callback 全时的接口最终会返回一个能够直接打开的url地址,这个callback函数默认是直接打开这个返回的地址(注意h5和PC端不同). + * 也需要支持前端自定义这个回调函数, + */ + quanshi:function(userName,password,isH5,callback){ + if(!$.isFunction(callback)){ + callback = function(data){ + var url = data.data; + window.open(url, "_blank"); + } + } + + var username = 'xxxx'; + var isH5 = false + + $.ajax({ + type:"get", + async:false, + url:"/decision/url/getQsUrl?loginname="+username+"&isH5="+isH5, + success:function(data){ + var url = data.data; + window.open(url, "_blank"); + } + }) + } + }) +})(); +