diff --git a/README.md b/README.md
index 1313839..75e76ec 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,6 @@
# open-JSD-7889
-JSD-7889 开源任务材料
\ No newline at end of file
+JSD-7889 开源任务材料\
+免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
+仅作为开发者学习参考使用!禁止用于任何商业用途!\
+为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。
\ No newline at end of file
diff --git a/lib/finekit-10.0.jar b/lib/finekit-10.0.jar
new file mode 100644
index 0000000..611c8f5
Binary files /dev/null and b/lib/finekit-10.0.jar differ
diff --git a/plugin.xml b/plugin.xml
new file mode 100644
index 0000000..e6f4f8f
--- /dev/null
+++ b/plugin.xml
@@ -0,0 +1,17 @@
+
+
+ com.fr.plugin.third.party.jsd7889
+
+ yes
+ 0.2
+ 10.0
+ 2019-01-01
+ fr.open
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/fr/plugin/third/party/jsdhiij/RSAEncrypt.java b/src/main/java/com/fr/plugin/third/party/jsdhiij/RSAEncrypt.java
new file mode 100644
index 0000000..d26e444
--- /dev/null
+++ b/src/main/java/com/fr/plugin/third/party/jsdhiij/RSAEncrypt.java
@@ -0,0 +1,50 @@
+package com.fr.plugin.third.party.jsdhiij;
+
+import java.security.KeyFactory;
+import java.security.PublicKey;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+import javax.crypto.Cipher;
+
+public class RSAEncrypt {
+
+ /**Token的Key为FRToken
+ * 解析后的内容为Json格式,类似{"UserNo":"W08709","ExpiredTime":"2021-05-31 13:28:19"}
+ * 其中UserNo为工号,ExpiredTime为有效时长,若超时,请判官为非法访问
+ * @param args
+ * @throws Exception
+ */
+ public static void main(String[] args) throws Exception {
+
+
+ String cryToken="XXX";
+ String pubKey="XXX";
+ String decryToken=decryptByPub(cryToken,pubKey);
+ System.out.print(decryToken);//输出结果为{"UserNo":"W08709","ExpiredTime":"2021-05-31 13:28:19"}
+ }
+ /**
+ * RSA私钥解密
+ *
+ * @param str
+ * 加密字符串
+ * @param publicKey
+ * 私钥
+ * @return 铭文
+ * @throws Exception
+ * 解密过程中的异常信息
+ */
+ public static String decryptByPub(String str, String publicKey) throws Exception{
+ //64位解码加密后的字符串
+ byte[] inputByte = Base64.getDecoder().decode(str.getBytes("UTF-8"));
+ //base64编码的私钥
+ byte[] decoded = Base64.getDecoder().decode(publicKey);
+ PublicKey pubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
+ //RSA解密
+ Cipher cipher = Cipher.getInstance("RSA");
+ cipher.init(Cipher.DECRYPT_MODE, pubKey);
+ String outStr = new String(cipher.doFinal(inputByte));
+ return outStr;
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/fr/plugin/third/party/jsdhiij/config/CustomDataConfig.java b/src/main/java/com/fr/plugin/third/party/jsdhiij/config/CustomDataConfig.java
new file mode 100644
index 0000000..efeda76
--- /dev/null
+++ b/src/main/java/com/fr/plugin/third/party/jsdhiij/config/CustomDataConfig.java
@@ -0,0 +1,45 @@
+package com.fr.plugin.third.party.jsdhiij.config;
+
+
+import com.fr.config.*;
+import com.fr.config.holder.Conf;
+import com.fr.config.holder.factory.Holders;
+
+/**
+ * 配置数据保存
+ */
+@Visualization(category = "单点登录配置")
+public class CustomDataConfig extends DefaultConfiguration {
+ public String getNameSpace() {
+ return this.getClass().getName();
+ }
+
+ private static volatile CustomDataConfig config = null;
+
+ public static CustomDataConfig getInstance() {
+ if (config == null) {
+ config = ConfigContext.getConfigInstance(CustomDataConfig.class);
+ }
+ return config;
+ }
+
+
+ @Identifier(value = "userKey", name = "密钥", description = "", status = Status.SHOW)
+ private Conf userKey = Holders.simple("XXX");
+
+
+ public String getUserKey() {
+ return userKey.get();
+ }
+
+ public void setUserKey(String userKey) {
+ this.userKey.set(userKey);
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ CustomDataConfig cloned = (CustomDataConfig) super.clone();
+ cloned.userKey = (Conf) userKey.clone();
+ return cloned;
+ }
+}
diff --git a/src/main/java/com/fr/plugin/third/party/jsdhiij/config/DataConfigInitializeMonitor.java b/src/main/java/com/fr/plugin/third/party/jsdhiij/config/DataConfigInitializeMonitor.java
new file mode 100644
index 0000000..c98c914
--- /dev/null
+++ b/src/main/java/com/fr/plugin/third/party/jsdhiij/config/DataConfigInitializeMonitor.java
@@ -0,0 +1,19 @@
+package com.fr.plugin.third.party.jsdhiij.config;
+
+import com.fr.plugin.context.PluginContext;
+import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor;
+
+/**
+ * 配置信息初始化
+ */
+public class DataConfigInitializeMonitor extends AbstractPluginLifecycleMonitor {
+ @Override
+ public void afterRun(PluginContext pluginContext) {
+ CustomDataConfig.getInstance();
+ }
+
+ @Override
+ public void beforeStop(PluginContext pluginContext) {
+
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/fr/plugin/third/party/jsdhiij/http/SessionGlobalRequestFilterProvider.java b/src/main/java/com/fr/plugin/third/party/jsdhiij/http/SessionGlobalRequestFilterProvider.java
new file mode 100644
index 0000000..b6840ee
--- /dev/null
+++ b/src/main/java/com/fr/plugin/third/party/jsdhiij/http/SessionGlobalRequestFilterProvider.java
@@ -0,0 +1,186 @@
+package com.fr.plugin.third.party.jsdhiij.http;
+
+import com.fanruan.api.log.LogKit;
+import com.fanruan.api.util.StringKit;
+import com.fr.data.NetworkHelper;
+import com.fr.decision.authority.data.User;
+import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider;
+import com.fr.decision.mobile.terminal.TerminalHandler;
+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.general.ComparatorUtils;
+import com.fr.intelli.record.Focus;
+import com.fr.intelli.record.Original;
+import com.fr.json.JSONObject;
+import com.fr.log.FineLoggerFactory;
+import com.fr.plugin.third.party.jsdhiij.RSAEncrypt;
+import com.fr.plugin.third.party.jsdhiij.config.CustomDataConfig;
+import com.fr.record.analyzer.EnableMetrics;
+
+import javax.servlet.FilterChain;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+@EnableMetrics
+public class SessionGlobalRequestFilterProvider extends AbstractGlobalRequestFilterProvider {
+ @Override
+ public String filterName() {
+ return "com.fr.plugin.third.party.jsd7889";
+ }
+
+ @Override
+ public String[] urlPatterns() {
+ return new String[]{"/decision", "/decision/*"};
+ }
+
+ @Override
+ @Focus(id = "com.fr.plugin.third.party.jsd7889", text = "plugin-jsd-7889", source = Original.PLUGIN)
+ public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
+ try {
+ String fullUrl = getRequestFullUrl(req);
+ String method = req.getMethod();
+ LogKit.info("单点登录,记录访问地址:" + method + " " + fullUrl);
+ //boolean option = isLogged(req);
+ //if (option) {
+ //filterChain.doFilter(req, res);
+ // return;
+ //}
+
+ String loginUsername = getUsernameByCookie(req);
+ if (StringKit.isEmpty(loginUsername)) {
+ filterChain.doFilter(req, res);
+ return;
+ }
+ LogKit.info("单点登录集成,用户名:" + loginUsername );
+ User user = UserService.getInstance().getUserByUserName(loginUsername);
+ boolean tipsOption = false;
+ if (user == null) {
+ tipsOption = true;
+ LogKit.info("单点登录集成,用户名:" + loginUsername + "在报表平台不存在");
+ } else if (!user.isEnable()) {
+ tipsOption = true;
+ LogKit.info("单点登录集成,用户名:" + loginUsername + "在报表平台上被禁用");
+ }
+ if (tipsOption) {
+ filterChain.doFilter(req, res);
+ return;
+ }
+ String loginToken = LoginService.getInstance().login(req, res, loginUsername);
+ req.setAttribute("fine_auth_token", loginToken);
+
+
+ filterChain.doFilter(req, res);
+ } catch (Exception e) {
+ FineLoggerFactory.getLogger().error("单点登录出错," + e.getMessage(), e);
+ }
+ }
+
+ private synchronized String getUsernameByCookie(HttpServletRequest req) {
+ String userId = "";
+ try {
+ String frToken = getCookieValue(req, "FRToken");
+ if (StringKit.isEmpty(frToken)) {
+ return "";
+ }
+ String decryToken = RSAEncrypt.decryptByPub(frToken, CustomDataConfig.getInstance().getUserKey());
+ JSONObject jsonObject = new JSONObject(decryToken);
+ userId = jsonObject.getString("UserNo");
+ } catch (Exception e) {
+ LogKit.error("单点登录:" + e.getMessage(), e);
+ userId = "";
+ }
+ return userId;
+ }
+
+ private String getCookieValue(HttpServletRequest req, String key) {
+ Cookie[] cookies = req.getCookies();
+ if ((cookies == null) || (cookies.length <= 0)) {
+ return "";
+ }
+
+ Cookie cookie;
+ for (int i = 0, max = cookies.length - 1; i <= max; i++) {
+ cookie = cookies[i];
+ if (StringKit.equals(key, cookie.getName())) {
+ return cookie.getValue();
+ }
+ }
+ return "";
+ }
+
+
+ private String getRequestUrl(HttpServletRequest req) {
+ String fullUrl = req.getRequestURL().toString();
+ Map paraMap = req.getParameterMap();
+ String paraName;
+ String[] paraValues;
+ String loginTypeParaName = "token";
+ String queryStr = "";
+ for (Map.Entry entry : paraMap.entrySet()) {
+ paraName = entry.getKey();
+ if (ComparatorUtils.equals(paraName, loginTypeParaName)) {
+ continue;
+ }
+ paraValues = entry.getValue();
+ queryStr = addParaToQuery(queryStr, paraName, paraValues);
+ }
+ if (StringKit.isEmpty(queryStr)) {
+ return fullUrl;
+ }
+ fullUrl = fullUrl + "?" + queryStr;
+ return fullUrl;
+ }
+
+ private String addParaToQuery(String query, String paraName, String[] paraValues) {
+ if (StringKit.isEmpty(paraName)) {
+ return query;
+ }
+ String fullQuery = query;
+ if ((paraValues == null) || (paraValues.length <= 0)) {
+ if (StringKit.isNotEmpty(fullQuery)) {
+ fullQuery = fullQuery + "&";
+ }
+ fullQuery = paraName + "=";
+ return fullQuery;
+ }
+ for (int i = 0, max = paraValues.length - 1; i <= max; i++) {
+ if (StringKit.isNotEmpty(fullQuery)) {
+ fullQuery = fullQuery + "&";
+ }
+ fullQuery = fullQuery + paraName + "=" + paraValues[i];
+ }
+ return fullQuery;
+ }
+
+
+ private String getRequestFullUrl(HttpServletRequest req) {
+ if (req == null) {
+ return "";
+ }
+ String query = req.getQueryString();
+ if ("null".equalsIgnoreCase(query) || StringKit.isEmpty(query)) {
+ query = "";
+ } else {
+ query = "?" + query;
+ }
+ String url = req.getRequestURL().toString() + query;
+ return url;
+ }
+
+ public boolean isLogged(HttpServletRequest req) {
+ boolean logged = true;
+
+ try {
+ String token = TokenResource.COOKIE.getToken(req);
+ LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, NetworkHelper.getDevice(req)));
+ } catch (Exception var4) {
+ logged = false;
+ }
+
+ return logged;
+ }
+
+}