commit 59dbcab65fbb8c536b0fb8cf5d34efc4c77d0e5d Author: pioneer Date: Tue Nov 29 16:12:24 2022 +0800 open diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff1c191 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# open-JSD-10203 + +JSD-10203 oauth2单点登录\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 \ No newline at end of file diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..6523380 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,32 @@ + + com.fr.plugin.xx.zyjn.sso + + yes + 1.6 + 10.0~11.0 + 2018-07-31 + fr.open + + + [2022-10-13]【1.1】url encode 移除多余配置。
+ [2022-10-14]【1.2】登出+拦截配置。
+ [2022-10-27]【1.3】新增组织同步、接口鉴权、ssoToken。
+ [2022-11-08]【1.3】token刷新。
+ [2022-11-25]【1.4】token刷新+参数过滤。
+ [2022-11-25]【1.5】token刷新+参数过滤。
+ [2022-11-25]【1.6】token刷新+参数过滤。
+ ]]>
+ + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/zyjn/PluginConstants.java b/src/main/java/com/fr/plugin/xx/zyjn/PluginConstants.java new file mode 100644 index 0000000..b65145f --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/PluginConstants.java @@ -0,0 +1,13 @@ +package com.fr.plugin.xx.zyjn; + +/** + * @author xx + * @since 2021/12/04 + */ +public class PluginConstants { + + public static final String PLUGIN_ID = "com.fr.plugin.xx.zyjn.sso"; + + public static final String PLUGIN_NAME = "sso"; + +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/SyncDBAccessProvider.java b/src/main/java/com/fr/plugin/xx/zyjn/SyncDBAccessProvider.java new file mode 100644 index 0000000..0c93644 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/SyncDBAccessProvider.java @@ -0,0 +1,57 @@ +package com.fr.plugin.xx.zyjn; + +import com.fr.db.fun.impl.AbstractDBAccessProvider; +import com.fr.plugin.xx.zyjn.dao.SyncOrgDao; +import com.fr.plugin.xx.zyjn.dao.SyncUserDao; +import com.fr.plugin.xx.zyjn.entity.SyncOrgEntity; +import com.fr.plugin.xx.zyjn.entity.SyncUserEntity; +import com.fr.stable.db.accessor.DBAccessor; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.dao.DAOProvider; + +/** + * @Author xx + * @Date 2022/10/12 + * @Description + **/ +public class SyncDBAccessProvider extends AbstractDBAccessProvider { + + private static DBAccessor dbAccessor = null; + + public static DBAccessor getDbAccessor() { + return dbAccessor; + } + + @Override + public DAOProvider[] registerDAO() { + return new DAOProvider[]{ + new DAOProvider() { + @Override + public Class getEntityClass() { + return SyncUserEntity.class; + } + + @Override + public Class> getDAOClass() { + return SyncUserDao.class; + } + }, + new DAOProvider() { + @Override + public Class getEntityClass() { + return SyncOrgEntity.class; + } + + @Override + public Class> getDAOClass() { + return SyncOrgDao.class; + } + } + }; + } + + @Override + public void onDBAvailable(DBAccessor dbAccessor) { + SyncDBAccessProvider.dbAccessor = dbAccessor; + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/zyjn/conf/GxkgSsoConfig.java b/src/main/java/com/fr/plugin/xx/zyjn/conf/GxkgSsoConfig.java new file mode 100644 index 0000000..b6aa19b --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/conf/GxkgSsoConfig.java @@ -0,0 +1,163 @@ +package com.fr.plugin.xx.zyjn.conf; + +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; +import com.fr.stable.StringUtils; + +/** + * @author xx + * @date 2021/11/04 + */ +@Visualization(category = "sso单点") +@EnableMetrics +public class GxkgSsoConfig extends DefaultConfiguration { + + private static volatile GxkgSsoConfig config = null; + + @Focus(id="com.fr.plugin.sso.sykg.extra", text = "SYKG-SSO配置", source = Original.PLUGIN) + public static GxkgSsoConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(GxkgSsoConfig.class); + } + return config; + } + + @Identifier(value = "debugSwitch", name = "日志调试模式", description = "日志调试模式", status = Status.SHOW) + private Conf debugSwitch = Holders.simple(true); + + public Boolean getdebugSwitch() { return debugSwitch.get(); } + + public void setdebugSwitch(Boolean debugSwitch) { this.debugSwitch.set(debugSwitch); } + + @Identifier(value = "redirect", name = "帆软服务回跳地址", description = "帆软服务回跳地址,http://ip:port/webroot/decision", status = Status.SHOW) + private Conf redirect = Holders.simple(StringUtils.EMPTY); + + public String getRedirect() { + return redirect.get(); + } + + public void setRedirect(String redirect) { + this.redirect.set(redirect); + } + + @Identifier(value = "host", name = "单点Oauth2地址", description = "单点Oauth2地址,http://ip:port", status = Status.SHOW) + private Conf host = Holders.simple(StringUtils.EMPTY); + + public String getHost() { + return host.get(); + } + + public void setHost(String host) { + this.host.set(host); + } + + + private Conf syncHost = Holders.simple(StringUtils.EMPTY); + + public String getSyncHost() { + return syncHost.get(); + } + + public void setSyncHost(String syncHost) { + this.syncHost.set(syncHost); + } + + @Identifier(value = "clientId", name = "clientId", description = "clientId", status = Status.SHOW) + private Conf clientId = Holders.simple(StringUtils.EMPTY); + + public String getClientId() { + return clientId.get(); + } + + public void setClientId(String clientId) { + this.clientId.set(clientId); + } + + @Identifier(value = "clientSecret", name = "clientSecret", description = "clientSecret", status = Status.SHOW) + private Conf clientSecret = Holders.simple(StringUtils.EMPTY); + + public String getClientSecret() { + return clientSecret.get(); + } + + public void setClientSecret(String clientSecret) { + this.clientSecret.set(clientSecret); + } + + @Identifier(value = "logoutUrl", name = "登出调用地址", description = "登出调用地址", status = Status.SHOW) + private Conf logoutUrl = Holders.simple(StringUtils.EMPTY); + public String getLogoutUrl() { + return logoutUrl.get(); + } + + public void setLogoutUrl(String logoutUrl) { + this.logoutUrl.set(logoutUrl); + } + + @Identifier(value = "refreshToken", name = "刷新token开关", description = "刷新token开关", status = Status.SHOW) + private Conf refreshToken = Holders.simple(false); + + public Boolean getRefreshToken() { + return refreshToken.get(); + } + + public void setRefreshToken(Boolean refreshToken) { + this.refreshToken.set(refreshToken); + } + + + private Conf cron = Holders.simple("0 0/1 * * * ? *"); + + public String getCron() { + return cron.get(); + } + + public void setCron(String cron) { + this.cron.set(cron); + } + + + private Conf syncUser = Holders.simple(StringUtils.EMPTY); + + public String getSyncUser() { + return syncUser.get(); + } + + public void setSyncUser(String syncUser) { + this.syncUser.set(syncUser); + } + + private Conf syncPass = Holders.simple(StringUtils.EMPTY); + + public String getSyncPass() { + return syncPass.get(); + } + + public void setSyncPass(String syncPass) { + this.syncPass.set(syncPass); + } + + + private Conf appSn = Holders.simple(StringUtils.EMPTY); + + public String getAppSn() { + return appSn.get(); + } + + public void setAppSn(String appSn) { + this.appSn.set(appSn); + } + + @Override + public Object clone() throws CloneNotSupportedException { + GxkgSsoConfig cloned = (GxkgSsoConfig) super.clone(); + cloned.debugSwitch = (Conf) debugSwitch.clone(); + return cloned; + } + + +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncOrgDao.java b/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncOrgDao.java new file mode 100644 index 0000000..c515562 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncOrgDao.java @@ -0,0 +1,21 @@ +package com.fr.plugin.xx.zyjn.dao; + +import com.fr.plugin.xx.zyjn.entity.SyncOrgEntity; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.session.DAOSession; + +/** + * @Author xx + * @Date 2022/10/12 + * @Description + **/ +public class SyncOrgDao extends BaseDAO { + public SyncOrgDao(DAOSession daoSession) { + super(daoSession); + } + + @Override + protected Class getEntityClass() { + return SyncOrgEntity.class; + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncService.java b/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncService.java new file mode 100644 index 0000000..8c7555f --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncService.java @@ -0,0 +1,37 @@ +package com.fr.plugin.xx.zyjn.dao; + +import com.fr.plugin.xx.zyjn.SyncDBAccessProvider; +import com.fr.plugin.xx.zyjn.entity.SyncOrgEntity; +import com.fr.plugin.xx.zyjn.entity.SyncUserEntity; +import com.fr.plugin.xx.zyjn.utils.LogUtils; +import com.fr.stable.db.action.DBAction; + +/** + * @Author xx + * @Date 2022/10/12 + * @Description + **/ +public class SyncService { + + public static void saveUser(SyncUserEntity entity) { + try { + SyncDBAccessProvider.getDbAccessor().runDMLAction((DBAction) daoContext -> { + daoContext.getDAO(SyncUserDao.class).addOrUpdate(entity); + return null; + }); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + } + + public static void saveOrg(SyncOrgEntity entity) { + try { + SyncDBAccessProvider.getDbAccessor().runDMLAction((DBAction) daoContext -> { + daoContext.getDAO(SyncOrgDao.class).addOrUpdate(entity); + return null; + }); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncUserDao.java b/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncUserDao.java new file mode 100644 index 0000000..ccfd610 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/dao/SyncUserDao.java @@ -0,0 +1,21 @@ +package com.fr.plugin.xx.zyjn.dao; + +import com.fr.plugin.xx.zyjn.entity.SyncUserEntity; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.session.DAOSession; + +/** + * @Author xx + * @Date 2022/10/12 + * @Description + **/ +public class SyncUserDao extends BaseDAO { + public SyncUserDao(DAOSession daoSession) { + super(daoSession); + } + + @Override + protected Class getEntityClass() { + return SyncUserEntity.class; + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/entity/SyncOrgEntity.java b/src/main/java/com/fr/plugin/xx/zyjn/entity/SyncOrgEntity.java new file mode 100644 index 0000000..767f09f --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/entity/SyncOrgEntity.java @@ -0,0 +1,85 @@ +package com.fr.plugin.xx.zyjn.entity; + +import com.fr.json.JSONObject; +import com.fr.stable.db.entity.BaseEntity; +import com.fr.third.javax.persistence.Column; +import com.fr.third.javax.persistence.Entity; +import com.fr.third.javax.persistence.Table; + +/** + * @Author xx + * @Date 2022/10/12 + * @Description + **/ +@Entity +@Table(name = "plugin_fine_sync_org") +public class SyncOrgEntity extends BaseEntity { + + @Column(name = "name") + private String name; + + @Column(name = "parent_sn") + private String parentSn; + + @Column(name = "status") + private Boolean status; + + @Column(name = "org_code") + private String orgCode; + + @Column(name = "sort_num") + private String sortNum; + + public SyncOrgEntity() { + + } + + public SyncOrgEntity(JSONObject object) { + this.setId(object.getString("sn")); + this.setName(object.getString("name")); + this.setParentSn(object.getString("parentSn")); + this.setStatus(object.getInt("status") == 1); + this.setOrgCode(object.getString("orgCode")); + this.setSortNum(object.getString("sortNum")); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getParentSn() { + return parentSn; + } + + public void setParentSn(String parentSn) { + this.parentSn = parentSn; + } + + public Boolean getStatus() { + return status; + } + + public void setStatus(Boolean status) { + this.status = status; + } + + public String getOrgCode() { + return orgCode; + } + + public void setOrgCode(String orgCode) { + this.orgCode = orgCode; + } + + public String getSortNum() { + return sortNum; + } + + public void setSortNum(String sortNum) { + this.sortNum = sortNum; + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/entity/SyncUserEntity.java b/src/main/java/com/fr/plugin/xx/zyjn/entity/SyncUserEntity.java new file mode 100644 index 0000000..7eaea50 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/entity/SyncUserEntity.java @@ -0,0 +1,153 @@ +package com.fr.plugin.xx.zyjn.entity; + +import com.fr.json.JSONObject; +import com.fr.stable.StringUtils; +import com.fr.stable.db.entity.BaseEntity; +import com.fr.third.javax.persistence.Column; +import com.fr.third.javax.persistence.Entity; +import com.fr.third.javax.persistence.Table; + +/** + * @Author xx + * @Date 2022/10/12 + * @Description + **/ +@Entity +@Table(name = "plugin_fine_sync_user") +public class SyncUserEntity extends BaseEntity { + + @Column(name = "orgSn") + private String orgSn; + + @Column(name = "name") + private String name; + + @Column(name = "sex") + private Boolean sex; + + @Column(name = "status") + private Boolean status; + + @Column(name = "telephone") + private String telephone; + + @Column(name = "email") + private String email; + + @Column(name = "position") + private String position; + + @Column(name = "joinDate") + private String joinDate; + + @Column(name = "loginName") + private String loginName; + + @Column(name = "password") + private String password; + + public SyncUserEntity() { + + } + + public SyncUserEntity(JSONObject object) { + this.setId(object.getString("sn")); + Boolean male = null; + if (object.has("sex") && StringUtils.isNotBlank(object.getString("sex"))) { + if (object.getInt("sex") != 0) { + male = object.getInt("sex") == 1 ? true : false; + } + } + this.setSex(male); + this.setLoginName(object.getString("loginName")); + this.setName(object.getString("name")); + this.setEmail(object.getString("email")); + this.setTelephone(object.getString("telephone")); + this.setStatus(object.getInt("status") == 1); + this.setOrgSn(object.getString("orgSn")); + this.setPosition(object.getString("position")); + this.setJoinDate(object.getString("joinDate")); + this.setPassword(object.getString("password")); + } + + + public String getOrgSn() { + return orgSn; + } + + public void setOrgSn(String orgSn) { + this.orgSn = orgSn; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Boolean getSex() { + return sex; + } + + public void setSex(Boolean sex) { + this.sex = sex; + } + + public Boolean getStatus() { + return status; + } + + public void setStatus(Boolean status) { + this.status = status; + } + + public String getTelephone() { + return telephone; + } + + public void setTelephone(String telephone) { + this.telephone = telephone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public String getJoinDate() { + return joinDate; + } + + public void setJoinDate(String joinDate) { + this.joinDate = joinDate; + } + + public String getLoginName() { + return loginName; + } + + public void setLoginName(String loginName) { + this.loginName = loginName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/handler/HRGT.java b/src/main/java/com/fr/plugin/xx/zyjn/handler/HRGT.java new file mode 100644 index 0000000..5cc8017 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/handler/HRGT.java @@ -0,0 +1,21 @@ +package com.fr.plugin.xx.zyjn.handler; + +import com.fr.decision.fun.HttpHandler; +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.plugin.xx.zyjn.handler.action.SyncOrgHandler; +import com.fr.plugin.xx.zyjn.handler.action.SyncUserHandler; + +/** + * @Author xx + * @Date 2021/11/27 + * @Description + **/ +public class HRGT extends AbstractHttpHandlerProvider { + @Override + public HttpHandler[] registerHandlers() { + return new HttpHandler[]{ + new SyncUserHandler(), + new SyncOrgHandler(), + }; + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/handler/URGT.java b/src/main/java/com/fr/plugin/xx/zyjn/handler/URGT.java new file mode 100644 index 0000000..a1d910b --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/handler/URGT.java @@ -0,0 +1,20 @@ +package com.fr.plugin.xx.zyjn.handler; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; + +/** + * @Author xx + * @Date 2021/11/27 + * @Description + **/ +public class URGT extends AbstractURLAliasProvider { + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/sync/user", "/sync/user", true), + URLAliasFactory.createPluginAlias("/sync/org", "/sync/org", true), + }; + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/handler/action/BaseHandler.java b/src/main/java/com/fr/plugin/xx/zyjn/handler/action/BaseHandler.java new file mode 100644 index 0000000..153aded --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/handler/action/BaseHandler.java @@ -0,0 +1,65 @@ +package com.fr.plugin.xx.zyjn.handler.action; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.general.IOUtils; +import com.fr.json.JSONObject; +import com.fr.plugin.xx.zyjn.utils.LogUtils; +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.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @Author xx + * @Date 2022/10/27 + * @Description + **/ +public abstract class BaseHandler extends BaseHttpHandler { + + private final static String PREFIX = "jynsh"; + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + String tokenId = req.getHeader("tokenId"); + String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + if (!StringUtils.equals(DigestUtils.md5Hex((PREFIX + format).getBytes(StandardCharsets.UTF_8)).toLowerCase(), tokenId)) { + setError(res, "报文认证不通过"); + return; + } + String body = IOUtils.inputStream2String(req.getInputStream()); + if (StringUtils.isBlank(body)) { + setError(res, "请求内容不能为空"); + return; + } + JSONObject object = null; + try { + object = new JSONObject(body); + } catch (Exception e) { + setError(res, "报文格式非json"); + } + if (!object.has("sn")) { + setError(res, "请求sn不能为空"); + return; + } + LogUtils.debug4plugin("sync url is {} body is {}", req.getRequestURI(), body); + sync(res, object); + + + } + + abstract void sync(HttpServletResponse res, JSONObject entity) throws Exception; + + protected void setError(HttpServletResponse res, String mess) { + try { + JSONObject error = JSONObject.create().put("code", 1).put("msg", mess); + WebUtils.printAsJSON(res, error); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/handler/action/SyncOrgHandler.java b/src/main/java/com/fr/plugin/xx/zyjn/handler/action/SyncOrgHandler.java new file mode 100644 index 0000000..aa639a9 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/handler/action/SyncOrgHandler.java @@ -0,0 +1,39 @@ +package com.fr.plugin.xx.zyjn.handler.action; + +import com.fr.json.JSONObject; +import com.fr.plugin.xx.zyjn.dao.SyncService; +import com.fr.plugin.xx.zyjn.entity.SyncOrgEntity; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletResponse; + +/** + * @Author xx + * @Date 2021/11/27 + * @Description + **/ +public class SyncOrgHandler extends BaseHandler { + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/sync/org"; + } + + @Override + public boolean isPublic() { + return true; + } + + + @Override + void sync(HttpServletResponse res, JSONObject entity) throws Exception { + SyncService.saveOrg(new SyncOrgEntity(entity)); + WebUtils.printAsJSON(res, new JSONObject("{\"code\":0,\"msg\":\"成功\"}")); + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/handler/action/SyncUserHandler.java b/src/main/java/com/fr/plugin/xx/zyjn/handler/action/SyncUserHandler.java new file mode 100644 index 0000000..365e7cd --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/handler/action/SyncUserHandler.java @@ -0,0 +1,55 @@ +package com.fr.plugin.xx.zyjn.handler.action; + +import com.fr.json.JSONObject; +import com.fr.plugin.xx.zyjn.dao.SyncService; +import com.fr.plugin.xx.zyjn.entity.SyncUserEntity; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletResponse; + +/** + * @Author xx + * @Date 2021/11/27 + * @Description + **/ +public class SyncUserHandler extends BaseHandler { + + /* + * +基本字段-员工工号 sn String no no 员工工号 +基本字段-组织编号 orgSn String no no 所属组织编号 +基本字段-姓名 name String no no 用户名称 +基本字段-性别 sex int yes no 性别,1-男,2-女,0-未知 +基本字段-状态 status int no no 1-正常,2-离职 +基本字段-手机号 telephone String yes no 手机号 +基本字段-邮箱 email String yes no 邮箱 +基本字段-职务 position String yes no 职务中文 +基本字段-入职日期 joinDate String yes no 入职日期,例2020-07-07 00:00:00 +基本字段-登录名 loginName String yes no +基本字段-密码 password String yes no MD5 32位小写加密后的密码 + * */ + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/sync/user"; + } + + @Override + public boolean isPublic() { + return true; + } + + + @Override + void sync(HttpServletResponse res, JSONObject body) throws Exception { + SyncUserEntity entity = new SyncUserEntity(body); + SyncService.saveUser(entity); + WebUtils.printAsJSON(res, new JSONObject("{\"code\":0,\"msg\":\"成功\"}")); + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/rgt/PLMRGT.java b/src/main/java/com/fr/plugin/xx/zyjn/rgt/PLMRGT.java new file mode 100644 index 0000000..e119f5f --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/rgt/PLMRGT.java @@ -0,0 +1,20 @@ +package com.fr.plugin.xx.zyjn.rgt; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.xx.zyjn.conf.GxkgSsoConfig; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; + +/** + * @author xx + * @date 2021/11/04 + */ +public class PLMRGT extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + GxkgSsoConfig.getInstance(); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/schedule/SyncUserSchedule.java b/src/main/java/com/fr/plugin/xx/zyjn/schedule/SyncUserSchedule.java new file mode 100644 index 0000000..30e01b2 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/schedule/SyncUserSchedule.java @@ -0,0 +1,85 @@ +package com.fr.plugin.xx.zyjn.schedule; + +import com.fr.cluster.core.ClusterNode; +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.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.plugin.xx.zyjn.conf.GxkgSsoConfig; +import com.fr.plugin.xx.zyjn.utils.HttpUtil; +import com.fr.plugin.xx.zyjn.utils.LogUtils; +import com.fr.scheduler.job.FineScheduleJob; +import com.fr.stable.StringUtils; +import com.fr.third.v2.org.quartz.JobExecutionContext; + +import java.util.HashMap; +import java.util.Map; + +/** + * @Author xx + * @Date 2022/7/18 + * @Description + **/ +public class SyncUserSchedule extends FineScheduleJob { + + private static final String TOKEN_URL = "%s/api/sys/getToken"; + + private static final String USER_URL = "%s/api/rest/data/acct"; + + + @Override + public void run(JobExecutionContext jobExecutionContext, ClusterNode clusterNode) throws Exception { + GxkgSsoConfig config = GxkgSsoConfig.getInstance(); + if (StringUtils.isBlank(config.getSyncUser()) || StringUtils.isBlank(config.getSyncPass())) { + LogUtils.error("同步授权账户信息为空"); + return; + } + JSONObject tokenBody = JSONObject.create().put("username", config.getSyncUser()).put("password", config.getSyncPass()); + String tokenUrl = String.format(TOKEN_URL, config.getSyncHost()); + LogUtils.debug4plugin("token url is {}", tokenUrl); + String tokenRes = HttpUtil.sendPost(tokenUrl, null, tokenBody); + LogUtils.debug4plugin("token res is {}", tokenRes); + if (StringUtils.isBlank(tokenRes)) { + LogUtils.error("token 返回空"); + return; + } + JSONObject tokenObject = new JSONObject(tokenRes); + String token = tokenObject.getString("msg"); + if (StringUtils.isBlank(token)) { + LogUtils.error("msg 返回空"); + return; + } + String userUrl = String.format(USER_URL, config.getSyncHost()); + Map header = new HashMap(); + header.put("uim-login-user-id", token); + LogUtils.debug4plugin("user url is {}", userUrl); + String userRes = HttpUtil.sendPost(userUrl, header, JSONObject.create().put("appSn", config.getAppSn())); + LogUtils.debug4plugin("user res is {}", userRes); + JSONObject object = new JSONObject(userRes); + if (object.containsKey("data")) { + JSONArray array = object.getJSONArray("data"); + LogUtils.debug4plugin("get sync user size is {}", array.size()); + int created = 0, updated = 0; + for (int i = 0; i < array.size(); i++) { + JSONObject body = array.getJSONObject(i); + String id = body.getString("id"); + User user = AuthorityContext.getInstance().getUserController().getById(id); + if (user == null) { + user = new User().id(id).userName(body.getString("loginName")) + .realName(body.getString("userName")).creationType(ManualOperationType.KEY) + .lastOperationType(ManualOperationType.KEY).enable(body.getInt("status") == 1); + AuthorityContext.getInstance().getUserController().add(user); + created++; + } else { + user.id(id).userName(body.getString("loginName")) + .realName(body.getString("userName")).creationType(ManualOperationType.KEY) + .lastOperationType(ManualOperationType.KEY).enable(body.getInt("status") == 1); + AuthorityContext.getInstance().getUserController().update(user); + updated++; + } + } + LogUtils.debug4plugin("sync user create size is {} updated size is {}", created, updated); + } + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/sso/Logout.java b/src/main/java/com/fr/plugin/xx/zyjn/sso/Logout.java new file mode 100644 index 0000000..554e314 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/sso/Logout.java @@ -0,0 +1,38 @@ +package com.fr.plugin.xx.zyjn.sso; + +import com.fr.decision.fun.impl.AbstractLogInOutEventProvider; +import com.fr.decision.webservice.login.LogInOutResultInfo; +import com.fr.plugin.xx.zyjn.conf.GxkgSsoConfig; +import com.fr.plugin.xx.zyjn.utils.LogUtils; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.stable.StringUtils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +/** + * @author xx + * @date 2021/11/04 + */ +@FunctionRecorder +public class Logout extends AbstractLogInOutEventProvider { + + @Override + public void loginAction(LogInOutResultInfo result) { + } + + @Override + public String logoutAction(LogInOutResultInfo result) { + GxkgSsoConfig config = GxkgSsoConfig.getInstance(); + if (StringUtils.isBlank(config.getHost())) { + return StringUtils.EMPTY; + } + String temp = "%s?redirectToUrl=%s"; + try { + return String.format(temp, config.getLogoutUrl(), URLEncoder.encode(config.getRedirect(),"UTF-8")); + } catch (UnsupportedEncodingException e) { + LogUtils.error(e.getMessage(),e); + } + return StringUtils.EMPTY; + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/zyjn/sso/OAuth.java b/src/main/java/com/fr/plugin/xx/zyjn/sso/OAuth.java new file mode 100644 index 0000000..49c4445 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/sso/OAuth.java @@ -0,0 +1,231 @@ +package com.fr.plugin.xx.zyjn.sso; + +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.zyjn.PluginConstants; +import com.fr.plugin.xx.zyjn.conf.GxkgSsoConfig; +import com.fr.plugin.xx.zyjn.schedule.SyncUserSchedule; +import com.fr.plugin.xx.zyjn.utils.CommonUtils; +import com.fr.plugin.xx.zyjn.utils.HttpUtil; +import com.fr.plugin.xx.zyjn.utils.LogUtils; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.scheduler.QuartzContext; +import com.fr.scheduler.ScheduleJobManager; +import com.fr.stable.StringUtils; +import com.fr.stable.fun.Authorize; +import com.fr.third.v2.org.quartz.CronScheduleBuilder; +import com.fr.third.v2.org.quartz.JobKey; +import com.fr.third.v2.org.quartz.SchedulerException; +import com.fr.third.v2.org.quartz.TriggerBuilder; +import com.fr.web.utils.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +/** + * @author xx + * @date 2021/11/04 + */ +@FunctionRecorder +@Authorize(callSignKey = PluginConstants.PLUGIN_ID) +public class OAuth extends AbstractGlobalRequestFilterProvider { + + @Override + public void init(FilterConfig filterConfig) { + } + + public static void initSchedule() { + JobKey jobKey = new JobKey("syncUser", "syncGroup"); + try { + if (QuartzContext.getInstance().getScheduler().checkExists(jobKey)) { + ScheduleJobManager.getInstance().removeJob(jobKey.getName(), jobKey.getGroup()); + } + } catch (SchedulerException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + + addSchedule(jobKey); + } + + private static void addSchedule(JobKey jobKey) { + Map param = new HashMap(); + TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger(); + triggerBuilder.forJob(jobKey.getName(), jobKey.getGroup()).withIdentity(jobKey.getName(), jobKey.getGroup()).startNow(); + String cron = GxkgSsoConfig.getInstance().getCron(); + if (StringUtils.isBlank(cron)) { + FineLoggerFactory.getLogger().error("cron is null schedule start failed"); + return; + } + CronScheduleBuilder schedule = CronScheduleBuilder.cronSchedule(cron); + triggerBuilder.withSchedule(schedule); + try { + ScheduleJobManager.getInstance().addJob(jobKey.getName(), jobKey.getGroup(), "sync job", SyncUserSchedule.class, triggerBuilder.build(), param); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + @Override + public String filterName() { + return "oauthFilter"; + } + + @Override + public String[] urlPatterns() { + if (!PluginContexts.currentContext().isAvailable()) { + LogUtils.error("未注册或禁用"); + return new String[]{"/neverbeused"}; + } + //initSchedule(); + return new String[]{ + "/decision", + "/decision/view/report", + "/decision/view/form", + }; + } + + @Override + public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { + GxkgSsoConfig config = GxkgSsoConfig.getInstance(); + if (CommonUtils.isLogin(request)) { + Cookie sessionId = com.fr.third.springframework.web.util.WebUtils.getCookie(request, "SSO_SESSION_ID"); + if (config.getRefreshToken() && StringUtils.equals("XMLHttpRequest", request.getHeader("X-Requested-With"))) { + refreshSession(sessionId, config); + } + CommonUtils.next(request, response, chain); + return; + } + if (isAccept(request)) { + CommonUtils.next(request, response, chain); + return; + } + try { + String code = request.getParameter("code"); + if (StringUtils.isBlank(code)) { + jumpAuthorize(request, response, config); + return; + } + String token = getToken(code, config); + if (StringUtils.isBlank(token)) { + CommonUtils.setError(response, "token 获取失败"); + return; + } + String username = getUsername(token, config); + if (StringUtils.isBlank(username)) { + CommonUtils.setError(response, "username 获取失败"); + return; + } + if (!CommonUtils.existUser(username)) { + CommonUtils.setError(response, String.format("[%s]用户不存在", username)); + return; + } + CommonUtils.login(username, request, response); + String state = request.getParameter("state"); + String sessionId = request.getParameter("sessionId"); + response.addCookie(new Cookie("SSO_SESSION_ID", sessionId)); + if (StringUtils.isNotBlank(state)) { + String accessURL = CommonUtils.getCachedParam(state); + if (StringUtils.isNotBlank(accessURL)) { + response.sendRedirect(accessURL); + return; + } + } + + String url = request.getRequestURL().toString(); + String query = String.format("%s=%s", "code", code); + String queryString = URLDecoder.decode(request.getQueryString(),"UTF-8"); + LogUtils.debug4plugin("query string is {}", queryString); + queryString = queryString.replace("&" + query, "").replace(query, ""); + if (StringUtils.isNotBlank(queryString)) { + LogUtils.debug4plugin("replace string is {}", url + "?" + queryString); + response.sendRedirect(url + "?" + queryString); + } else { + LogUtils.debug4plugin("replace string is {}", url); + response.sendRedirect(url); + } + } catch (Exception e) { + LogUtils.error("oauth2单点登陆处理失败, Cause by: ", e); + CommonUtils.setError(response, e.getMessage()); + } + } + + private void refreshSession(Cookie cookie, GxkgSsoConfig config) { + if (cookie == null) { + return; + } + String temp = "%s/sso/refreshLoginTime?sessionId=%s"; + String url = String.format(temp, config.getHost(), cookie.getValue()); + LogUtils.debug4plugin("get refreshSession url is {}", url); + Map param = new HashMap<>(); + param.put("sessionId", cookie.getValue()); + String res = HttpUtil.doFormPost(url, null, param, null); + LogUtils.debug4plugin("refreshSession token res is {}", res); + } + + private String getUsername(String token, GxkgSsoConfig config) { + String temp = "%s/sso/oauth2/userInfo?access_token=%s&client_id=%s"; + String url = String.format(temp, config.getHost(), token, config.getClientId()); + LogUtils.debug4plugin("get username url is {}", url); + String res = HttpUtil.sendGet(url, null, null); + LogUtils.debug4plugin("get token res is {}", res); + JSONObject result = new JSONObject(res); + if (result.has("uid")) { + return result.getString("uid"); + } + return StringUtils.EMPTY; + } + + private String getToken(String code, GxkgSsoConfig config) { + String temp = "%s/sso/oauth2/token?client_id=%s&grant_type=authorization_code&code=%s&client_secret=%s"; + String url = String.format(temp, config.getHost(), config.getClientId(), code, config.getClientSecret()); + LogUtils.debug4plugin("get token url is {}", url); + String res = HttpUtil.sendPost(url, null, JSONObject.create()); + LogUtils.debug4plugin("get token res is {}", res); + JSONObject result = new JSONObject(res); + if (result.has("access_token")) { + return result.getString("access_token"); + } + return StringUtils.EMPTY; + } + + private void jumpAuthorize(HttpServletRequest request, HttpServletResponse response, GxkgSsoConfig config) { + try { + String redirectUrl = CommonUtils.getUrl(request); + String key = CommonUtils.cacheParams(redirectUrl); + String temp = "%s/sso/oauth2/authorize?response_type=code&redirect_uri=%s&client_id=%s&state=%s"; + String url = String.format(temp, config.getHost(), URLEncoder.encode(config.getRedirect(), "UTF-8"), config.getClientId(), key); + if (StringUtils.isNotBlank(request.getParameter("ssoToken"))) { + url += "&ssoToken=" + request.getParameter("ssoToken"); + } + LogUtils.debug4plugin("redirect url is {}", url); + response.sendRedirect(url); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + + } + + private boolean isAccept(HttpServletRequest request) { + if (request.getRequestURI().endsWith("/view/form") || request.getRequestURI().endsWith("/view/report")) { + if (StringUtils.isNotBlank(WebUtils.getHTTPRequestParameter(request, "code"))) { + return false; + } + if (StringUtils.isNotBlank(WebUtils.getReportTitleFromRequest(request))) { + return false; + } + return true; + } + return false; + } + + +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/utils/CommonUtils.java b/src/main/java/com/fr/plugin/xx/zyjn/utils/CommonUtils.java new file mode 100644 index 0000000..4690f02 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/utils/CommonUtils.java @@ -0,0 +1,191 @@ +package com.fr.plugin.xx.zyjn.utils; + +import com.fr.data.NetworkHelper; +import com.fr.decision.authority.data.User; +import com.fr.decision.mobile.terminal.TerminalHandler; +import com.fr.decision.webservice.utils.DecisionServiceConstants; +import com.fr.decision.webservice.utils.DecisionStatusService; +import com.fr.decision.webservice.utils.WebServiceUtils; +import com.fr.decision.webservice.v10.login.LoginService; +import com.fr.decision.webservice.v10.login.TokenResource; +import com.fr.decision.webservice.v10.user.UserService; +import com.fr.locale.InterProviderFactory; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +import com.fr.stable.web.Device; +import com.fr.web.utils.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.UUID; + +/** + * @author xx + * @since 2021/8/24 + */ +public class CommonUtils { + + public static String getProperty(Properties props, String key, String defaultValue, boolean allowBlank) { + String value = props.getProperty(key); + if (StringUtils.isNotBlank(value)) { + return value; + } else { + if (allowBlank) { + LogUtils.warn("Property[" + key + "] value is blank."); + return defaultValue; + } else { + throw new IllegalArgumentException("Property[" + key + "] cann't be blank."); + } + } + } + + public static String getProperty(Properties props, String key, boolean allowBlank) { + return getProperty(props, key, null, allowBlank); + } + + public static String getProperty(Properties props, String key) { + return getProperty(props, key, null, true); + } + + public static boolean isLogin(HttpServletRequest request) { + String oldToken = TokenResource.COOKIE.getToken(request); + return oldToken != null && checkTokenValid(request, (String) oldToken); + } + + private static boolean checkTokenValid(HttpServletRequest req, String token) { + try { + Device device = NetworkHelper.getDevice(req); + LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, device)); + return true; + } catch (Exception ignore) { + } + return false; + } + + /** + * 跳转到过滤器链中的下一个过滤器 + * + * @param request + * @param response + * @param chain + */ + public static void next(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { + try { + chain.doFilter(request, response); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + } + + public static boolean existUser(String username){ + try { + User user = UserService.getInstance().getUserByUserName(username); + if (user == null) { + return false; + } + return true; + } catch (Exception e) { + + } + return false; + + } + + public static void login(String username, HttpServletRequest request, HttpServletResponse response) { + try { + User user = UserService.getInstance().getUserByUserName(username); + if (user == null) { + throw new RuntimeException("系统未授权, 当前用户是\"" + username + "\""); + } + String token = LoginService.getInstance().login(request, response, user.getUserName()); + request.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token); + } catch (Exception e) { + FineLoggerFactory.getLogger().error("sso >> Failed to login with[" + username + "]", e); + throw new RuntimeException("用户\"" + username + "\"登录失败"); + } + } + + public static boolean isMobileDevice(HttpServletRequest request) { + if (WebUtils.getDevice(request).isMobile()) { + LogUtils.debug4plugin("current request is is mobile request ,url is {}", request.getRequestURI()); + return true; + } + String requestHeader = request.getHeader("user-agent"); + String[] deviceArray = new String[]{"android", "iphone", "ipad", "ios", "windows phone", "wechat"}; + if (requestHeader == null) { + return false; + } + requestHeader = requestHeader.toLowerCase(); + for (int i = 0; i < deviceArray.length; i++) { + if (requestHeader.toLowerCase().contains(deviceArray[i])) { + LogUtils.debug4plugin("current request:{} is mobile request!", request.getRequestURI()); + return true; + } + } + String op = WebUtils.getHTTPRequestParameter(request, "op"); + return StringUtils.isNotBlank(op) && StringUtils.equals("h5", op); + } + + public static String cacheParams(String values) { + try { + String key = UUID.randomUUID().toString(); + DecisionStatusService.originUrlStatusService().put(key, values); + return key; + } catch (Exception e) { + LogUtils.error(e.getMessage(),e); + } + return StringUtils.EMPTY; + } + public static String getCachedParam(String key) { + try { + return DecisionStatusService.originUrlStatusService().get(key); + } catch (Exception e) { + return StringUtils.EMPTY; + } + } + + public static void cacheParams(String key, Map values) { + try { + DecisionStatusService.originUrlStatusService().put(key, values); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String getCachedParam(String key, String name) { + try { + Map values = DecisionStatusService.originUrlStatusService().get(key); + return values.get(name); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void setError(HttpServletResponse res, String reason) { + try { + PrintWriter printWriter = WebUtils.createPrintWriter(res); + Map map = new HashMap<>(); + map.put("result", InterProviderFactory.getProvider().getLocText("Fine-Engine_Error_Page_Result")); + map.put("reason", reason); + map.put("solution", InterProviderFactory.getProvider().getLocText("Fine-Engine_Please_Contact_Platform_Admin")); + String page = WebServiceUtils.parseWebPageResourceSafe("com/fr/web/controller/decision/entrance/resources/unavailable.html", map); + printWriter.write(page); + printWriter.flush(); + printWriter.close(); + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + + public static String getUrl(HttpServletRequest req) { + String uri = req.getRequestURI(); + String query = req.getQueryString(); + return StringUtils.isNotBlank(query) ? uri + "?" + query : uri; + } + +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/utils/HttpUtil.java b/src/main/java/com/fr/plugin/xx/zyjn/utils/HttpUtil.java new file mode 100644 index 0000000..1c2e6db --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/utils/HttpUtil.java @@ -0,0 +1,330 @@ +package com.fr.plugin.xx.zyjn.utils; + +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.stable.StringUtils; +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.HttpClient; +import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.config.Registry; +import com.fr.third.org.apache.http.config.RegistryBuilder; +import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.socket.LayeredConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.ssl.SSLContexts; +import com.fr.third.org.apache.http.conn.ssl.TrustStrategy; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; +import com.fr.third.org.apache.http.impl.client.HttpClientBuilder; +import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import com.fr.third.org.apache.http.message.BasicNameValuePair; +import com.fr.third.org.apache.http.util.EntityUtils; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author xx + * @Date 2020/12/05 + * @Description + **/ +public class HttpUtil { + + private static HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + System.out.println("Warning: URL Host: " + urlHostName + " vs. " + + session.getPeerHost()); + return true; + } + }; + + /** + * 发送get请求 + * + * @param url + * @param param + * @param header + * @return + * @throws IOException + */ + public static String sendGet(String url, Map param, Map header) { + String result = ""; + BufferedReader in = null; + String urlNameString = url; + try { + if (param != null) { + urlNameString += "?"; + urlNameString += param.entrySet() + .stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining("&")); + } + + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + HttpURLConnection connection; + if (url.startsWith("https")) { + trustAllHttpsCertificates(); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + connection = (HttpURLConnection) realUrl.openConnection(); + } else { + connection = (HttpURLConnection) realUrl.openConnection(); + } + //设置超时时间 + connection.setDoInput(true); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(5000); + connection.setReadTimeout(15000); + // 设置通用的请求属性 + if (header != null) { + Iterator> it = header.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + System.out.println(entry.getKey() + ":::" + entry.getValue()); + connection.setRequestProperty(entry.getKey(), entry.getValue()); + } + } + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 建立实际的连接 + connection.connect(); + // 定义 BufferedReader输入流来读取URL的响应,设置utf8防止中文乱码 + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + if (in != null) { + in.close(); + } + }catch (Exception e){ + FineLoggerFactory.getLogger().error(e,"get url error ,url is:{},error is {}",urlNameString,e.getMessage()); + } + return result; + } + + public static String sendPost(String url,Map header, JSONObject body) { + PrintWriter out = null; + BufferedReader in = null; + String result = StringUtils.EMPTY; + String res = StringUtils.EMPTY; + try { + String urlNameString = url; + + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + HttpURLConnection conn; + if (url.startsWith("https")) { + trustAllHttpsCertificates(); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + conn = (HttpURLConnection) realUrl.openConnection(); + } else { + conn = (HttpURLConnection) realUrl.openConnection(); + } + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", + "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Content-Type","application/json;;charset=UTF-8"); + //conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=----footfoodapplicationrequestnetwork"); + if(header != null){ + header.forEach((k, v) -> { + conn.setRequestProperty(k, v); + }); + } + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + //获取请求头 + + // 获取URLConnection对象对应的输出流 + out = new PrintWriter(conn.getOutputStream()); + StringBuffer buffer = new StringBuffer(); + + // 发送请求参数 + if(body != null){ + out.print(body.toString()); + } + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader( + new InputStreamReader(conn.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + res = result; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + //使用finally块来关闭输出流、输入流 + finally{ + try{ + if(out!=null){ + out.close(); + } + if(in!=null){ + in.close(); + } + } + catch(IOException e){ + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + } + return res; + } + + + private static CloseableHttpClient getHttpsClient() { + RegistryBuilder registryBuilder = RegistryBuilder.create(); + ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory(); + registryBuilder.register("http", plainSF); + // 指定信任密钥存储对象和连接套接字工厂 + try { + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + // 信任任何链接 + TrustStrategy anyTrustStrategy = new TrustStrategy() { + + @Override + public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException { + // TODO Auto-generated method stub + return true; + } + }; + SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build(); + LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + registryBuilder.register("https", sslSF); + } catch (KeyStoreException e) { + throw new RuntimeException(e); + } catch (KeyManagementException e) { + throw new RuntimeException(e); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + Registry registry = registryBuilder.build(); + // 设置连接管理器 + PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry); + // 构建客户端 + return HttpClientBuilder.create().setConnectionManager(connManager).build(); + + } + + public static String doFormPost(String url,Map header, Map map, String chartset) { + //声明返回结果 + String result = ""; + UrlEncodedFormEntity entity = null; + HttpResponse httpResponse = null; + HttpClient httpClient = null; + try { + // 创建连接 + httpClient = getHttpsClient(); + + // 设置请求头和报文 + HttpPost httpPost = new HttpPost(url); + if (header != null) { + header.forEach((k, v) -> { + httpPost.setHeader(k, v.toString()); + }); + } + //设置参数 + List list = new ArrayList(); + Iterator iterator = map.entrySet().iterator(); + while (iterator.hasNext()) { + Map.Entry elem = (Map.Entry) iterator.next(); + list.add(new BasicNameValuePair(elem.getKey(), elem.getValue())); + } + entity = new UrlEncodedFormEntity(list, chartset == null ? "UTF-8" : chartset); + httpPost.setEntity(entity); + //执行发送,获取相应结果 + httpResponse = httpClient.execute(httpPost); + if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + result = EntityUtils.toString(httpResponse.getEntity()); + } else { + FineLoggerFactory.getLogger().error("Http post form code is {},message is {}", httpResponse.getStatusLine().getStatusCode(), EntityUtils.toString(httpResponse.getEntity())); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return result; + + } + + private static void trustAllHttpsCertificates() throws Exception { + javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1]; + javax.net.ssl.TrustManager tm = new miTM(); + trustAllCerts[0] = tm; + javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL","SunJSSE"); + sc.init(null, trustAllCerts, null); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } + + + /** + * encode url by UTF-8 + * @param url url before encoding + * @return url after encoding + */ + public static String encodeUrl(String url){ + String eurl = url; + try { + eurl = URLEncoder.encode(url,"UTF-8"); + } catch (UnsupportedEncodingException e) { + } + return eurl; + } + + private static class miTM implements javax.net.ssl.TrustManager, + javax.net.ssl.X509TrustManager { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public boolean isServerTrusted( + java.security.cert.X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted( + java.security.cert.X509Certificate[] certs) { + return true; + } + + @Override + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) + throws java.security.cert.CertificateException { + return; + } + + @Override + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) + throws java.security.cert.CertificateException { + return; + } + } +} diff --git a/src/main/java/com/fr/plugin/xx/zyjn/utils/LogUtils.java b/src/main/java/com/fr/plugin/xx/zyjn/utils/LogUtils.java new file mode 100644 index 0000000..5343e47 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/zyjn/utils/LogUtils.java @@ -0,0 +1,122 @@ +package com.fr.plugin.xx.zyjn.utils; + +import com.fr.log.FineLoggerFactory; +import com.fr.log.FineLoggerProvider; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.zyjn.PluginConstants; +import com.fr.plugin.xx.zyjn.conf.GxkgSsoConfig; +import com.fr.stable.StringUtils; + +/** + * @author xx + * @date 2021/11/04 + */ +public final class LogUtils { + private static final String DEBUG_PREFIX = "[插件调试] "; + private static String LOG_PREFIX = PluginConstants.PLUGIN_NAME; + private static final String PLUGIN_VERSION; + + private static final FineLoggerProvider LOGGER = FineLoggerFactory.getLogger(); + + static { + String version = PluginContexts.currentContext().getMarker().getVersion(); + if (StringUtils.isNotBlank(version)) { + PLUGIN_VERSION = "[v" + version + "] "; + } else { + PLUGIN_VERSION = "[unknown version] "; + } + + LOG_PREFIX = LOG_PREFIX + PLUGIN_VERSION; + } + + public static void setPrefix(String prefix) { + if (prefix != null) { + LOG_PREFIX = prefix; + } + } + + public static boolean isDebugEnabled() { + return LOGGER.isDebugEnabled(); + } + + public static void debug(String s) { + LOGGER.debug(LOG_PREFIX + s); + } + + public static void debug(String s, Object... objects) { + LOGGER.debug(LOG_PREFIX + s, objects); + } + + public static void debug(String s, Throwable throwable) { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + + public static void debug4plugin(String s) { + if (GxkgSsoConfig.getInstance().getdebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s); + } else { + LOGGER.debug(LOG_PREFIX + s); + } + } + + public static void debug4plugin(String s, Object... objects) { + if (GxkgSsoConfig.getInstance().getdebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, objects); + } else { + LOGGER.debug(LOG_PREFIX + s, objects); + } + } + + public static void debug4plugin(String s, Throwable throwable) { + if (GxkgSsoConfig.getInstance().getdebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, throwable); + } else { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + } + + + public static boolean isInfoEnabled() { + return LOGGER.isInfoEnabled(); + } + + public static void info(String s) { + LOGGER.info(LOG_PREFIX + s); + } + + public static void info(String s, Object... objects) { + LOGGER.info(LOG_PREFIX + s, objects); + } + + public static void warn(String s) { + LOGGER.warn(LOG_PREFIX + s); + } + + public static void warn(String s, Object... objects) { + LOGGER.warn(LOG_PREFIX + s, objects); + } + + public static void warn(String s, Throwable throwable) { + LOGGER.warn(LOG_PREFIX + s, throwable); + } + + public static void warn(Throwable throwable, String s, Object... objects) { + LOGGER.warn(throwable, LOG_PREFIX + s, objects); + } + + public static void error(String s) { + LOGGER.error(LOG_PREFIX + s); + } + + public static void error(String s, Object... objects) { + LOGGER.error(LOG_PREFIX + s, objects); + } + + public static void error(String s, Throwable throwable) { + LOGGER.error(LOG_PREFIX + s, throwable); + } + + public static void error(Throwable throwable, String s, Object... objects) { + LOGGER.error(throwable, LOG_PREFIX + s, objects); + } +}