diff --git a/JSD-9446-需求确认书V1.docx b/JSD-9446-需求确认书V1.docx new file mode 100644 index 0000000..6c20099 Binary files /dev/null and b/JSD-9446-需求确认书V1.docx differ diff --git a/JSD-9446配置使用文档.pdf b/JSD-9446配置使用文档.pdf new file mode 100644 index 0000000..d5576c7 Binary files /dev/null and b/JSD-9446配置使用文档.pdf differ diff --git a/README.md b/README.md index b2bd6b4..78a1595 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-9446 -OAuth2 单点 \ No newline at end of file +JSD-9446 OAuth2 单点\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系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..f4482fc 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..5e8bcdd --- /dev/null +++ b/plugin.xml @@ -0,0 +1,25 @@ + + + com.fr.plugin.idnf.sso + + yes + 1.0 + 10.0 + 2018-07-31 + fr.open + + + com.fr.plugin.idnf + + com.fanruan.api + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idnf/LocaleFinder.java b/src/main/java/com/fr/plugin/idnf/LocaleFinder.java new file mode 100644 index 0000000..c5affe1 --- /dev/null +++ b/src/main/java/com/fr/plugin/idnf/LocaleFinder.java @@ -0,0 +1,37 @@ + /* + * Copyright (C), 2018-2020 + * Project: starter + * FileName: LocaleFinder + * Author: Louis + * Date: 2020/8/31 22:19 + */ + package com.fr.plugin.idnf; + + import com.fr.intelli.record.Focus; + import com.fr.intelli.record.Original; + import com.fr.record.analyzer.EnableMetrics; + import com.fr.stable.fun.impl.AbstractLocaleFinder; + + import static com.fr.plugin.idnf.config.IdnfConfig.PLUGIN_ID; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @EnableMetrics + public class LocaleFinder extends AbstractLocaleFinder { + + @Override + @Focus(id = PLUGIN_ID, text = "Plugin-idnf", source = Original.PLUGIN) + public String find() { + return "com/fr/plugin/idnf/locale/lang"; + } + + @Override + public int currentAPILevel() { + return CURRENT_LEVEL; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idnf/PluginMonitor.java b/src/main/java/com/fr/plugin/idnf/PluginMonitor.java new file mode 100644 index 0000000..6feca7b --- /dev/null +++ b/src/main/java/com/fr/plugin/idnf/PluginMonitor.java @@ -0,0 +1,33 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: PluginMonitor + * Author: Louis + * Date: 2021/3/30 15:10 + */ + package com.fr.plugin.idnf; + + import com.fr.plugin.context.PluginContext; + import com.fr.plugin.idnf.config.IdnfConfig; + import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class PluginMonitor extends AbstractPluginLifecycleMonitor { + public PluginMonitor() { + } + + @Override + public void afterRun(PluginContext pluginContext) { + IdnfConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idnf/config/IdnfConfig.java b/src/main/java/com/fr/plugin/idnf/config/IdnfConfig.java new file mode 100644 index 0000000..b88edbd --- /dev/null +++ b/src/main/java/com/fr/plugin/idnf/config/IdnfConfig.java @@ -0,0 +1,43 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: IdnfConfig + * Author: Louis + * Date: 2021/3/30 9:38 + */ + package com.fr.plugin.idnf.config; + + import com.fr.config.*; + import com.fr.config.holder.Conf; + import com.fr.config.holder.factory.Holders; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @Visualization(category = "Plugin-idnf_Group") + public class IdnfConfig extends DefaultConfiguration { + public static final String PLUGIN_ID = "com.fr.plugin.idnf.sso"; + + private static volatile IdnfConfig config = null; + @Identifier(value = "keyCode", name = "Plugin-idnf_Config_KeyCode", description = "Plugin-idnf_Config_KeyCode_Description", status = Status.SHOW) + private final Conf keyCode = Holders.simple("username"); + + public static IdnfConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(IdnfConfig.class); + } + return config; + } + + public String getKeyCode() { + return keyCode.get(); + } + + public void setKeyCode(String keyCode) { + this.keyCode.set(keyCode); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idnf/request/OAuthLogin.java b/src/main/java/com/fr/plugin/idnf/request/OAuthLogin.java new file mode 100644 index 0000000..5cb619e --- /dev/null +++ b/src/main/java/com/fr/plugin/idnf/request/OAuthLogin.java @@ -0,0 +1,118 @@ + /* + * Copyright (C), 2018-2021 + * Project: starter + * FileName: OAuthLogin + * Author: Louis + * Date: 2021/3/30 22:09 + */ + package com.fr.plugin.idnf.request; + + import com.fanruan.api.decision.login.LoginKit; + import com.fanruan.api.decision.user.UserKit; + import com.fanruan.api.i18n.I18nKit; + import com.fanruan.api.log.LogKit; + import com.fanruan.api.net.NetworkKit; + import com.fanruan.api.util.StringKit; + import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; + import com.fr.decision.webservice.utils.DecisionServiceConstants; + import com.fr.decision.webservice.v10.login.LoginService; + import com.fr.plugin.context.PluginContexts; + import com.fr.plugin.idnf.config.IdnfConfig; + import com.fr.stable.fun.Authorize; + + import javax.servlet.FilterChain; + import javax.servlet.FilterConfig; + import javax.servlet.http.HttpServletRequest; + import javax.servlet.http.HttpServletResponse; + + import static com.fr.plugin.idnf.config.IdnfConfig.PLUGIN_ID; + import static com.fr.plugin.idnf.service.AuthController.AUTH_PATH; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @Authorize(callSignKey = PLUGIN_ID) + public class OAuthLogin extends AbstractGlobalRequestFilterProvider { + private IdnfConfig config; + + /** + * 过滤器名称 + * + * @return + */ + @Override + public String filterName() { + return "idnfFilter"; + } + + /** + * 过滤规则 + * + * @return + */ + @Override + public String[] urlPatterns() { + return new String[]{"/decision", "/decision/view/form", "/decision/view/report", "/decision/v10/entry/access/*", "/decision/v5/design/report/*", AUTH_PATH}; + } + + /** + * 过滤器初始化 + * + * @param filterConfig + */ + @Override + public void init(FilterConfig filterConfig) { + this.config = IdnfConfig.getInstance(); + super.init(filterConfig); + } + + /** + * 过滤器处理 + * + * @param request + * @param response + * @param filterChain + */ + @Override + public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) { + try { + operation(request, response); + filterChain.doFilter(request, response); + } catch (Exception e) { + LogKit.error(e.getMessage(), e); + } + } + + /** + * 用户验证登陆操作 + * + * @param req + * @param res + * @throws Exception + */ + private void operation(HttpServletRequest req, HttpServletResponse res) throws Exception { + // 已登录 + if (LoginService.getInstance().isLogged(req)) { + return; + } + String code = NetworkKit.getHTTPRequestParameter(req, this.config.getKeyCode()); + LogKit.info("idnf-OAuthLogin-operation-code:{}", code); + if (StringKit.isBlank(code)) { + return; + } + String username = code; + if (StringKit.isEmpty(username) || !UserKit.existUsername(username)) { + return; + } + if (!PluginContexts.currentContext().isAvailable()) { + LogKit.error(I18nKit.getLocText("Plugin-idnf_Licence_Expired")); + return; + } + String tokenFR = LoginKit.login(req, res, username); + req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, tokenFR); + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idnf/service/AuthController.java b/src/main/java/com/fr/plugin/idnf/service/AuthController.java new file mode 100644 index 0000000..1008f22 --- /dev/null +++ b/src/main/java/com/fr/plugin/idnf/service/AuthController.java @@ -0,0 +1,123 @@ + /* + * Copyright (C), 2018-2022 + * Project: starter + * FileName: AuthController + * Author: Louis + * Date: 2022/1/19 23:47 + */ + package com.fr.plugin.idnf.service; + + import com.fanruan.api.decision.login.LoginKit; + import com.fanruan.api.log.LogKit; + import com.fanruan.api.util.StringKit; + import com.fr.decision.authority.AuthorityContext; + import com.fr.decision.authority.base.constant.type.authority.ViewAuthorityType; + import com.fr.decision.authority.data.Authority; + import com.fr.decision.authority.data.User; + import com.fr.decision.authority.data.extra.ExtraPropertyKey; + import com.fr.decision.finebi.data.user.type.BIDataAnalysisKey; + import com.fr.decision.finebi.data.user.type.BIDataProcessKey; + import com.fr.decision.finebi.data.user.type.BIDesignKey; + import com.fr.decision.finebi.data.user.type.BIViewKey; + import com.fr.decision.webservice.Response; + import com.fr.decision.webservice.annotation.LoginStatusChecker; + import com.fr.decision.webservice.v10.user.UserService; + import com.fr.general.ComparatorUtils; + import com.fr.json.JSONObject; + import com.fr.stable.query.QueryFactory; + import com.fr.third.springframework.stereotype.Controller; + import com.fr.third.springframework.web.bind.annotation.RequestMapping; + import com.fr.third.springframework.web.bind.annotation.RequestMethod; + import com.fr.third.springframework.web.bind.annotation.ResponseBody; + + import javax.servlet.http.HttpServletRequest; + import javax.servlet.http.HttpServletResponse; + import java.util.List; + import java.util.Map; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + @Controller + @RequestMapping("jsd3645") + public class AuthController { + public static final String DECISION_MANAGEMENT_ROOT = "decision-management-root"; + public static final String DECISION_DIRECTORY_ROOT = "decision-directory-root"; + public static final String BI_USE_ROOT = "bi-use-root"; + public static final String AUTH_PATH = "/decision/jsd3645/auth"; + + @RequestMapping(value = "auth", method = RequestMethod.GET) + @ResponseBody + @LoginStatusChecker(required = false) + public Response authGet(HttpServletRequest req, HttpServletResponse res) { + // 跨域设置header + res.setHeader("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); + res.setHeader("Access-Control-Max-Age", "3600"); + res.setHeader("Access-Control-Allow-Headers", "x-requested-with"); + String username = LoginKit.getCurrentUserNameFromRequest(req); + if (StringKit.isBlank(username)) { + username = LoginKit.getCurrentUserNameFromRequestCookie(req); + } + try { + User user = UserService.getInstance().getUserByUserName(username); + JSONObject data = new JSONObject(); + data.put("decisionManagementRoot", isDecisionManagementRoot(user.getId())); + data.put("decisionDirectoryRoot", isDecisionDirectoryRoot(user)); + data.put("biUseRoot", isBiUse(user)); + return (new Response()).status(200).errorCode("0").data(data); + } catch (Exception e) { + LogKit.error(e.getMessage(), e); + } + return (new Response()).status(200).errorCode("1"); + } + + private Boolean isDecisionManagementRoot(String userId) throws Exception { + List authorityList = AuthorityContext.getInstance().getAuthorityController().findByUser(userId, + ViewAuthorityType.TYPE, + QueryFactory.create()); + for (Authority authority : authorityList) { + if (ComparatorUtils.equals(authority.getParentId(), DECISION_MANAGEMENT_ROOT)) { + return true; + } + } + return false; + } + + /** + * @param user + * @return + */ + private Boolean isDecisionDirectoryRoot(User user) { + Map extraPropertyKeyObjectMap = user.getExtraPropertyMap(); + if (extraPropertyKeyObjectMap.containsKey(BIDataAnalysisKey.KEY) + || extraPropertyKeyObjectMap.containsKey(BIDataProcessKey.KEY) + || extraPropertyKeyObjectMap.containsKey(BIDesignKey.KEY) + || extraPropertyKeyObjectMap.containsKey(BIViewKey.KEY) + ) { + return true; + } + return false; + } + + /** + * BI权限 + * + * @param user + * @return + */ + private Boolean isBiUse(User user) { + Map extraPropertyKeyObjectMap = user.getExtraPropertyMap(); + if (extraPropertyKeyObjectMap.containsKey(BIDataAnalysisKey.KEY) + || extraPropertyKeyObjectMap.containsKey(BIDataProcessKey.KEY) + || extraPropertyKeyObjectMap.containsKey(BIDesignKey.KEY) + ) { + return true; + } + return false; + } + } \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/idnf/service/AuthControllerBridge.java b/src/main/java/com/fr/plugin/idnf/service/AuthControllerBridge.java new file mode 100644 index 0000000..914cc61 --- /dev/null +++ b/src/main/java/com/fr/plugin/idnf/service/AuthControllerBridge.java @@ -0,0 +1,27 @@ + /* + * Copyright (C), 2018-2022 + * Project: starter + * FileName: AuthControllerBridge + * Author: Louis + * Date: 2022/1/19 23:45 + */ + package com.fr.plugin.idnf.service; + + import com.fr.decision.fun.impl.AbstractControllerRegisterProvider; + + /** + *
+ * + * + * @author fr.open + * @since 1.0.0 + */ + public class AuthControllerBridge extends AbstractControllerRegisterProvider { + + @Override + public Class[] getControllers() { + return new Class[]{ + AuthController.class + }; + } + } \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/idnf/locale/lang.properties b/src/main/resources/com/fr/plugin/idnf/locale/lang.properties new file mode 100644 index 0000000..86721f9 --- /dev/null +++ b/src/main/resources/com/fr/plugin/idnf/locale/lang.properties @@ -0,0 +1,11 @@ +Plugin-idnf=Sso Plugin +Plugin-idnf_Group=Sso Plugin +Plugin-idnf_Config_KeyCode=Key Code +Plugin-idnf_Config_KeyCode_Description=Key Code +Plugin-idnf_Licence_Expired=Sso Plugin Licence Expired +Plugin-idnf_Config_ClientId=Client Id +Plugin-idnf_Config_ClientId_Description=Client Id +Plugin-idnf_Config_ClientSecret=Client Secret +Plugin-idnf_Config_ClientSecret_Description=Client Secret +Plugin-idnf_Config_FrUri=FR Uri +Plugin-idnf_Config_FrUri_Description=FR Uri \ No newline at end of file diff --git a/src/main/resources/com/fr/plugin/idnf/locale/lang_zh_CN.properties b/src/main/resources/com/fr/plugin/idnf/locale/lang_zh_CN.properties new file mode 100644 index 0000000..6dc6059 --- /dev/null +++ b/src/main/resources/com/fr/plugin/idnf/locale/lang_zh_CN.properties @@ -0,0 +1,11 @@ +Plugin-idnf=\u5355\u70B9\u767B\u9646\u63D2\u4EF6 +Plugin-idnf_Group=\u5355\u70B9\u767B\u9646\u63D2\u4EF6 +Plugin-idnf_Config_KeyCode=Key Code +Plugin-idnf_Config_KeyCode_Description=Key Code +Plugin-idnf_Licence_Expired=\u5355\u70B9\u767B\u9646\u63D2\u4EF6\u8BB8\u53EF\u8FC7\u671F +Plugin-idnf_Config_ClientId=\u5E94\u7528\u6CE8\u518CID +Plugin-idnf_Config_ClientId_Description=\u5E94\u7528\u6CE8\u518CID +Plugin-idnf_Config_ClientSecret=\u5E94\u7528\u6CE8\u518C\u5BC6\u7801 +Plugin-idnf_Config_ClientSecret_Description=\u5E94\u7528\u6CE8\u518C\u5BC6\u7801 +Plugin-idnf_Config_FrUri=\u5E06\u8F6F\u7CFB\u7EDFurl +Plugin-idnf_Config_FrUri_Description=\u5E06\u8F6F\u7CFB\u7EDFurl \ No newline at end of file