commit 14dadd4e64da10124f45c045c9cc99f3612528fe Author: pioneer Date: Fri Jul 1 14:33:41 2022 +0800 open diff --git a/README.md b/README.md new file mode 100644 index 0000000..fac3e1e --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# open-JSD-10408 + +JSD-10408 挂载bi仪表板url单点登录\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..ff967a2 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,26 @@ + + com.eco.plugin.xxx.dapsso + + yes + 1.0.0 + 10.0 + 2018-07-31 + fr.open + + + com.eco.plugin.xxx.dapsso + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/eco/plugin/xxx/dapsso/AccessKeyConfig.java b/src/main/java/com/eco/plugin/xxx/dapsso/AccessKeyConfig.java new file mode 100644 index 0000000..1448ea7 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxx/dapsso/AccessKeyConfig.java @@ -0,0 +1,65 @@ +package com.eco.plugin.xxx.dapsso; + +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.record.analyzer.EnableMetrics; +import com.fr.stable.StringUtils; + +@Visualization(category = "Plugin-Config_Login") +@EnableMetrics +public class AccessKeyConfig extends DefaultConfiguration { + + public static volatile AccessKeyConfig config = null; + + @Focus(id = "com.eco.plugin.xxx.dapsso", text = "DAP_SSO") + public static AccessKeyConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(AccessKeyConfig.class); + } + return config; + } + + @Identifier(value = "accessKey", name = "Plugin-Config_Property_AccessKey", description = "Plugin-Config_Property_AccessKey_Description", status = Status.SHOW) + private Conf accessKey = Holders.simple(StringUtils.EMPTY); + + @Identifier(value = "authURL", name = "Plugin-Config_Property_AuthURL", description = "Plugin-Config_Property_AuthURL_Description", status = Status.SHOW) + private Conf authURL = Holders.simple(StringUtils.EMPTY); + + @Identifier(value = "redirectURL", name = "Plugin-Config_Property_RedirectURL", description = "Plugin-Config_Property_RedirectURL_Description", status = Status.HIDE) + private Conf redirectURL = Holders.simple(StringUtils.EMPTY); + + public String getAccessKey() { + return accessKey.get(); + } + + public void setAccessKey(String accessKey) { + this.accessKey.set(accessKey); + } + + public String getRedirectURL() { + return redirectURL.get(); + } + + public void setRedirectURL(String redirectURL){ + this.redirectURL.set(redirectURL); + } + + public String getAuthURL() { + return authURL.get(); + } + + public void setAuthURL(String authURL){ + this.authURL.set(authURL); + } + + + @Override + public Object clone() throws CloneNotSupportedException { + AccessKeyConfig cloned = (AccessKeyConfig) super.clone(); +// cloned.appCode = (Conf) appCode.clone(); +// cloned.redirectURL = (Conf) redirectURL.clone(); + return cloned; + } +} diff --git a/src/main/java/com/eco/plugin/xxx/dapsso/DAPLoginFilter.java b/src/main/java/com/eco/plugin/xxx/dapsso/DAPLoginFilter.java new file mode 100644 index 0000000..d52443d --- /dev/null +++ b/src/main/java/com/eco/plugin/xxx/dapsso/DAPLoginFilter.java @@ -0,0 +1,304 @@ +package com.eco.plugin.xxx.dapsso; + +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.decision.webservice.utils.DecisionServiceConstants; +import com.fr.decision.webservice.utils.WebServiceUtils; +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.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.third.org.apache.http.HttpEntity; +import com.fr.third.org.apache.http.ParseException; +import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.entity.StringEntity; +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.message.BasicHeader; +import com.fr.third.org.apache.http.protocol.HTTP; +import com.fr.third.org.apache.http.util.EntityUtils; +import com.fr.web.utils.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; + +public class DAPLoginFilter extends AbstractGlobalRequestFilterProvider { + @Override + public String filterName() { + return "DAP_SSO"; + } + + @Override + public String[] urlPatterns() { +// if (!PluginContexts.currentContext().isAvailable()) { +// FineLoggerFactory.getLogger().info("com.fr.plugin.dap.sso: no lic!"); +// return new String[0]; +// } + FineLoggerFactory.getLogger().info("com.eco.plugin.xxx.dapsso: have lic!"); + return new String[]{"/*"}; + } + + @Override + public void init(FilterConfig filterConfig) { + AccessKeyConfig.getInstance(); + super.init(filterConfig); + } + + public static void main(String[] args) { + String url = "https://xxxx/webroot/decision/v5/design/report/d2db1040ffd641d4aee4b58368c48bcc/view?entryType=5"; + + System.out.println(url.contains("/design/report")); + + + } + + @Override + public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) { + String token = req.getParameter("userToken"); + String requestUrl = WebUtils.getOriginalURL(req); + FineLoggerFactory.getLogger().info("FRLOG:url:"+requestUrl); + if (LoginService.getInstance().isLogged(req)){ + FineLoggerFactory.getLogger().info("FRLOG:已经登录"); + release(req, res, filterChain); + return; + } + + + if (isLocal(req)){ + FineLoggerFactory.getLogger().info("FRLOG:Local"); + release(req, res, filterChain); + return; + } else if (isRelease(req)){ + FineLoggerFactory.getLogger().info("FRLOG:Release"); + release(req, res, filterChain); + return; + } else if(StringUtils.isEmpty(token)){ + FineLoggerFactory.getLogger().info("FRLOG:EmptyToken"); + returnString(res, "Open failed!", "Token is Empty!"); + return; + } + + int length = requestUrl.length(); + if (requestUrl.contains("?userToken")){ + length = requestUrl.indexOf("?userToken"); + } else if (requestUrl.contains("&userToken")){ + length = requestUrl.indexOf("&userToken"); + } + +// FineLoggerFactory.getLogger().info("requestURL -> " + requestUrl); + requestUrl = requestUrl.substring(0, length); + + String username = getUsername(token); + username = username.toLowerCase(); + FineLoggerFactory.getLogger().info("username -> " + username); + + //登录 + login(req, res, username, requestUrl); + + release(req, res, filterChain); + } + + public boolean isRelease(HttpServletRequest request) { + return StringUtils.isEmpty(request.getParameter("userToken")); +// if (StringUtils.isEmpty(request.getParameter("userToken"))){ +// String url = WebUtils.getOriginalURL(request); +// return StringUtils.isEmpty(request.getParameter("viewlet")) && !url.contains("v5/design/report"); +// } +// return false; + } + private void release(HttpServletRequest req, HttpServletResponse res, FilterChain chain) { + try{ + chain.doFilter(req,res); + }catch (Exception e){ + FineLoggerFactory.getLogger().info("FRLOG:filter fail"); + } + } + + private String getUsername(String token) { + AccessKeyConfig config = AccessKeyConfig.getInstance(); + String accessKey = config.getAccessKey(); + String authURL = config.getAuthURL(); + JSONObject param = new JSONObject(); + param.put("accessKey", accessKey); + param.put("userToken", token); + String result = ""; + try { + result = send(authURL + "/api/user/auth", param, "UTF-8"); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("FRLOG -> get user failed"); + return ""; + } + FineLoggerFactory.getLogger().info("FRLOG result -> " + result); + JSONObject jo = new JSONObject(result); + if (jo.containsKey("data")){ + return jo.getJSONObject("data").getString("yumADAccount"); + } + return ""; + } + + /** + * 发送post请求 + * @param url 路径 + * @param jsonObject 参数(json类型) + * @param encoding 编码格式 UTF-8 + * @return + * @throws ParseException + * @throws IOException + */ + public static String send(String url, JSONObject jsonObject, String encoding) throws ParseException, IOException { + String body = ""; + + FineLoggerFactory.getLogger().info("authURL -> " + url); +// FineLoggerFactory.getLogger().info("param -> " + jsonObject.toString()); + //创建httpclient对象 + CloseableHttpClient client = HttpClients.createDefault(); + //创建post方式请求对象 + HttpPost httpPost = new HttpPost(url); + + //装填参数 + StringEntity s = new StringEntity(jsonObject.toString(), "utf-8"); + s.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, + "application/json")); + //设置参数到请求对象中 + httpPost.setEntity(s); +// System.out.println("请求地址:"+url); +// System.out.println("请求参数:"+nvps.toString()); + + //设置header信息 + //指定报文头【Content-type】、【User-Agent】 +// httpPost.setHeader("Content-type", "application/x-www-form-urlencoded"); + httpPost.setHeader("Content-type", "application/json"); + httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"); + + //执行请求操作,并拿到结果(同步阻塞) + CloseableHttpResponse response = client.execute(httpPost); + //获取结果实体 + HttpEntity entity = response.getEntity(); + if (entity != null) { + //按指定编码转换结果实体为String类型 + body = EntityUtils.toString(entity, encoding); + } + EntityUtils.consume(entity); + //释放链接 + response.close(); + FineLoggerFactory.getLogger().info(body); + return body; + } + + public void login(HttpServletRequest request, HttpServletResponse response, String userName, String url){ + FineLoggerFactory.getLogger().info("FRLOG:username -> " + userName); +// FineLoggerFactory.getLogger().info("FRLOG:跳转链接:"+url); + + + //判断用户名是否为空 + if(!StringUtils.isEmpty(userName)){ + if(isUserExist(userName)){ + String FRToken = ""; + + try { + HttpSession session = request.getSession(true); + + FRToken = LoginService.getInstance().login(request, response, userName); + + request.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME,FRToken); + + session.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, FRToken); + EventDispatcher.fire(LogInOutEvent.LOGIN,new LogInOutResultInfo(request,response,userName,true)); + FineLoggerFactory.getLogger().info("FRLOG:Login success!"); + +// if(!StringUtils.isEmpty(url)){ +// response.sendRedirect(url); +// } + } catch (Exception e) { + FineLoggerFactory.getLogger().info("FRLOG -> Login failed!"); + FineLoggerFactory.getLogger().info("FRLOGException:"+e.getMessage()); + + returnString(response, "Open failed!", "Login failed!"); +// returnJSON(response, "Login failed!"); + return; + } + }else{ + FineLoggerFactory.getLogger().info("FRLOG -> user is not exist!"); + returnString(response, "Open failed!", "User is not exist!"); +// returnJSON(response, "User is not exist!"); + return; + } + }else{ + FineLoggerFactory.getLogger().info("FRLOG -> username is empty!"); + returnString(response, "Open failed!", "Token expired!"); +// returnJSON(response, "Token expired!"); + return; + } + } + + public static void returnString(HttpServletResponse res, String notice, String msg) { + try { + String errorHtml = WebServiceUtils.generateErrorWebPage(notice, msg, ""); + WebUtils.printAsString(res,errorHtml); + } catch (Exception e) { + FineLoggerFactory.getLogger().info("return error -> " + e.getMessage()); + } + } + + public void returnJSON(HttpServletResponse res, String msg){ + JSONObject data = new JSONObject(); + data.put("msg", msg); + try { + WebUtils.printAsJSON(res,data); + } catch (Exception e) { + FineLoggerFactory.getLogger().info("return error -> " + e.getMessage()); + } + } + + public boolean isUserExist(String userName){ + try { + if (UserService.getInstance().getUserByUserName(userName) == null){ + return false; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage(), e); + return false; + } + return true; + } + + public static Boolean isLocal(HttpServletRequest request) { + + String ip = request.getHeader("x-forwarded-for"); + if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) { + // 多次反向代理后会有多个ip值,第一个ip才是真实ip + if( ip.indexOf(",")!=-1 ){ + ip = ip.split(",")[0]; + } + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_CLIENT_IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("X-Real-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + FineLoggerFactory.getLogger().info("RealIp -> [{}] ",ip); + return StringUtils.equals(ip, "0:0:0:0:0:0:0:1") || StringUtils.equals(ip, "127.0.0.1"); + } + +} diff --git a/src/main/java/com/eco/plugin/xxx/dapsso/LocaleFinderBridge.java b/src/main/java/com/eco/plugin/xxx/dapsso/LocaleFinderBridge.java new file mode 100644 index 0000000..54e5393 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxx/dapsso/LocaleFinderBridge.java @@ -0,0 +1,10 @@ +package com.eco.plugin.xxx.dapsso; + +import com.fr.stable.fun.impl.AbstractLocaleFinder; + +public class LocaleFinderBridge extends AbstractLocaleFinder { + @Override + public String find() { + return "dap_locale/conf"; + } +} diff --git a/src/main/java/com/eco/plugin/xxx/dapsso/PluginInitializeMonitor.java b/src/main/java/com/eco/plugin/xxx/dapsso/PluginInitializeMonitor.java new file mode 100644 index 0000000..1308f14 --- /dev/null +++ b/src/main/java/com/eco/plugin/xxx/dapsso/PluginInitializeMonitor.java @@ -0,0 +1,17 @@ +package com.eco.plugin.xxx.dapsso; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + + +public class PluginInitializeMonitor extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + AccessKeyConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + + } +} diff --git a/src/main/resources/dap_locale/conf.properties b/src/main/resources/dap_locale/conf.properties new file mode 100644 index 0000000..c334e1c --- /dev/null +++ b/src/main/resources/dap_locale/conf.properties @@ -0,0 +1,8 @@ +Plugin-Config_Login=Login configuration +Plugin-Config_Property_AccessKey=AccessKey +Plugin-Config_Property_AccessKey_Description=Set AccessKey. +Plugin-Config_Property_RedirectURL=RedirectURL +Plugin-Config_Property_RedirectURL_Description=Set RedirectURL. +Plugin-Config_Property_AuthURL=Authorization address +Plugin-Config_Property_AuthURL_Description=Set Authorization address\u3002 +Plugin-Error_Token=No token, access deny. \ No newline at end of file diff --git a/src/main/resources/dap_locale/conf_zh_CN.properties b/src/main/resources/dap_locale/conf_zh_CN.properties new file mode 100644 index 0000000..8f6176e --- /dev/null +++ b/src/main/resources/dap_locale/conf_zh_CN.properties @@ -0,0 +1,8 @@ +Plugin-Config_Login=\u5355\u70B9\u767B\u5F55\u914D\u7F6E +Plugin-Config_Property_AccessKey=AccessKey +Plugin-Config_Property_AccessKey_Description=\u8BBE\u7F6EAccessKey\u3002 +Plugin-Config_Property_RedirectURL=\u65E0\u7528\u6237\u8DF3\u8F6C\u5730\u5740 +Plugin-Config_Property_RedirectURL_Description=\u51B3\u7B56\u5E73\u53F0\u4E2D\u4E0D\u5B58\u5728\u8BE5\u7528\u6237\u65F6\u7684\u8DF3\u8F6C\u5730\u5740\u3002 +Plugin-Config_Property_AuthURL=\u8BA4\u8BC1\u5730\u5740 +Plugin-Config_Property_AuthURL_Description=\u8BBE\u7F6E\u8BA4\u8BC1\u5730\u5740\u3002 +Plugin-Error_Token=\u65E0\u6548\u7684Token\uFF0C\u7981\u6B62\u8BBF\u95EE \ No newline at end of file