From e12c80b192285a4b3f96e57f190c2f25c1008070 Mon Sep 17 00:00:00 2001 From: pioneer Date: Tue, 8 Nov 2022 15:03:45 +0800 Subject: [PATCH] open --- README.md | 7 + plugin.xml | 22 ++ .../wink/bjsso/config/InitializeMonitor.java | 21 ++ .../wink/bjsso/config/PluginSimpleConfig.java | 123 ++++++ .../plugin/wink/bjsso/filter/SSOFilter.java | 169 +++++++++ .../eco/plugin/wink/bjsso/logout/Logout.java | 21 ++ .../plugin/wink/bjsso/utils/EncryptUtils.java | 349 ++++++++++++++++++ .../eco/plugin/wink/bjsso/utils/FRUtils.java | 320 ++++++++++++++++ .../plugin/wink/bjsso/utils/HttpUtils.java | 265 +++++++++++++ .../wink/bjsso/utils/ResponseUtils.java | 108 ++++++ .../eco/plugin/wink/bjsso/utils/Utils.java | 283 ++++++++++++++ .../xx/bjsso/config/InitializeMonitor.java | 21 ++ .../xx/bjsso/config/PluginSimpleConfig.java | 123 ++++++ .../eco/plugin/xx/bjsso/filter/SSOFilter.java | 169 +++++++++ .../eco/plugin/xx/bjsso/logout/Logout.java | 21 ++ .../plugin/xx/bjsso/utils/EncryptUtils.java | 349 ++++++++++++++++++ .../eco/plugin/xx/bjsso/utils/FRUtils.java | 320 ++++++++++++++++ .../eco/plugin/xx/bjsso/utils/HttpUtils.java | 265 +++++++++++++ .../plugin/xx/bjsso/utils/ResponseUtils.java | 108 ++++++ .../com/eco/plugin/xx/bjsso/utils/Utils.java | 283 ++++++++++++++ 使用手册.docx | Bin 0 -> 145287 bytes 21 files changed, 3347 insertions(+) create mode 100644 README.md create mode 100644 plugin.xml create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/config/InitializeMonitor.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/config/PluginSimpleConfig.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/filter/SSOFilter.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/logout/Logout.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/utils/EncryptUtils.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/utils/FRUtils.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/utils/HttpUtils.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/utils/ResponseUtils.java create mode 100644 src/main/java/com/eco/plugin/wink/bjsso/utils/Utils.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/config/InitializeMonitor.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/config/PluginSimpleConfig.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/filter/SSOFilter.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/logout/Logout.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/utils/EncryptUtils.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/utils/FRUtils.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/utils/HttpUtils.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/utils/ResponseUtils.java create mode 100644 src/main/java/com/eco/plugin/xx/bjsso/utils/Utils.java create mode 100644 使用手册.docx diff --git a/README.md b/README.md new file mode 100644 index 0000000..6be5f21 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ + +# open-JSD-9865 + +JSD-9865 PC单点+移动端h5单点\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..a91febf --- /dev/null +++ b/plugin.xml @@ -0,0 +1,22 @@ + + com.eco.plugin.xx.bjsso + + yes + 1.0.1 + 10.0 + 2018-07-31 + fr.open + + + com.eco.plugin.xx.bjsso + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/eco/plugin/wink/bjsso/config/InitializeMonitor.java b/src/main/java/com/eco/plugin/wink/bjsso/config/InitializeMonitor.java new file mode 100644 index 0000000..9b33867 --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/config/InitializeMonitor.java @@ -0,0 +1,21 @@ +package com.eco.plugin.xx.bjsso.config; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + +/** + * @author xx + * @version 10.0 + * Created by xx on 2021-12-03 + */ +public class InitializeMonitor extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + PluginSimpleConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + + } +} diff --git a/src/main/java/com/eco/plugin/wink/bjsso/config/PluginSimpleConfig.java b/src/main/java/com/eco/plugin/wink/bjsso/config/PluginSimpleConfig.java new file mode 100644 index 0000000..952247e --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/config/PluginSimpleConfig.java @@ -0,0 +1,123 @@ +package com.eco.plugin.xx.bjsso.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.xx.bjsso.config", text = "单点登录配置", source = Original.PLUGIN) + public static PluginSimpleConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(PluginSimpleConfig.class); + } + return config; + } + + @Identifier(value = "clientId", name = "应用名称", description = "应用名称", status = Status.SHOW) + private Conf clientId = Holders.simple(""); + + @Identifier(value = "key", name = "订阅id", description = "订阅id", status = Status.SHOW) + private Conf key = Holders.simple(""); + + @Identifier(value = "authUrl", name = "获取授权码接口", description = "获取授权码接口", status = Status.SHOW) + private Conf authUrl = Holders.simple(""); + + @Identifier(value = "tokenUrl", name = "校验授权码接口", description = "校验授权码接口", status = Status.SHOW) + private Conf tokenUrl = Holders.simple(""); + + @Identifier(value = "logoutUrl", name = "登出接口", description = "登出接口", status = Status.SHOW) + private Conf logoutUrl = Holders.simple(""); + + @Identifier(value = "paramname", name = "token参数名(直接加密方式)", description = "token参数名(直接加密方式)", status = Status.SHOW) + private Conf paramname = Holders.simple(""); + + @Identifier(value = "timeout", name = "token超时时间(直接加密方式)", description = "token超时时间(直接加密方式)", status = Status.SHOW) + private Conf timeout = Holders.simple(""); + + @Identifier(value = "privatekey", name = "解密密钥(直接加密方式)", description = "解密密钥(直接加密方式)", status = Status.SHOW) + private Conf privatekey = Holders.simple(""); + + public String getClientId() { + return clientId.get(); + } + + public void setClientId(String url) { + this.clientId.set(url); + } + + public String getKey() { + return key.get(); + } + + public void setKey(String url) { + this.key.set(url); + } + + public String getAuthUrl() { + return authUrl.get(); + } + + public void setAuthUrl(String url) { + this.authUrl.set(url); + } + + public String getTokenUrl() { + return tokenUrl.get(); + } + + public void setTokenUrl(String url) { + this.tokenUrl.set(url); + } + + public String getLogoutUrl() { + return logoutUrl.get(); + } + + public void setLogoutUrl(String url) { + this.logoutUrl.set(url); + } + + public String getParamname() { + return paramname.get(); + } + + public void setParamname(String url) { + this.paramname.set(url); + } + + public String getTimeout() { + return timeout.get(); + } + + public void setTimeout(String url) { + this.timeout.set(url); + } + + public String getPrivatekey() { + return privatekey.get(); + } + + public void setPrivatekey(String url) { + this.privatekey.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/wink/bjsso/filter/SSOFilter.java b/src/main/java/com/eco/plugin/wink/bjsso/filter/SSOFilter.java new file mode 100644 index 0000000..326e8a3 --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/filter/SSOFilter.java @@ -0,0 +1,169 @@ +package com.eco.plugin.xx.bjsso.filter; + +import com.eco.plugin.xx.bjsso.config.PluginSimpleConfig; +import com.eco.plugin.xx.bjsso.utils.*; +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.json.JSONObject; +import com.fr.plugin.context.PluginContexts; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.stable.fun.Authorize; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@EnableMetrics +@Authorize(callSignKey = "com.eco.plugin.xx.bjsso") +public class SSOFilter extends AbstractGlobalRequestFilterProvider { + @Override + public String filterName() { + return "bjssoFilter"; + } + + @Override + public String[] urlPatterns() { + return new String[]{"/*"}; + } + + @Override + public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain ){ + + if(PluginContexts.currentContext().isAvailable()){ + PluginSimpleConfig psc = PluginSimpleConfig.getInstance(); + String token = req.getParameter(psc.getParamname()); + + //如果存在token参数,走加密单点 + if(Utils.isNotNullStr(token)){ + //直接加密用户名的方式 + jmsso(req,res,psc); + return ; + } + + //是否放行 + if(isRelease(req)){ + release(req,res,chain); + return ; + } + + //oauth2单点 + oauthsso(req,res,psc); + } + + release(req,res,chain); + } + + private void oauthsso(HttpServletRequest req, HttpServletResponse res, PluginSimpleConfig psc) { + String code = req.getParameter("code"); + + if(Utils.isNullStr(code)){ + //跳转认证中心 + redirect(req,res,psc); + return; + } + + //获取用户名 + String username = getToken(code,psc,req); + String url = Utils.removeParam(FRUtils.getAllUrl(req),"code"); + + //登录 + FRUtils.login(req,res,username,url); + } + + /** + * 加密用户名方式 + * @param req + * @param res + * @param psc + */ + private void jmsso(HttpServletRequest req, HttpServletResponse res, PluginSimpleConfig psc) { + String token = req.getParameter(psc.getParamname()); + String privatekey = Utils.trim(psc.getPrivatekey()); + String mwtoken = null; + try { + mwtoken = EncryptUtils.rsaDecrypt(token,privatekey); + } catch (Exception e) { + ResponseUtils.failedResponse(res,"token解密失败:"+e.getMessage()); + return ; + } + + if(Utils.isNullStr(mwtoken)){ + ResponseUtils.failedResponse(res,"token解密失败!"); + return ; + } + + JSONObject tokenJson = new JSONObject(mwtoken); + Long now = System.currentTimeMillis(); + Long timestamp = tokenJson.getLong("timestamp"); + + FRUtils.FRLogInfo("now:"+now+";timestamp:"+timestamp); + + if((now - timestamp)/1000 > Long.parseLong(psc.getTimeout())){ + ResponseUtils.failedResponse(res,"token超时!"); + return ; + } + + String username = tokenJson.getString("username"); + String url = Utils.encodeCH(Utils.removeParam(FRUtils.getAllUrl(req),psc.getParamname())); + + FRUtils.login(req,res,username,url); + } + + private boolean isRelease(HttpServletRequest req) { + String url = FRUtils.getAllUrl(req); + String reft = req.getParameter("ref_t"); + + boolean isLogin = FRUtils.isLogin(req); + boolean isRemote = url.contains("remote"); + boolean isLoginPage = url.contains("login")||url.contains("decision/file")||url.contains("decision/resource")||url.contains("decision/system")||url.contains("query/ip"); + boolean isViewlt = "design".equals(reft); +// boolean isViewlt = url.contains("viewlet") || "design".equals(reft) || url.contains("view/report") || url.contains("view/form"); + return isLogin || isRemote || isLoginPage || isViewlt; + } + + //跳转认证中心 + private void redirect(HttpServletRequest req,HttpServletResponse res, PluginSimpleConfig psc) { + String authurl = psc.getAuthUrl()+"?app="+psc.getClientId()+"&subscription-key="+psc.getKey()+"&original-url="+FRUtils.getAllUrl(req)+"&pfidpadapterid=ad..OAuth"; + + try { + res.sendRedirect(authurl); + } catch (IOException e) { + FRUtils.FRLogInfo("跳转认证中心异常:"+e.getMessage()); + } + } + + //获取token + private String getToken(String code,PluginSimpleConfig psc,HttpServletRequest req) { + String tokenurl = psc.getTokenUrl(); + JSONObject param = new JSONObject(); + String url = Utils.removeParam(FRUtils.getAllUrl(req),"code"); + param.put("app",psc.getClientId()); + param.put("code",code); + param.put("redirectUri",url); + + String result = HttpUtils.HttpPostJson(tokenurl,param.toString(),null); + + if(Utils.isNullStr(result)){ + return ""; + } + + JSONObject json = new JSONObject(result); + + if(json == null ){ + return ""; + } + + String token = json.getString("username"); + return token; + } + + //放行拦截器 + private void release(HttpServletRequest req, HttpServletResponse res, FilterChain chain) { + try{ + chain.doFilter(req,res); + }catch (Exception e){ + FRUtils.FRLogInfo("拦截失败"); + } + } +} + diff --git a/src/main/java/com/eco/plugin/wink/bjsso/logout/Logout.java b/src/main/java/com/eco/plugin/wink/bjsso/logout/Logout.java new file mode 100644 index 0000000..2e2a26b --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/logout/Logout.java @@ -0,0 +1,21 @@ +package com.eco.plugin.xx.bjsso.logout; + +import com.eco.plugin.xx.bjsso.config.PluginSimpleConfig; +import com.fr.decision.fun.impl.AbstractLogInOutEventProvider; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.decision.webservice.v10.login.LoginService; + +import javax.servlet.http.HttpSession; + +public class Logout extends AbstractLogInOutEventProvider { + + @Override + public String logoutAction(LogInOutResultInfo result) { + HttpSession session = result.getRequest().getSession(true); + LoginService.getInstance().crossDomainLogout(result.getRequest(),result.getResponse(),""); + session.invalidate(); + PluginSimpleConfig psc = PluginSimpleConfig.getInstance(); + return psc.getLogoutUrl()+ "?app="+psc.getClientId()+"&subscription-key="+psc.getKey(); + } +} + diff --git a/src/main/java/com/eco/plugin/wink/bjsso/utils/EncryptUtils.java b/src/main/java/com/eco/plugin/wink/bjsso/utils/EncryptUtils.java new file mode 100644 index 0000000..ffeeebb --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/utils/EncryptUtils.java @@ -0,0 +1,349 @@ +package com.eco.plugin.xx.bjsso.utils; + +import com.fr.log.FineLoggerFactory; +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import java.io.IOException; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +public class EncryptUtils { + + /** + * sha 加密 + * @param str + * @return + */ + public static String sha(String str){ + String sha256Str = ""; + + try { + MessageDigest sha256Deget = MessageDigest.getInstance("SHA-256"); + byte[] sha256Encode = sha256Deget.digest(str.getBytes()); + sha256Str = ByteToHexStr(sha256Encode); + }catch (Exception e){ + FineLoggerFactory.getLogger().info("FRLOG:SHA256加密异常:"+e.getMessage()); + } + + return sha256Str; + } + + /** + * byte数组转16进制字符串 + * @param bytes + * @return + */ + private static String ByteToHexStr(byte[] bytes) + { + String hexStr = ""; + + for(int i =0;i= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') + || c == '+' || c == '/' || c == '=') { + continue; + } + else { + return false; + } + } + + return true; + } + } + + /** + * des加密 + * @param datasource + * @param password + * @return + */ + public static String desEncrypt(String datasource, String password) { + try { + SecureRandom random = new SecureRandom(); + DESKeySpec desKey = new DESKeySpec(password.getBytes()); + // 创建一个密匙工厂,然后用它把DESKeySpec转换成 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey securekey = keyFactory.generateSecret(desKey); + // Cipher对象实际完成加密操作 + Cipher cipher = Cipher.getInstance("DES"); + // 用密匙初始化Cipher对象 + cipher.init(Cipher.ENCRYPT_MODE, securekey, random); + // 现在,获取数据并加密 + // 正式执行加密操作 + return base64Encode(cipher.doFinal(datasource.getBytes())); + } catch (Throwable e) { + FRUtils.FRLogInfo("des 加密异常 " + e.getMessage()); + } + + return null; + } + + /** + * des 解密 + * @param src + * @param password + * @return + * @throws Exception + */ + public static String desDecrypt(String src, String password) throws Exception { + // DES算法要求有一个可信任的随机数源 + SecureRandom random = new SecureRandom(); + // 创建一个DESKeySpec对象 + DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8")); + // 创建一个密匙工厂 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + // 将DESKeySpec对象转换成SecretKey对象 + SecretKey securekey = keyFactory.generateSecret(desKey); + // Cipher对象实际完成解密操作 + Cipher cipher = Cipher.getInstance("DES"); + // 用密匙初始化Cipher对象 + cipher.init(Cipher.DECRYPT_MODE, securekey, random); + // 真正开始解密操作 + return new String(cipher.doFinal(base64DecodeB(src))); + } + + /** + * 随机生成RSA密钥对 + * @throws NoSuchAlgorithmException + * @return privateKey,publicKey + */ + public static Map genRSAKeyPair() throws NoSuchAlgorithmException { + // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + // 初始化密钥对生成器,密钥大小为96-1024位 + keyPairGen.initialize(1024,new SecureRandom()); + // 生成一个密钥对,保存在keyPair中 + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥 + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥 + String publicKeyString = base64Encode(publicKey.getEncoded()); + // 得到私钥字符串 + String privateKeyString = base64Encode(privateKey.getEncoded()); + // 将公钥和私钥保存到Map + Map result = new HashMap(); + result.put("publicKey",publicKeyString.replaceAll("\n","").replace("\r","").trim()); + result.put("privateKey",privateKeyString.replaceAll("\n","").replace("\r","").trim()); + + return result; + } + + /** + * rsa 加密 + * @param str + * @param publicKey + * @return + * @throws Exception + */ + public static String rsaEncrypt(String str,String publicKey) throws Exception { + //base64编码的公钥 + byte[] decoded = base64DecodeB(publicKey); + RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); + //RSA加密 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, pubKey); + String outStr = base64Encode(cipher.doFinal(str.getBytes("UTF-8"))); + return outStr; + } + + /** + * rsa解密 + * @param str + * @param privateKey + * @return + * @throws Exception + */ + public static String rsaDecrypt(String str,String privateKey) throws Exception { + //64位解码加密后的字符串 + byte[] inputByte = base64DecodeB(str); + //base64编码的私钥 + byte[] decoded = base64DecodeB(privateKey); + RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + //RSA解密 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, priKey); + String outStr = new String(cipher.doFinal(inputByte)); + return outStr; + } + + public static void main(String[] args) throws Exception { + Map keys =genRSAKeyPair(); + String publicKey = keys.get("publicKey"); + String privateKey = keys.get("privateKey"); + + System.out.println(publicKey); + System.out.println(privateKey); + +// JSONObject json = new JSONObject(); +// json.put("username","xiamaofa"); +// json.put("timestamp",111111111); +// +// String jsonstr =json.toString(); +// String encrypt = rsaEncrypt(jsonstr,publicKey); +// String decrypt = rsaDecrypt(encrypt,privateKey); +// +// System.out.println(decrypt); + } +} diff --git a/src/main/java/com/eco/plugin/wink/bjsso/utils/FRUtils.java b/src/main/java/com/eco/plugin/wink/bjsso/utils/FRUtils.java new file mode 100644 index 0000000..ac5ab84 --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/utils/FRUtils.java @@ -0,0 +1,320 @@ +package com.eco.plugin.xx.bjsso.utils; + +import com.fr.base.ServerConfig; +import com.fr.base.TableData; +import com.fr.base.TemplateUtils; +import com.fr.decision.authority.AuthorityContext; +import com.fr.decision.authority.base.constant.type.operation.ManualOperationType; +import com.fr.decision.authority.data.User; +import com.fr.decision.base.util.UUIDUtil; +import com.fr.decision.privilege.encrpt.PasswordValidator; +import com.fr.decision.webservice.bean.authentication.OriginUrlResponseBean; +import com.fr.decision.webservice.interceptor.handler.ReportTemplateRequestChecker; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.decision.webservice.utils.DecisionServiceConstants; +import com.fr.decision.webservice.utils.DecisionStatusService; +import com.fr.decision.webservice.utils.UserSourceFactory; +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.general.data.DataModel; +import com.fr.log.FineLoggerFactory; +import com.fr.script.Calculator; +import com.fr.stable.StringUtils; +import com.fr.stable.query.QueryFactory; +import com.fr.stable.query.restriction.RestrictionFactory; +import com.fr.third.springframework.web.method.HandlerMethod; +import com.fr.web.controller.ReportRequestService; +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 getDBPsd(String username,String password){ + PasswordValidator pv = UserSourceFactory.getInstance().getUserSource(ManualOperationType.KEY).getPasswordValidator(); + String uuid = UUIDUtil.generate(); + + return pv.encode(username, password, uuid); + } + + /** + * 获取带参数的访问链接 + * @return + */ + public static String getAllUrl(HttpServletRequest httpServletRequest){ + return WebUtils.getOriginalURL(httpServletRequest); + } + + /** + * 根据originKey获取源链接 + * @param originKey + * @return + * @throws Exception + */ + public static String getOriginUrl(String originKey) throws Exception { + if (StringUtils.isNotEmpty(originKey)) { + OriginUrlResponseBean originUrlResponseBean = (OriginUrlResponseBean) DecisionStatusService.originUrlStatusService().get(originKey); + DecisionStatusService.originUrlStatusService().delete(originKey); + if (originUrlResponseBean != null) { + return originUrlResponseBean.getOriginUrl(); + } + } + + return new OriginUrlResponseBean(TemplateUtils.render("${fineServletURL}")).getOriginUrl(); + } + + /** + * 判断是否开启模板认证 + * @param + * @return + * @throws Exception + */ + public static boolean isTempAuth(HttpServletRequest req,HttpServletResponse res) throws Exception { + ReportTemplateRequestChecker checker = new ReportTemplateRequestChecker(); + HandlerMethod hm = new HandlerMethod(new ReportRequestService(),ReportRequestService.class.getMethod("preview", HttpServletRequest.class, HttpServletResponse.class, String.class)); + return checker.checkRequest(req,res,hm); + } + + /** + * 获取数据集数据 + * @param serverDataSetName + * @return + */ + public static DataModel getTableData(String serverDataSetName){ + TableData userInfo = TableDataConfig.getInstance().getTableData(serverDataSetName); + DataModel userInfoDM = userInfo.createDataModel(Calculator.createCalculator()); +// userInfoDM.getRowCount(); +// userInfoDM.getColumnIndex(); +// userInfoDM.getValueAt() + return userInfoDM; + } + + public static String getIndex(HttpServletRequest req){ + String url = req.getScheme()+"://"+req.getServerName()+":"+String.valueOf(req.getServerPort())+req.getRequestURI(); + return url; + } +} diff --git a/src/main/java/com/eco/plugin/wink/bjsso/utils/HttpUtils.java b/src/main/java/com/eco/plugin/wink/bjsso/utils/HttpUtils.java new file mode 100644 index 0000000..46c714b --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/utils/HttpUtils.java @@ -0,0 +1,265 @@ +package com.eco.plugin.xx.bjsso.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.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +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 HttpPostText(String url, String xmlParam){ + FineLoggerFactory.getLogger().info("FRLOG:HttpPostText:url:"+url); + + HttpPost postMethod = new HttpPost(url); + + postMethod.setHeader("Content-type", "text/plain"); + HttpEntity entity2 = null; + try { + entity2 = new StringEntity(xmlParam); + } catch (UnsupportedEncodingException e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpPostText:参数异常:"+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/wink/bjsso/utils/ResponseUtils.java b/src/main/java/com/eco/plugin/wink/bjsso/utils/ResponseUtils.java new file mode 100644 index 0000000..ff0916b --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/utils/ResponseUtils.java @@ -0,0 +1,108 @@ +package com.eco.plugin.xx.bjsso.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 responseText(HttpServletResponse res,String text){ + PrintWriter pw; + try { + pw = WebUtils.createPrintWriter(res); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + return; + } + res.setContentType("text/html;charset=utf-8"); + pw.println(text); + 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/wink/bjsso/utils/Utils.java b/src/main/java/com/eco/plugin/wink/bjsso/utils/Utils.java new file mode 100644 index 0000000..444cd27 --- /dev/null +++ b/src/main/java/com/eco/plugin/wink/bjsso/utils/Utils.java @@ -0,0 +1,283 @@ +package com.eco.plugin.xx.bjsso.utils; + +import com.fr.base.TemplateUtils; +import com.fr.data.NetworkHelper; +import com.fr.decision.webservice.v10.user.UserService; +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); + } + + /** + * + * @param res + * @param path /com/fr/plugin/loginAuth/html/getMac.html + * @param parameterMap + */ + 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("跳转页面异常"); + } + + } + + /** + * 判断是否是管理员 + * @param username + * @return + */ + public static boolean isAdmin(String username) throws Exception{ + return UserService.getInstance().isAdmin(UserService.getInstance().getUserByUserName(username).getId()); + } + + /** + * 去掉浏览器中的参数 + * @param url + * @param param + * @return + */ + public static String removeParam(String url,String param){ + if(!url.contains("?"+param) && !url.contains("&"+param)){ + return url; + } + + return url.substring(0,url.indexOf(url.contains("?"+param) ? "?"+param : "&"+param)); + } + + /** + * 获取跳转链接 + * @param req + * @param param + * @return + */ + public static String getRedirectUrl(HttpServletRequest req,String param){ + String url = FRUtils.getAllUrl(req); + + if(isNotNullStr(param)){ + url = removeParam(url,param); + } + + url = encodeCH(url); + + return url; + } + + /** + * 去除空格换行 + * @param str + * @return + */ + public static String trim(String str){ + return str.trim().replaceAll("\n","").replaceAll("\r",""); + } +} diff --git a/src/main/java/com/eco/plugin/xx/bjsso/config/InitializeMonitor.java b/src/main/java/com/eco/plugin/xx/bjsso/config/InitializeMonitor.java new file mode 100644 index 0000000..fe1358d --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/config/InitializeMonitor.java @@ -0,0 +1,21 @@ +package com.eco.plugin.wink.bjsso.config; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + +/** + * @author wink + * @version 10.0 + * Created by wink on 2021-12-03 + */ +public class InitializeMonitor extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + PluginSimpleConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + + } +} diff --git a/src/main/java/com/eco/plugin/xx/bjsso/config/PluginSimpleConfig.java b/src/main/java/com/eco/plugin/xx/bjsso/config/PluginSimpleConfig.java new file mode 100644 index 0000000..efcd9bc --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/config/PluginSimpleConfig.java @@ -0,0 +1,123 @@ +package com.eco.plugin.wink.bjsso.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.wink.bjsso.config", text = "单点登录配置", source = Original.PLUGIN) + public static PluginSimpleConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(PluginSimpleConfig.class); + } + return config; + } + + @Identifier(value = "clientId", name = "应用名称", description = "应用名称", status = Status.SHOW) + private Conf clientId = Holders.simple(""); + + @Identifier(value = "key", name = "订阅id", description = "订阅id", status = Status.SHOW) + private Conf key = Holders.simple(""); + + @Identifier(value = "authUrl", name = "获取授权码接口", description = "获取授权码接口", status = Status.SHOW) + private Conf authUrl = Holders.simple(""); + + @Identifier(value = "tokenUrl", name = "校验授权码接口", description = "校验授权码接口", status = Status.SHOW) + private Conf tokenUrl = Holders.simple(""); + + @Identifier(value = "logoutUrl", name = "登出接口", description = "登出接口", status = Status.SHOW) + private Conf logoutUrl = Holders.simple(""); + + @Identifier(value = "paramname", name = "token参数名(直接加密方式)", description = "token参数名(直接加密方式)", status = Status.SHOW) + private Conf paramname = Holders.simple(""); + + @Identifier(value = "timeout", name = "token超时时间(直接加密方式)", description = "token超时时间(直接加密方式)", status = Status.SHOW) + private Conf timeout = Holders.simple(""); + + @Identifier(value = "privatekey", name = "解密密钥(直接加密方式)", description = "解密密钥(直接加密方式)", status = Status.SHOW) + private Conf privatekey = Holders.simple(""); + + public String getClientId() { + return clientId.get(); + } + + public void setClientId(String url) { + this.clientId.set(url); + } + + public String getKey() { + return key.get(); + } + + public void setKey(String url) { + this.key.set(url); + } + + public String getAuthUrl() { + return authUrl.get(); + } + + public void setAuthUrl(String url) { + this.authUrl.set(url); + } + + public String getTokenUrl() { + return tokenUrl.get(); + } + + public void setTokenUrl(String url) { + this.tokenUrl.set(url); + } + + public String getLogoutUrl() { + return logoutUrl.get(); + } + + public void setLogoutUrl(String url) { + this.logoutUrl.set(url); + } + + public String getParamname() { + return paramname.get(); + } + + public void setParamname(String url) { + this.paramname.set(url); + } + + public String getTimeout() { + return timeout.get(); + } + + public void setTimeout(String url) { + this.timeout.set(url); + } + + public String getPrivatekey() { + return privatekey.get(); + } + + public void setPrivatekey(String url) { + this.privatekey.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/xx/bjsso/filter/SSOFilter.java b/src/main/java/com/eco/plugin/xx/bjsso/filter/SSOFilter.java new file mode 100644 index 0000000..f26ed22 --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/filter/SSOFilter.java @@ -0,0 +1,169 @@ +package com.eco.plugin.wink.bjsso.filter; + +import com.eco.plugin.wink.bjsso.config.PluginSimpleConfig; +import com.eco.plugin.wink.bjsso.utils.*; +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.json.JSONObject; +import com.fr.plugin.context.PluginContexts; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.stable.fun.Authorize; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@EnableMetrics +@Authorize(callSignKey = "com.eco.plugin.wink.bjsso") +public class SSOFilter extends AbstractGlobalRequestFilterProvider { + @Override + public String filterName() { + return "bjssoFilter"; + } + + @Override + public String[] urlPatterns() { + return new String[]{"/*"}; + } + + @Override + public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain ){ + + if(PluginContexts.currentContext().isAvailable()){ + PluginSimpleConfig psc = PluginSimpleConfig.getInstance(); + String token = req.getParameter(psc.getParamname()); + + //如果存在token参数,走加密单点 + if(Utils.isNotNullStr(token)){ + //直接加密用户名的方式 + jmsso(req,res,psc); + return ; + } + + //是否放行 + if(isRelease(req)){ + release(req,res,chain); + return ; + } + + //oauth2单点 + oauthsso(req,res,psc); + } + + release(req,res,chain); + } + + private void oauthsso(HttpServletRequest req, HttpServletResponse res, PluginSimpleConfig psc) { + String code = req.getParameter("code"); + + if(Utils.isNullStr(code)){ + //跳转认证中心 + redirect(req,res,psc); + return; + } + + //获取用户名 + String username = getToken(code,psc,req); + String url = Utils.removeParam(FRUtils.getAllUrl(req),"code"); + + //登录 + FRUtils.login(req,res,username,url); + } + + /** + * 加密用户名方式 + * @param req + * @param res + * @param psc + */ + private void jmsso(HttpServletRequest req, HttpServletResponse res, PluginSimpleConfig psc) { + String token = req.getParameter(psc.getParamname()); + String privatekey = Utils.trim(psc.getPrivatekey()); + String mwtoken = null; + try { + mwtoken = EncryptUtils.rsaDecrypt(token,privatekey); + } catch (Exception e) { + ResponseUtils.failedResponse(res,"token解密失败:"+e.getMessage()); + return ; + } + + if(Utils.isNullStr(mwtoken)){ + ResponseUtils.failedResponse(res,"token解密失败!"); + return ; + } + + JSONObject tokenJson = new JSONObject(mwtoken); + Long now = System.currentTimeMillis(); + Long timestamp = tokenJson.getLong("timestamp"); + + FRUtils.FRLogInfo("now:"+now+";timestamp:"+timestamp); + + if((now - timestamp)/1000 > Long.parseLong(psc.getTimeout())){ + ResponseUtils.failedResponse(res,"token超时!"); + return ; + } + + String username = tokenJson.getString("username"); + String url = Utils.encodeCH(Utils.removeParam(FRUtils.getAllUrl(req),psc.getParamname())); + + FRUtils.login(req,res,username,url); + } + + private boolean isRelease(HttpServletRequest req) { + String url = FRUtils.getAllUrl(req); + String reft = req.getParameter("ref_t"); + + boolean isLogin = FRUtils.isLogin(req); + boolean isRemote = url.contains("remote"); + boolean isLoginPage = url.contains("login")||url.contains("decision/file")||url.contains("decision/resource")||url.contains("decision/system")||url.contains("query/ip"); + boolean isViewlt = "design".equals(reft); +// boolean isViewlt = url.contains("viewlet") || "design".equals(reft) || url.contains("view/report") || url.contains("view/form"); + return isLogin || isRemote || isLoginPage || isViewlt; + } + + //跳转认证中心 + private void redirect(HttpServletRequest req,HttpServletResponse res, PluginSimpleConfig psc) { + String authurl = psc.getAuthUrl()+"?app="+psc.getClientId()+"&subscription-key="+psc.getKey()+"&original-url="+FRUtils.getAllUrl(req)+"&pfidpadapterid=ad..OAuth"; + + try { + res.sendRedirect(authurl); + } catch (IOException e) { + FRUtils.FRLogInfo("跳转认证中心异常:"+e.getMessage()); + } + } + + //获取token + private String getToken(String code,PluginSimpleConfig psc,HttpServletRequest req) { + String tokenurl = psc.getTokenUrl(); + JSONObject param = new JSONObject(); + String url = Utils.removeParam(FRUtils.getAllUrl(req),"code"); + param.put("app",psc.getClientId()); + param.put("code",code); + param.put("redirectUri",url); + + String result = HttpUtils.HttpPostJson(tokenurl,param.toString(),null); + + if(Utils.isNullStr(result)){ + return ""; + } + + JSONObject json = new JSONObject(result); + + if(json == null ){ + return ""; + } + + String token = json.getString("username"); + return token; + } + + //放行拦截器 + private void release(HttpServletRequest req, HttpServletResponse res, FilterChain chain) { + try{ + chain.doFilter(req,res); + }catch (Exception e){ + FRUtils.FRLogInfo("拦截失败"); + } + } +} + diff --git a/src/main/java/com/eco/plugin/xx/bjsso/logout/Logout.java b/src/main/java/com/eco/plugin/xx/bjsso/logout/Logout.java new file mode 100644 index 0000000..ec08005 --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/logout/Logout.java @@ -0,0 +1,21 @@ +package com.eco.plugin.wink.bjsso.logout; + +import com.eco.plugin.wink.bjsso.config.PluginSimpleConfig; +import com.fr.decision.fun.impl.AbstractLogInOutEventProvider; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.decision.webservice.v10.login.LoginService; + +import javax.servlet.http.HttpSession; + +public class Logout extends AbstractLogInOutEventProvider { + + @Override + public String logoutAction(LogInOutResultInfo result) { + HttpSession session = result.getRequest().getSession(true); + LoginService.getInstance().crossDomainLogout(result.getRequest(),result.getResponse(),""); + session.invalidate(); + PluginSimpleConfig psc = PluginSimpleConfig.getInstance(); + return psc.getLogoutUrl()+ "?app="+psc.getClientId()+"&subscription-key="+psc.getKey(); + } +} + diff --git a/src/main/java/com/eco/plugin/xx/bjsso/utils/EncryptUtils.java b/src/main/java/com/eco/plugin/xx/bjsso/utils/EncryptUtils.java new file mode 100644 index 0000000..7a917c9 --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/utils/EncryptUtils.java @@ -0,0 +1,349 @@ +package com.eco.plugin.wink.bjsso.utils; + +import com.fr.log.FineLoggerFactory; +import sun.misc.BASE64Decoder; +import sun.misc.BASE64Encoder; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; +import java.io.IOException; +import java.security.*; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.HashMap; +import java.util.Map; + +public class EncryptUtils { + + /** + * sha 加密 + * @param str + * @return + */ + public static String sha(String str){ + String sha256Str = ""; + + try { + MessageDigest sha256Deget = MessageDigest.getInstance("SHA-256"); + byte[] sha256Encode = sha256Deget.digest(str.getBytes()); + sha256Str = ByteToHexStr(sha256Encode); + }catch (Exception e){ + FineLoggerFactory.getLogger().info("FRLOG:SHA256加密异常:"+e.getMessage()); + } + + return sha256Str; + } + + /** + * byte数组转16进制字符串 + * @param bytes + * @return + */ + private static String ByteToHexStr(byte[] bytes) + { + String hexStr = ""; + + for(int i =0;i= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') + || c == '+' || c == '/' || c == '=') { + continue; + } + else { + return false; + } + } + + return true; + } + } + + /** + * des加密 + * @param datasource + * @param password + * @return + */ + public static String desEncrypt(String datasource, String password) { + try { + SecureRandom random = new SecureRandom(); + DESKeySpec desKey = new DESKeySpec(password.getBytes()); + // 创建一个密匙工厂,然后用它把DESKeySpec转换成 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + SecretKey securekey = keyFactory.generateSecret(desKey); + // Cipher对象实际完成加密操作 + Cipher cipher = Cipher.getInstance("DES"); + // 用密匙初始化Cipher对象 + cipher.init(Cipher.ENCRYPT_MODE, securekey, random); + // 现在,获取数据并加密 + // 正式执行加密操作 + return base64Encode(cipher.doFinal(datasource.getBytes())); + } catch (Throwable e) { + FRUtils.FRLogInfo("des 加密异常 " + e.getMessage()); + } + + return null; + } + + /** + * des 解密 + * @param src + * @param password + * @return + * @throws Exception + */ + public static String desDecrypt(String src, String password) throws Exception { + // DES算法要求有一个可信任的随机数源 + SecureRandom random = new SecureRandom(); + // 创建一个DESKeySpec对象 + DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8")); + // 创建一个密匙工厂 + SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); + // 将DESKeySpec对象转换成SecretKey对象 + SecretKey securekey = keyFactory.generateSecret(desKey); + // Cipher对象实际完成解密操作 + Cipher cipher = Cipher.getInstance("DES"); + // 用密匙初始化Cipher对象 + cipher.init(Cipher.DECRYPT_MODE, securekey, random); + // 真正开始解密操作 + return new String(cipher.doFinal(base64DecodeB(src))); + } + + /** + * 随机生成RSA密钥对 + * @throws NoSuchAlgorithmException + * @return privateKey,publicKey + */ + public static Map genRSAKeyPair() throws NoSuchAlgorithmException { + // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象 + KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); + // 初始化密钥对生成器,密钥大小为96-1024位 + keyPairGen.initialize(1024,new SecureRandom()); + // 生成一个密钥对,保存在keyPair中 + KeyPair keyPair = keyPairGen.generateKeyPair(); + RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥 + RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥 + String publicKeyString = base64Encode(publicKey.getEncoded()); + // 得到私钥字符串 + String privateKeyString = base64Encode(privateKey.getEncoded()); + // 将公钥和私钥保存到Map + Map result = new HashMap(); + result.put("publicKey",publicKeyString.replaceAll("\n","").replace("\r","").trim()); + result.put("privateKey",privateKeyString.replaceAll("\n","").replace("\r","").trim()); + + return result; + } + + /** + * rsa 加密 + * @param str + * @param publicKey + * @return + * @throws Exception + */ + public static String rsaEncrypt(String str,String publicKey) throws Exception { + //base64编码的公钥 + byte[] decoded = base64DecodeB(publicKey); + RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); + //RSA加密 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, pubKey); + String outStr = base64Encode(cipher.doFinal(str.getBytes("UTF-8"))); + return outStr; + } + + /** + * rsa解密 + * @param str + * @param privateKey + * @return + * @throws Exception + */ + public static String rsaDecrypt(String str,String privateKey) throws Exception { + //64位解码加密后的字符串 + byte[] inputByte = base64DecodeB(str); + //base64编码的私钥 + byte[] decoded = base64DecodeB(privateKey); + RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); + //RSA解密 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.DECRYPT_MODE, priKey); + String outStr = new String(cipher.doFinal(inputByte)); + return outStr; + } + + public static void main(String[] args) throws Exception { + Map keys =genRSAKeyPair(); + String publicKey = keys.get("publicKey"); + String privateKey = keys.get("privateKey"); + + System.out.println(publicKey); + System.out.println(privateKey); + +// JSONObject json = new JSONObject(); +// json.put("username","xiamaofa"); +// json.put("timestamp",111111111); +// +// String jsonstr =json.toString(); +// String encrypt = rsaEncrypt(jsonstr,publicKey); +// String decrypt = rsaDecrypt(encrypt,privateKey); +// +// System.out.println(decrypt); + } +} diff --git a/src/main/java/com/eco/plugin/xx/bjsso/utils/FRUtils.java b/src/main/java/com/eco/plugin/xx/bjsso/utils/FRUtils.java new file mode 100644 index 0000000..6709d76 --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/utils/FRUtils.java @@ -0,0 +1,320 @@ +package com.eco.plugin.wink.bjsso.utils; + +import com.fr.base.ServerConfig; +import com.fr.base.TableData; +import com.fr.base.TemplateUtils; +import com.fr.decision.authority.AuthorityContext; +import com.fr.decision.authority.base.constant.type.operation.ManualOperationType; +import com.fr.decision.authority.data.User; +import com.fr.decision.base.util.UUIDUtil; +import com.fr.decision.privilege.encrpt.PasswordValidator; +import com.fr.decision.webservice.bean.authentication.OriginUrlResponseBean; +import com.fr.decision.webservice.interceptor.handler.ReportTemplateRequestChecker; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.decision.webservice.utils.DecisionServiceConstants; +import com.fr.decision.webservice.utils.DecisionStatusService; +import com.fr.decision.webservice.utils.UserSourceFactory; +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.general.data.DataModel; +import com.fr.log.FineLoggerFactory; +import com.fr.script.Calculator; +import com.fr.stable.StringUtils; +import com.fr.stable.query.QueryFactory; +import com.fr.stable.query.restriction.RestrictionFactory; +import com.fr.third.springframework.web.method.HandlerMethod; +import com.fr.web.controller.ReportRequestService; +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 getDBPsd(String username,String password){ + PasswordValidator pv = UserSourceFactory.getInstance().getUserSource(ManualOperationType.KEY).getPasswordValidator(); + String uuid = UUIDUtil.generate(); + + return pv.encode(username, password, uuid); + } + + /** + * 获取带参数的访问链接 + * @return + */ + public static String getAllUrl(HttpServletRequest httpServletRequest){ + return WebUtils.getOriginalURL(httpServletRequest); + } + + /** + * 根据originKey获取源链接 + * @param originKey + * @return + * @throws Exception + */ + public static String getOriginUrl(String originKey) throws Exception { + if (StringUtils.isNotEmpty(originKey)) { + OriginUrlResponseBean originUrlResponseBean = (OriginUrlResponseBean) DecisionStatusService.originUrlStatusService().get(originKey); + DecisionStatusService.originUrlStatusService().delete(originKey); + if (originUrlResponseBean != null) { + return originUrlResponseBean.getOriginUrl(); + } + } + + return new OriginUrlResponseBean(TemplateUtils.render("${fineServletURL}")).getOriginUrl(); + } + + /** + * 判断是否开启模板认证 + * @param + * @return + * @throws Exception + */ + public static boolean isTempAuth(HttpServletRequest req,HttpServletResponse res) throws Exception { + ReportTemplateRequestChecker checker = new ReportTemplateRequestChecker(); + HandlerMethod hm = new HandlerMethod(new ReportRequestService(),ReportRequestService.class.getMethod("preview", HttpServletRequest.class, HttpServletResponse.class, String.class)); + return checker.checkRequest(req,res,hm); + } + + /** + * 获取数据集数据 + * @param serverDataSetName + * @return + */ + public static DataModel getTableData(String serverDataSetName){ + TableData userInfo = TableDataConfig.getInstance().getTableData(serverDataSetName); + DataModel userInfoDM = userInfo.createDataModel(Calculator.createCalculator()); +// userInfoDM.getRowCount(); +// userInfoDM.getColumnIndex(); +// userInfoDM.getValueAt() + return userInfoDM; + } + + public static String getIndex(HttpServletRequest req){ + String url = req.getScheme()+"://"+req.getServerName()+":"+String.valueOf(req.getServerPort())+req.getRequestURI(); + return url; + } +} diff --git a/src/main/java/com/eco/plugin/xx/bjsso/utils/HttpUtils.java b/src/main/java/com/eco/plugin/xx/bjsso/utils/HttpUtils.java new file mode 100644 index 0000000..d001507 --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/utils/HttpUtils.java @@ -0,0 +1,265 @@ +package com.eco.plugin.wink.bjsso.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.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +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 HttpPostText(String url, String xmlParam){ + FineLoggerFactory.getLogger().info("FRLOG:HttpPostText:url:"+url); + + HttpPost postMethod = new HttpPost(url); + + postMethod.setHeader("Content-type", "text/plain"); + HttpEntity entity2 = null; + try { + entity2 = new StringEntity(xmlParam); + } catch (UnsupportedEncodingException e) { + FineLoggerFactory.getLogger().info("FRLOG:HttpPostText:参数异常:"+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/xx/bjsso/utils/ResponseUtils.java b/src/main/java/com/eco/plugin/xx/bjsso/utils/ResponseUtils.java new file mode 100644 index 0000000..f14e5e4 --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/utils/ResponseUtils.java @@ -0,0 +1,108 @@ +package com.eco.plugin.wink.bjsso.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 responseText(HttpServletResponse res,String text){ + PrintWriter pw; + try { + pw = WebUtils.createPrintWriter(res); + } catch (Exception e) { + FineLoggerFactory.getLogger().info(e.getMessage()); + return; + } + res.setContentType("text/html;charset=utf-8"); + pw.println(text); + 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/xx/bjsso/utils/Utils.java b/src/main/java/com/eco/plugin/xx/bjsso/utils/Utils.java new file mode 100644 index 0000000..a05335d --- /dev/null +++ b/src/main/java/com/eco/plugin/xx/bjsso/utils/Utils.java @@ -0,0 +1,283 @@ +package com.eco.plugin.wink.bjsso.utils; + +import com.fr.base.TemplateUtils; +import com.fr.data.NetworkHelper; +import com.fr.decision.webservice.v10.user.UserService; +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); + } + + /** + * + * @param res + * @param path /com/fr/plugin/loginAuth/html/getMac.html + * @param parameterMap + */ + 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("跳转页面异常"); + } + + } + + /** + * 判断是否是管理员 + * @param username + * @return + */ + public static boolean isAdmin(String username) throws Exception{ + return UserService.getInstance().isAdmin(UserService.getInstance().getUserByUserName(username).getId()); + } + + /** + * 去掉浏览器中的参数 + * @param url + * @param param + * @return + */ + public static String removeParam(String url,String param){ + if(!url.contains("?"+param) && !url.contains("&"+param)){ + return url; + } + + return url.substring(0,url.indexOf(url.contains("?"+param) ? "?"+param : "&"+param)); + } + + /** + * 获取跳转链接 + * @param req + * @param param + * @return + */ + public static String getRedirectUrl(HttpServletRequest req,String param){ + String url = FRUtils.getAllUrl(req); + + if(isNotNullStr(param)){ + url = removeParam(url,param); + } + + url = encodeCH(url); + + return url; + } + + /** + * 去除空格换行 + * @param str + * @return + */ + public static String trim(String str){ + return str.trim().replaceAll("\n","").replaceAll("\r",""); + } +} diff --git a/使用手册.docx b/使用手册.docx new file mode 100644 index 0000000000000000000000000000000000000000..11ba89518fc6c7d35c4c1643b81c79a41361ff11 GIT binary patch literal 145287 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⎵trw_!W=WY+rmxgyeh9K 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 z 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 literal 0 HcmV?d00001