Browse Source

提交开源任务材料

10.0
LAPTOP-SB56SG4Q\86185 3 years ago
parent
commit
8ee28c96b7
  1. BIN
      JSD-8089需求确认书.docx
  2. 5
      README.md
  3. BIN
      lib/commons-codec-1.3.jar
  4. BIN
      lib/commons-httpclient-3.0.1.jar
  5. BIN
      lib/commons-logging-1.1.jar
  6. BIN
      lib/dom4j-1.6.1.jar
  7. BIN
      lib/fastjson-1.1.37.jar
  8. BIN
      lib/finekit-10.0.jar
  9. BIN
      lib/jaxen-1.1.1.jar
  10. BIN
      lib/json-lib-2.3-jdk15.jar
  11. BIN
      lib/log4j-1.2.16.jar
  12. BIN
      lib/trsids-agent.jar
  13. BIN
      lib/trsids-filter.jar
  14. 24
      plugin.xml
  15. 96
      src/main/java/com/fr/plugin/third/party/jsdiaij/config/CustomDataConfig.java
  16. 24
      src/main/java/com/fr/plugin/third/party/jsdiaij/config/DataConfigInitializeMonitor.java
  17. 348
      src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpDataModel.java
  18. 18
      src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpTableData.java
  19. 50
      src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpTableDataDefine.java
  20. 76
      src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpTableDataPane.java
  21. 67
      src/main/java/com/fr/plugin/third/party/jsdiaij/data/DatasetData.java
  22. 189
      src/main/java/com/fr/plugin/third/party/jsdiaij/http/SessionGlobalRequestFilterProvider.java
  23. 380
      src/main/java/com/fr/plugin/third/party/jsdiaij/oauth/DesUtil.java
  24. 246
      src/main/java/com/fr/plugin/third/party/jsdiaij/oauth/IDSAPICall.java
  25. 111
      src/main/java/com/fr/plugin/third/party/jsdiaij/oauth/IdsQuery.java
  26. 249
      src/main/java/com/trs/idm/client/actor/IDSUser.java
  27. 151
      src/main/java/com/trs/idm/client/actor/TRSIDSServletAppActor.java
  28. 387
      src/main/java/com/trs/ids/oauth/DesUtil.java
  29. 247
      src/main/java/com/trs/ids/oauth/IDSAPICall.java
  30. 52
      src/main/java/com/trs/ids/oauth/Test.java

BIN
JSD-8089需求确认书.docx

Binary file not shown.

5
README.md

@ -1,3 +1,6 @@
# open-JSD-8089
JSD-8089 公务通单点(OAuth)+用户同步
JSD-8089 公务通单点(OAuth)+用户同步\
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
仅作为开发者学习参考使用!禁止用于任何商业用途!\
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。

BIN
lib/commons-codec-1.3.jar

Binary file not shown.

BIN
lib/commons-httpclient-3.0.1.jar

Binary file not shown.

BIN
lib/commons-logging-1.1.jar

Binary file not shown.

BIN
lib/dom4j-1.6.1.jar

Binary file not shown.

BIN
lib/fastjson-1.1.37.jar

Binary file not shown.

BIN
lib/finekit-10.0.jar

Binary file not shown.

BIN
lib/jaxen-1.1.1.jar

Binary file not shown.

BIN
lib/json-lib-2.3-jdk15.jar

Binary file not shown.

BIN
lib/log4j-1.2.16.jar

Binary file not shown.

BIN
lib/trsids-agent.jar

Binary file not shown.

BIN
lib/trsids-filter.jar

Binary file not shown.

24
plugin.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.third.party.jsd8089</id>
<name><![CDATA[IDS认证和用户同步]]></name>
<active>yes</active>
<version>0.8</version>
<env-version>10.0</env-version>
<jartime>2019-01-01</jartime>
<vendor>fr.open</vendor>
<description><![CDATA[]]></description>
<change-notes><![CDATA[]]></change-notes>
<prefer-packages>
<prefer-package>*</prefer-package>
</prefer-packages>
<extra-decision>
<GlobalRequestFilterProvider class="com.fr.plugin.third.party.jsdiaij.http.SessionGlobalRequestFilterProvider"/>
</extra-decision>
<extra-designer>
<ServerTableDataDefineProvider class="com.fr.plugin.third.party.jsdiaij.data.CustomHttpTableDataDefine"/>
<TableDataDefineProvider class="com.fr.plugin.third.party.jsdiaij.data.CustomHttpTableDataDefine"/>
</extra-designer>
<function-recorder class="com.fr.plugin.third.party.jsdiaij.config.DataConfigInitializeMonitor"/>
<lifecycle-monitor class="com.fr.plugin.third.party.jsdiaij.config.DataConfigInitializeMonitor"/>
</plugin>

96
src/main/java/com/fr/plugin/third/party/jsdiaij/config/CustomDataConfig.java

@ -0,0 +1,96 @@
package com.fr.plugin.third.party.jsdiaij.config;
import com.fr.config.*;
import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
/**
* 配置数据保存
*/
@Visualization(category = "TRS IDS配置")
public class CustomDataConfig extends DefaultConfiguration {
private static volatile CustomDataConfig config = null;
public String getNameSpace() {
return this.getClass().getName();
}
public static CustomDataConfig getInstance() {
if (config == null) {
config = ConfigContext.getConfigInstance(CustomDataConfig.class);
}
return config;
}
@Identifier(value = "idsServiceUrl", name = "IDS服务地址", description = "", status = Status.SHOW)
private Conf<String> idsServiceUrl = Holders.simple("");
@Identifier(value = "secretKey", name = "加密密钥", description = "", status = Status.SHOW)
private Conf<String> secretKey = Holders.simple("");
@Identifier(value = "digestAlgorithm", name = "消息摘要加密算法", description = "", status = Status.SHOW)
private Conf<String> digestAlgorithm = Holders.simple("");
@Identifier(value = "appName", name = "协作应用名", description = "", status = Status.SHOW)
private Conf<String> appName = Holders.simple("");
@Identifier(value = "tokenName", name = "应用接收Token字段名", description = "", status = Status.SHOW)
private Conf<String> tokenName = Holders.simple("");
public String getIdsServiceUrl() {
return idsServiceUrl.get();
}
public void setIdsServiceUrl(String idsServiceUrl) {
this.idsServiceUrl.set(idsServiceUrl);
}
public String getSecretKey() {
return secretKey.get();
}
public void setSecretKey(String secretKey) {
this.secretKey.set(secretKey);
}
public String getDigestAlgorithm() {
return digestAlgorithm.get();
}
public void setDigestAlgorithm(String digestAlgorithm) {
this.digestAlgorithm.set(digestAlgorithm);
}
public String getAppName() {
return appName.get();
}
public void setAppName(String appName) {
this.appName.set(appName);
}
public String getTokenName() {
return tokenName.get();
}
public void setTokenName(String tokenName) {
this.tokenName.set(tokenName);
}
@Override
public Object clone() throws CloneNotSupportedException {
CustomDataConfig cloned = (CustomDataConfig) super.clone();
cloned.idsServiceUrl = (Conf<String>) idsServiceUrl.clone();
cloned.secretKey = (Conf<String>) secretKey.clone();
cloned.digestAlgorithm = (Conf<String>) digestAlgorithm.clone();
cloned.appName = (Conf<String>) appName.clone();
cloned.tokenName = (Conf<String>) tokenName.clone();
return cloned;
}
}

24
src/main/java/com/fr/plugin/third/party/jsdiaij/config/DataConfigInitializeMonitor.java

@ -0,0 +1,24 @@
package com.fr.plugin.third.party.jsdiaij.config;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.Original;
import com.fr.plugin.context.PluginContext;
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor;
import com.fr.record.analyzer.EnableMetrics;
/**
* 配置信息初始化
*/
@EnableMetrics
public class DataConfigInitializeMonitor extends AbstractPluginLifecycleMonitor {
@Override
@Focus(id = "com.fr.plugin.third.party.jsd8089", text = "plugin-jsd-8089", source = Original.PLUGIN)
public void afterRun(PluginContext pluginContext) {
CustomDataConfig.getInstance();
}
@Override
public void beforeStop(PluginContext pluginContext) {
}
}

348
src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpDataModel.java

@ -0,0 +1,348 @@
package com.fr.plugin.third.party.jsdiaij.data;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.base.TableData;
import com.fr.data.AbstractDataModel;
import com.fr.general.data.TableDataException;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.plugin.third.party.jsdiaij.oauth.IdsQuery;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CustomHttpDataModel extends AbstractDataModel {
private static String[] COLUMN_NAMES = {"user_id", "username", "password", "mail", "mobile", "ou_id", "ou_name", "position", "p_id"};
private int rowCount = TableData.RESULT_ALL;
private DatasetData datas = new DatasetData();
public CustomHttpDataModel(int count) {
this.rowCount = count;
if (this.rowCount == 0) {
return;
}
queryData();
}
@Override
public int getColumnCount() throws TableDataException {
return COLUMN_NAMES.length;
}
@Override
public String getColumnName(int i) throws TableDataException {
return COLUMN_NAMES[i];
}
@Override
public boolean hasRow(int rowIndex) throws TableDataException {
int count = getRowCount();
return rowIndex < count;
}
@Override
public int getRowCount() throws TableDataException {
if (this.datas == null) {
return 0;
}
List<List<Object>> values = this.datas.getValues();
if (values == null) {
return 0;
}
int count = values.size();
return count;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) throws TableDataException {
if (this.datas == null) {
return "";
}
List<List<Object>> values = this.datas.getValues();
if ((values == null) || (values.size() <= rowIndex)) {
return "";
}
List<Object> rowValues = values.get(rowIndex);
if ((rowValues == null) || (rowValues.size() <= columnIndex)) {
return "";
}
return rowValues.get(columnIndex);
}
@Override
public void release() throws Exception {
this.datas = null;
}
/**
* 查询数据
*/
private void queryData() {
try {
createDatas();
} catch (Exception e) {
LogKit.error("数据集获取用户信息,请求出错," + e.getMessage(), e);
throw new NullPointerException("数据集获取用户信息为空");
}
}
/*
{
"lastModifiedTime": 1564628908631,
"parentId": "EveryOne",
"groupId": "7854",
"groupName": "海沧区党政机关",
"GroupDesc": "海沧区党政机关",
"groupDN": "EveryOne#7854",
"groupDisplayNameDN": "根组织#海沧区党政机关",
"displayName": "海沧区党政机关",
"IDSEXT_UNIT_DEPT": "0",
"parentName": "EveryOne"
}
* */
private void createDatas() throws Exception {
String deptName = "", jobTitle = "", userId = "", userName = "", password = "", code = "", fCode = "", mobile = "", mail = "";
String content = IdsQuery.queryUsers(this.rowCount);
if (StringKit.isEmpty(content)) {
return;
}
JSONObject contentJson = new JSONObject(content);
JSONArray userArray = contentJson.getJSONArray("list");
if ((userArray == null) || (userArray.size() <= 0)) {
return;
}
Map<String, String> existsOUs = new HashMap<>();
Map<String, Integer> existsOUs1 = new HashMap<>();
Map<String, OuInfo> orgs = getOrgs();
Map<String, String> orgsMapping = getOrgsMapping();
JSONObject userJson;
OuInfo ouInfo;
String userKey;
List<String> usedDeptIds = new ArrayList<>();
for (int i = 0, max = userArray.size() - 1; i <= max; i++) {
deptName = "";
jobTitle = "";
userId = "";
userName = "";
password = "111111";
mobile = "";
mail = "";
code = "";
fCode = "";
userJson = userArray.getJSONObject(i);
userId = userJson.getString("userName");
userId = StringKit.trim(userId);
if (StringKit.isEmpty(userId)) {
continue;
}
userId = userId.toLowerCase();
userName = userJson.getString("trueName");
mail = userJson.getString("email");
mobile = userJson.getString("mobile");
code = userJson.getString("groupName");
jobTitle = userJson.getString("position");
userKey = userJson.getString("userId");
if (orgsMapping.containsKey(userKey)) {
code = orgsMapping.get(userKey);
if (StringKit.isNotEmpty(code) && orgs.containsKey(code)) {
ouInfo = orgs.get(code);
if (ouInfo != null) {
deptName = ouInfo.displayName;
fCode = ouInfo.parentId;
}
}
}
if (StringKit.isEmpty(code)) {
continue;
}
if (StringKit.isEmpty(deptName)) {
deptName = "未知";
}
fCode = StringKit.trim(fCode);
if ("EveryOne".equals(fCode)) {
fCode = "";
}
usedDeptIds.add(code);
deptName = getOuName(code, deptName, existsOUs, existsOUs1);
addRowDatas(userId, userName, password, mail, mobile, code, deptName, jobTitle, fCode);
}
for (OuInfo ouInfo1 : orgs.values()) {
deptName = "";
jobTitle = "";
userId = "";
userName = "";
password = "111111";
mobile = "";
mail = "";
code = "";
fCode = "";
if (ouInfo1 == null) {
continue;
}
code = ouInfo1.groupId;
deptName = ouInfo1.displayName;
fCode = ouInfo1.parentId;
if (usedDeptIds.contains(code)) {
continue;
}
if (StringKit.isEmpty(code)) {
continue;
}
if ("EveryOne".equalsIgnoreCase(code)) {
continue;
}
if (StringKit.isEmpty(deptName)) {
deptName = "未知";
}
fCode = StringKit.trim(fCode);
if ("EveryOne".equals(fCode)) {
fCode = "";
}
deptName = getOuName(code, deptName, existsOUs, existsOUs1);
addRowDatas(userId, userName, password, mail, mobile, code, deptName, jobTitle, fCode);
}
}
// {"dept_name", "job_title", "user_id", "username", "password", "mobile", "mail", "code", "fcode"};
private void addRowDatas(String userId, String userName, String password, String mail, String mobile, String code, String deptName, String jobTitle, String fCode) {
List<Object> rowDatas = new ArrayList<>();
rowDatas.add(userId);
rowDatas.add(userName);
rowDatas.add(password);
rowDatas.add(mail);
rowDatas.add(mobile);
rowDatas.add(code);
rowDatas.add(deptName);
rowDatas.add(jobTitle);
rowDatas.add(fCode);
List<List<Object>> values = this.datas.getValues();
values.add(rowDatas);
}
private Map<String, OuInfo> getOrgs() throws Exception {
Map<String, OuInfo> orgs = new HashMap<>();
String content = IdsQuery.searchGroups();
if (StringKit.isEmpty(content)) {
return orgs;
}
JSONObject contentJson = new JSONObject(content);
JSONObject dataJson = contentJson.getJSONObject("data");
if (dataJson == null) {
return orgs;
}
JSONArray orgArray = dataJson.getJSONArray("groupDatas");
if ((orgArray == null) || (orgArray.size() <= 0)) {
return orgs;
}
JSONObject orgJson;
String parentId;
String groupId;
String displayName;
OuInfo ouInfo;
for (int i = 0, max = orgArray.size() - 1; i <= max; i++) {
orgJson = orgArray.getJSONObject(i);
if (orgJson == null) {
continue;
}
groupId = orgJson.getString("groupId");
if (StringKit.isEmpty(groupId)) {
continue;
}
parentId = orgJson.getString("parentId");
displayName = orgJson.getString("displayName");
ouInfo = new OuInfo();
ouInfo.parentId = parentId;
ouInfo.groupId = groupId;
ouInfo.displayName = displayName;
orgs.put(groupId, ouInfo);
}
return orgs;
}
private String getOuName(String ouId, String ouName, Map<String, String> existsOUs, Map<String, Integer> existsOUs1) {
if (existsOUs.containsKey(ouId)) {
return existsOUs.get(ouId);
}
if (!existsOUs1.containsKey(ouName)) {
existsOUs1.put(ouName, 0);
existsOUs.put(ouId, ouName);
return ouName;
}
int index = existsOUs1.get(ouName) + 1;
existsOUs1.put(ouName, index);
String tempName = ouName + index;
existsOUs.put(ouId, tempName);
LogKit.info("IDS认证和用户同步,部门名称 重命名:" + tempName);
return tempName;
}
private Map<String, String> getOrgsMapping() throws Exception {
Map<String, String> orgs = new HashMap<>();
String content = IdsQuery.searchUserGroupsMapping();
if (StringKit.isEmpty(content)) {
return orgs;
}
JSONObject contentJson = new JSONObject(content);
JSONObject dataJson = contentJson.getJSONObject("data");
if (dataJson == null) {
return orgs;
}
JSONArray orgArray = dataJson.getJSONArray("datas");
if ((orgArray == null) || (orgArray.size() <= 0)) {
return orgs;
}
JSONObject orgJson;
String parentId;
String groupId;
String displayName;
OuInfo ouInfo;
for (int i = 0, max = orgArray.size() - 1; i <= max; i++) {
orgJson = orgArray.getJSONObject(i);
if (orgJson == null) {
continue;
}
groupId = String.valueOf(orgJson.getInt("userId"));
if (StringKit.isEmpty(groupId)) {
continue;
}
displayName = orgJson.getString("groupName");
orgs.put(groupId, displayName);
}
return orgs;
}
class OuInfo {
public String parentId;
public String groupId;
public String displayName;
}
}

18
src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpTableData.java

@ -0,0 +1,18 @@
package com.fr.plugin.third.party.jsdiaij.data;
import com.fr.base.TableData;
import com.fr.data.AbstractParameterTableData;
import com.fr.general.data.DataModel;
import com.fr.script.Calculator;
public class CustomHttpTableData extends AbstractParameterTableData {
@Override
public DataModel createDataModel(Calculator calculator) {
return createDataModel(calculator, TableData.RESULT_ALL);
}
@Override
public DataModel createDataModel(Calculator calculator, int rowCount) {
return new CustomHttpDataModel(rowCount);
}
}

50
src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpTableDataDefine.java

@ -0,0 +1,50 @@
package com.fr.plugin.third.party.jsdiaij.data;
import com.fr.base.TableData;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.design.fun.ServerTableDataDefineProvider;
import com.fr.design.fun.impl.AbstractTableDataDefineProvider;
import com.fr.design.i18n.Toolkit;
public class CustomHttpTableDataDefine extends AbstractTableDataDefineProvider implements ServerTableDataDefineProvider {
@Override
public int currentAPILevel() {
return CURRENT_LEVEL;
}
@Override
public Class<? extends TableData> classForTableData() {
return CustomHttpTableData.class;
}
@Override
public Class<? extends TableData> classForInitTableData() {
return CustomHttpTableData.class;
}
@Override
public Class<? extends AbstractTableDataPane> appearanceForTableData() {
return CustomHttpTableDataPane.class;
}
@Override
public String nameForTableData() {
return Toolkit.i18nText("IDS用户数据集");
}
@Override
public String prefixForTableData() {
return "ids";
}
@Override
public String iconPathForTableData() {
return "";
}
}

76
src/main/java/com/fr/plugin/third/party/jsdiaij/data/CustomHttpTableDataPane.java

@ -0,0 +1,76 @@
package com.fr.plugin.third.party.jsdiaij.data;
import com.fanruan.api.design.DesignKit;
import com.fanruan.api.design.ui.component.UIButton;
import com.fr.design.data.datapane.preview.PreviewTablePane;
import com.fr.design.data.tabledata.tabledatapane.AbstractTableDataPane;
import com.fr.general.IOUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CustomHttpTableDataPane extends AbstractTableDataPane<CustomHttpTableData> {
public CustomHttpTableDataPane() {
super();
createContent();
}
@Override
public void populateBean(CustomHttpTableData ob) {
if (ob == null) {
return;
}
}
@Override
public CustomHttpTableData updateBean() {
CustomHttpTableData tableData = new CustomHttpTableData();
return tableData;
}
@Override
protected String title4PopupWindow() {
return DesignKit.i18nText("IDS用户数据集");
}
private void createContent() {
setLayout(new BorderLayout());
JPanel contentPane = new JPanel();
contentPane.setLayout(new BorderLayout());
add(contentPane, BorderLayout.CENTER);
JPanel connectionPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
UIButton previewButton = createIconButton("Fine-Design_Basic_Preview", "/com/fr/design/images/m_file/preview.png");
previewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PreviewTablePane.previewTableData(updateBean());
}
});
connectionPanel.add(previewButton);
contentPane.add(connectionPanel, BorderLayout.NORTH);
}
/**
* 获取图标按钮
*
* @param toolTip 提示信息,国际化key
* @param iconPath 图标路径
* @return
*/
public static UIButton createIconButton(String toolTip, String iconPath) {
UIButton iconButton = new UIButton(IOUtils.readIcon(iconPath));
iconButton.setToolTipText(DesignKit.i18nText(toolTip));
return iconButton;
}
}

67
src/main/java/com/fr/plugin/third/party/jsdiaij/data/DatasetData.java

@ -0,0 +1,67 @@
package com.fr.plugin.third.party.jsdiaij.data;
import java.util.ArrayList;
import java.util.List;
/**
* 数据集数据
*/
public class DatasetData {
private String name;
private List<String> columns;
private List<List<Object>> values;
public DatasetData() {
columns = new ArrayList<String>();
values = new ArrayList<List<Object>>();
}
/**
* 获取表名
* @return 表名
*/
public String getName() {
return this.name;
}
/**
* 设置表名
* @param name 表名
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取列名
* @return 列名
*/
public List<String> getColumns() {
return this.columns;
}
/**
* 设置列名
* @param columns 列名
*/
public void setColumns(List<String> columns) {
this.columns = columns;
}
/**
* 获取表数据
* @return 表数据
*/
public List<List<Object>> getValues() {
return this.values;
}
/**
* 设置表数据
* @param values
*/
public void setValues(List<List<Object>> values) {
this.values = values;
}
}

189
src/main/java/com/fr/plugin/third/party/jsdiaij/http/SessionGlobalRequestFilterProvider.java

@ -0,0 +1,189 @@
package com.fr.plugin.third.party.jsdiaij.http;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.data.NetworkHelper;
import com.fr.decision.authority.data.User;
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider;
import com.fr.decision.mobile.terminal.TerminalHandler;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.login.TokenResource;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.general.ComparatorUtils;
import com.fr.plugin.third.party.jsdiaij.config.CustomDataConfig;
import com.fr.plugin.third.party.jsdiaij.oauth.IdsQuery;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
public class SessionGlobalRequestFilterProvider extends AbstractGlobalRequestFilterProvider {
private static String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36";
@Override
public String filterName() {
return "com.fr.plugin.third.party.jsd8089";
}
@Override
public String[] urlPatterns() {
return new String[]{"/decision", "/decision/*"};
}
@Override
public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
try {
String fullUrl = getFullUrl(req);
String method = req.getMethod();
LogKit.info("IDS认证登录集成,记录访问地址:" + method + " " + fullUrl);
if (fullUrl.indexOf("/remote/") >= 0) {
filterChain.doFilter(req, res);
return;
}
if (!isAllow(req)) {
filterChain.doFilter(req, res);
return;
}
//boolean option = isLogged(req);
//if (option) {
// filterChain.doFilter(req, res);
// return;
//}
String loginUsername = IdsQuery.getUserId(req);
if (StringKit.isEmpty(loginUsername)) {
filterChain.doFilter(req, res);
return;
}
LogKit.info("IDS认证登录集成,用户名:" + loginUsername);
User user = UserService.getInstance().getUserByUserName(loginUsername);
boolean tipsOption = false;
if (user == null) {
tipsOption = true;
LogKit.info("IDS认证登录集成,用户名:" + loginUsername + "在报表平台不存在");
} else if (!user.isEnable()) {
tipsOption = true;
LogKit.info("IDS认证登录集成,用户名:" + loginUsername + "在报表平台上被禁用");
}
if (tipsOption) {
filterChain.doFilter(req, res);
return;
}
String loginToken = LoginService.getInstance().login(req, res, loginUsername);
req.setAttribute("fine_auth_token", loginToken);
if (!tipsOption) {
String frUrl = getRequestUrl(req);
sendRedirect(res, frUrl);
return;
}
filterChain.doFilter(req, res);
} catch (Exception e) {
LogKit.error("IDS认证登录集成出错," + e.getMessage(), e);
}
}
private boolean isAllow(HttpServletRequest req) {
if (req == null) {
return false;
}
String method = req.getMethod();
if (!"POST".equalsIgnoreCase(method)) {
return false;
}
String url = req.getRequestURL().toString();
if (url.endsWith("/decision") || url.endsWith("/decision/")) {
return true;
}
return false;
}
private String getRequestUrl(HttpServletRequest req) {
String fullUrl = req.getRequestURL().toString();
Map<String, String[]> paraMap = req.getParameterMap();
String paraName;
String[] paraValues;
String loginTypeParaName = CustomDataConfig.getInstance().getTokenName();
String queryStr = "";
for (Map.Entry<String, String[]> entry : paraMap.entrySet()) {
paraName = entry.getKey();
if (ComparatorUtils.equals(paraName, loginTypeParaName)) {
continue;
}
if (ComparatorUtils.equals(paraName, "SSOToken")) {
continue;
}
if (ComparatorUtils.equals(paraName, "ticket")) {
continue;
}
paraValues = entry.getValue();
queryStr = addParaToQuery(queryStr, paraName, paraValues);
}
if (StringKit.isEmpty(queryStr)) {
return fullUrl;
}
fullUrl = fullUrl + "?" + queryStr;
return fullUrl;
}
private String addParaToQuery(String query, String paraName, String[] paraValues) {
if (StringKit.isEmpty(paraName)) {
return query;
}
String fullQuery = query;
if ((paraValues == null) || (paraValues.length <= 0)) {
if (StringKit.isNotEmpty(fullQuery)) {
fullQuery = fullQuery + "&";
}
fullQuery = paraName + "=";
return fullQuery;
}
for (int i = 0, max = paraValues.length - 1; i <= max; i++) {
if (StringKit.isNotEmpty(fullQuery)) {
fullQuery = fullQuery + "&";
}
fullQuery = fullQuery + paraName + "=" + paraValues[i];
}
return fullQuery;
}
private void sendRedirect(HttpServletResponse res, String url) {
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
res.setHeader("Location", url);
}
public boolean isLogged(HttpServletRequest req) {
boolean logged = true;
try {
String token = TokenResource.COOKIE.getToken(req);
LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, NetworkHelper.getDevice(req)));
} catch (Exception var4) {
logged = false;
}
return logged;
}
private String getFullUrl(HttpServletRequest req) {
String url = req.getRequestURL().toString();
String queryUrl = req.getQueryString();
if (StringKit.isEmpty(queryUrl) || "null".equalsIgnoreCase(queryUrl)) {
queryUrl = "";
} else {
queryUrl = "?" + queryUrl;
}
String fullUrl = url + queryUrl;
return fullUrl;
}
}

380
src/main/java/com/fr/plugin/third/party/jsdiaij/oauth/DesUtil.java

@ -0,0 +1,380 @@
/*
* Title: TRS 身份服务器 Copyright: Copyright (c) 2004-2011, TRS信息技术股份有限公司. All rights reserved. License: see the license
* file. Company: TRS信息技术股份有限公司(www.trs.com.cn)
*
* Created: shixin@2011-3-2 上午08:18:45
*/
package com.fr.plugin.third.party.jsdiaij.oauth;
import com.trs.idm.util.Base64Util;
import com.trs.idm.util.StringHelper;
import org.apache.log4j.Logger;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
/**
* DES加密处理工具类.主要用来对数据进行DES加密/解密操作 <BR>
*
* @author fr.open
* @since fr.open
*/
public class DesUtil {
/**
* DES算法名称
*/
private final static String DES_ALGORITHM_NAME = "DES";
/**
* 默认的DES算法转换方式
*/
private final static String DES_ALGORITHM_TRANSFORMATION_DEFAULT = "DES/ECB/PKCS5Padding";
private static final Logger logger = Logger.getLogger(DesUtil.class);
private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* 根据指定密钥对数据DES加密返回16进制字符串数据<br>
* 默认转换模式transformation为DES/ECB/PKCS5Padding
*
* @param toEncryptData
* 需要加密的数据
* @param keyData
* 密钥数据内容, 使用该数据的byte[]缓冲区前 8 个字节作为密钥
* @return 返回加密后的数据以16进制字符串形式表示 @
*
* @creator TRS
*/
public static String encryptToHex(byte[] toEncryptData, String keyData) {
byte[] encryptedData = doEncrypt(getKeyByData(keyData), toEncryptData, DES_ALGORITHM_TRANSFORMATION_DEFAULT);
if (null == encryptedData) {
return "";
}
return bytesToHex(encryptedData, 0, encryptedData.length);
}
/**
* 指定密钥和转换方式进行数据加密
*
* @param key
* 密钥
* @param toEncryptData
* 要加密的数据
* @param transformation
* 转换的名称例如 DES/CBC/PKCS5Padding有关标准转换名称的信息请参见 Java
* Cryptography Architecture Reference Guide 的附录 A
* @return 加密后的数据
*
* @creator TRS
*/
public static byte[] doEncrypt(Key key, byte[] toEncryptData, String transformation) {
if (null == toEncryptData) {
return null;
}
// Get a cipher object
Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE, transformation);
// Encrypt
byte[] encryptedData = null;
try {
encryptedData = cipher.doFinal(toEncryptData);
} catch (IllegalBlockSizeException e) {
} catch (BadPaddingException e) {
}
return encryptedData;
}
/**
* 获取Cipher加密和解密对象
*
* @param key
* 密钥
* @param cipherMode
* Cipher的操作模式为以下之一ENCRYPT_MODEDECRYPT_MODEWRAP_MODE
* UNWRAP_MODE
* @param transformation
* 转换的名称例如 DES/CBC/PKCS5Padding有关标准转换名称的信息请参见 Java
* Cryptography Architecture Reference Guide 的附录 A
* @return
* @creator TRS
*/
public static Cipher getCipher(Key key, int cipherMode, String transformation) {
Cipher cipher = null;
try {
cipher = Cipher.getInstance(transformation);
} catch (NoSuchAlgorithmException e) {
} catch (NoSuchPaddingException e) {
}
try {
cipher.init(cipherMode, key);
} catch (InvalidKeyException e) {
}
return cipher;
}
/**
* 根据指定密钥对DES加密数据进行解密
*
* @pram encryptedDataHex 加密字符串(十六进制)
* @param keyData
* 密钥
* @return 解密字符串
* @throws Throwable
*
* @creator TRS
*/
public static String decrypt(String encryptedDataHex, String keyData) {
if (encryptedDataHex == null || encryptedDataHex.length() == 0) {
return "";
}
String decryptedHexStr = DesUtil.decryptToHex(StringHelper.toBytes(encryptedDataHex), keyData);
return hexToStr(decryptedHexStr);
}
/**
* 根据指定的密钥数据内容对数据进行DES解密并返回16进制字符串数据<br>
* 默认转换模式transformation为DES/ECB/PKCS5Padding
*
* @param toDecryptData
* 要解密的数据
* @param keyData
* DES密钥数据使用该数据的byte[]缓冲区前 8 个字节作为密钥
* @return 返回解密后的数据以16进制字符串形式表示 @
*
* @creator TRS
*/
public static String decryptToHex(byte[] toDecryptData, String keyData) {
byte[] decryptedData = doDecrypt(getKeyByData(keyData), toDecryptData, DES_ALGORITHM_TRANSFORMATION_DEFAULT);
if (null == decryptedData) {
return "";
}
return bytesToHex(decryptedData, 0, decryptedData.length);
}
/**
* 指定密钥和转换方式进行数据解密
*
* @param key
* 密钥
* @param toDecryptData
* 要解密的数据
* @param transformation
* * 转换的名称例如 DES/CBC/PKCS5Padding有关标准转换名称的信息请参见 Java
* Cryptography Architecture Reference Guide 的附录 A
* @return 解密后的数据
* @since
* @creator TRS
*/
public static byte[] doDecrypt(Key key, byte[] toDecryptData, String transformation) {
if (null == toDecryptData) {
return null;
}
// Get a cipher object
Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE, transformation);
// Decrypt
byte[] decryptedData = null;
try {
decryptedData = cipher.doFinal(toDecryptData);
} catch (IllegalBlockSizeException e) {
} catch (BadPaddingException e) {
}
return decryptedData;
}
/**
* 根据指定的算法名称和密钥规范获取密钥
*
* @param algorithm
* 所请求的秘密密钥算法的标准名称, "DES"有关标准算法名称的信息请参阅 Java Cryptography
* Architecture Reference Guide 中的附录 A
* @param keySpec
* 组成加密密钥的密钥内容的透明规范
* @return
* @creator TRS
*/
public static SecretKey getKey(String algorithm, KeySpec keySpec) {
SecretKeyFactory keyFactory = null;
try {
keyFactory = SecretKeyFactory.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
}
try {
return keyFactory.generateSecret(keySpec);
} catch (InvalidKeySpecException e) {
}
return null;
}
/**
* 根据密钥数据生成DES密钥
*
* @param keyData
* DES密钥数据使用该数据的byte[]缓冲区前 8 个字节作为密钥
* @return DES密钥
*
* @creator TRS
*/
public static SecretKey getKeyByData(String keyData) {
DESKeySpec desKeySpec = null;
try {
desKeySpec = new DESKeySpec(keyData.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return getKey(DES_ALGORITHM_NAME, desKeySpec);
}
/**
* 将给定的字节数组用十六进制字符串表示.
*/
public static String toString(byte[] data) {
if (data == null) {
return "null!";
}
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = DIGITS[0x0F & data[i]];
}
return new String(out);
}
/**
* 把输入的字节树组逐字节转化为其16进制的文本描述形式
*
* @param buf
* 输入的字节树组
* @param off
* 需要转化的开始位置
* @param len
* 需要转化的结束位置
* @return 转化结果
*/
public final static String bytesToHex(byte[] buf, int off, int len) {
char[] out = new char[len * 2];
for (int i = 0, j = 0; i < len; i++) {
int a = buf[off++];
out[j++] = DIGITS[(a >>> 4) & 0X0F];
out[j++] = DIGITS[a & 0X0F];
}
return (new String(out));
}
/**
*
* @param ch
* @param index
* @return
*/
static int toDigit(char ch, int index) {
int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new RuntimeException("Illegal hexadecimal charcter " + ch + " at index " + index);
}
return digit;
}
public static String hexToStr(String hex) {
return new String(toBytes(hex));
}
/**
* 将给定的十六进制字符串转化为字节数组. <BR>
* <code>toString(byte[] data)</code>作用相反.
*
* @throws RuntimeException
* 当给定十六进制字符串的长度为奇数时或给定字符串包含非十六进制字符.
* @see #toString(byte[])
*/
public static byte[] toBytes(String str) {
if (str == null) {
return null;
}
char[] data = str.toCharArray();
int len = data.length;
if ((len & 0x01) != 0) {
throw new RuntimeException("Odd number of characters!");
}
byte[] out = new byte[len >> 1];
// two characters form the hex value.
for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
/**
*
* 对指定的字符串进行加密
*
* @param data
* 需要加密的数据
*
* @param digestAlgorithm
* 签名算法
* @param secretKey
* 密钥
* @return 返回签名和加密数据组成的串
*
* @throws Exception
*/
public static String encrypt(String data, String digestAlgorithm, String secretKey) throws Exception {
// 2、根据拼成的整串生成消息摘要签名
MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
md.update(data.getBytes("UTF-8"));
byte[] digestByte = md.digest();
String digest = StringHelper.toString(digestByte);
if (logger.isDebugEnabled()) {
logger.debug("caller create digest is [" + digest + "] by digestAlgorithm [" + digestAlgorithm + "] , secretKey [" + secretKey + "] !");
}
// 3、对拼成的整串做base64编码
String dataAfterBase64Encode = Base64Util.encode(data, "UTF-8");
if (logger.isDebugEnabled()) {
logger.debug("after base64 encode data is [" + dataAfterBase64Encode + "] , before base64 encode data is [" + data + "] !");
}
// 4、对base64编码后的消息做DES加密
String dataAfterDESEncode = DesUtil.encryptToHex(dataAfterBase64Encode.getBytes("UTF-8"), secretKey);
if (logger.isDebugEnabled()) {
logger.debug("after des encrypt data is [" + dataAfterDESEncode + "] , secretKey is [" + secretKey + "] !");
}
// 5、将消息摘要与加密后的数据拼成整串 格式:摘要签名&加密后的数据
String finalData = digest + "&" + dataAfterDESEncode;
if (logger.isDebugEnabled()) {
logger.debug("caller post ids encrypted data is [" + finalData + "] , digest is [" + digest + "] , dataAfterDESEncode is ["
+ dataAfterDESEncode + "] !");
}
return finalData;
}
}

246
src/main/java/com/fr/plugin/third/party/jsdiaij/oauth/IDSAPICall.java

@ -0,0 +1,246 @@
package com.fr.plugin.third.party.jsdiaij.oauth;
import com.trs.idm.util.Base64Util;
import com.trs.idm.util.StringHelper;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.log4j.Logger;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class IDSAPICall {
/**
* 接口服务地址 需要到具体到接口地址
*/
private String serviceUrl;
private String secretKey;
private String digestAlgorithm;
private String appName;
private String responseType;
private static final Logger logger = Logger.getLogger(IDSAPICall.class);
/**
* 错误提示消息摘要不合法
*/
private static final String ERRPR_DIGEST_ILLEGALITY = "error.digest.illegality";
/**
* 错误提示IDS响应格式不合法
*/
private static final String ERROR_RESPONSE_ILLEGALITY = "error.response.illegality";
/**
* 错误提示调用IDS接口发送异常(网络异常等)
*/
private static final String ERROR_CALLING_EXCEPTION = "error.calling.exception";
/**
* 构造函数
*
* @param serviceUrl
* 接口服务url
* @param secretKey
* 密钥
* @param digestAlgorithm
* 签名算法 MD5SHA等注意区分大小写
*/
public IDSAPICall(String serviceUrl, String appName, String secretKey, String digestAlgorithm) {
this.serviceUrl = serviceUrl;
this.secretKey = secretKey;
this.appName = appName;
this.digestAlgorithm = digestAlgorithm;
this.responseType = "json";
}
public String Call(String method, String data) throws Exception {
PostMethod methodPost = null;
if (isHttpSSOAPI(serviceUrl)) {
methodPost = new PostMethod(serviceUrl + "&serviceName=" + method);
methodPost.addParameter("coAppName", appName);
} else {
methodPost = new PostMethod(serviceUrl + "&method=" + method);
methodPost.addParameter("appName", appName);
}
methodPost.addParameter("type", responseType);
String encryptedData = DesUtil.encrypt(data, digestAlgorithm, secretKey);
methodPost.addParameter("data", encryptedData);
HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(methodPost);
} catch (Exception e) {
logger.error("calling ids api has exception !", e);
throw new Exception(ERROR_CALLING_EXCEPTION, e);
}
String responsePost = new String(methodPost.getResponseBody(), "UTF-8");
String[] digestAndResult = StringHelper.split(responsePost, "&");
if (digestAndResult.length != 2) {
logger.error("response from ids format is illegality ! after split is digestAndResult [" + digestAndResult + "]");
throw new Exception(ERROR_RESPONSE_ILLEGALITY);
}
String digestOfServer = digestAndResult[0];
String result = digestAndResult[1];
// 8、对响应结果进行解密
String afterDESResult = DesUtil.decrypt(result, secretKey);
if (logger.isDebugEnabled()) {
logger.debug("after des decrypt response is [" + afterDESResult + "] , decrypt secretKey is [" + secretKey + "] !");
}
// 9、对解密后的结果做base64反解
String plaintextResponse = Base64Util.decode(afterDESResult, "UTF-8");
if (logger.isDebugEnabled()) {
logger.debug("after base64 decode plaintext response is [" + plaintextResponse + "] , before base64 decode response is ["
+ afterDESResult + "] !");
}
// 10、本地生成消息摘要与IDS返回的摘要对比,如果不相等则说明数据在传输过程中被篡改过
MessageDigest sd = MessageDigest.getInstance(digestAlgorithm);
sd.update(plaintextResponse.getBytes("UTF-8"));
String digestOfAgent = StringHelper.toString(sd.digest());
if (false == digestOfAgent.equals(digestOfServer)) {
logger.error("response from ids digest [" + digestOfServer + "] not eq client create digest [" + digestOfAgent + "] !");
throw new Exception(ERRPR_DIGEST_ILLEGALITY);
}
return plaintextResponse;
}
public String Call2Json(String method, String data) throws Exception {
this.responseType = "json";
return Call(method, data);
}
public String Call2Xml(String method, String data) throws Exception {
this.responseType = "xml";
return Call(method, data);
}
public String Call(String method, Map<String, String> params) throws Exception {
String data = "";
if (null != params && !params.isEmpty()) {
for (Iterator<Entry<String, String>> iterator = params.entrySet().iterator(); iterator.hasNext();) {
Entry<String, String> v = (Entry<String, String>) iterator.next();
if (isEmpty(data)) {
data = v.getKey() + "=" + v.getValue();
} else {
data += "&" + v.getKey() + "=" + v.getValue();
}
}
}
return Call(method, data);
}
public String Call2Json(String method, Map<String, String> params) throws Exception {
this.responseType = "json";
return Call(method, params);
}
public String Call2Xml(String method, Map<String, String> params) throws Exception {
this.responseType = "xml";
return Call(method, params);
}
public static boolean isEmpty(String str) {
return (str == null || str.trim().length() == 0) ? true : false;
}
private static boolean isHttpSSOAPI(String serviceUrl) {
return serviceUrl.contains("idsServiceType=httpssoservice");
}
public static String accessToken(String serviceUrl, String clientId, String clientSecret, String code, String callbackUrl) throws Exception {
String accessTokenUrl = serviceUrl
+ "&method=accessToken"
+ "&client_id=" + clientId
+ "&client_secret=" + clientSecret
+ "&grant_type=authorization_code"
+ "&code=" + code
+ "&redirect_uri=" + URLEncoder.encode(callbackUrl, "UTF-8");
return call(accessTokenUrl, "GET");
}
public static String userInfo(String serviceUrl, String accessToken, String clientId, String clientSecret) throws Exception {
String userInfoUrl = serviceUrl
+ "&method=getUser"
+ "&token_type=bearer"
+ "&access_token=" + accessToken
+ "&client_id=" + clientId
+ "&client_secret=" + clientSecret;
return call(userInfoUrl, "GET");
}
public static String call(String requestUrl, String requestMethod) throws Exception {
return call(requestUrl, requestMethod, null);
}
public static String call(String requestUrl, String requestMethod, String outputStr) throws Exception {
String content = "";
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
int contentLength = 0;
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
int flag = str.indexOf("Content-Length");
if (flag != -1) {
contentLength = Integer.parseInt((str.split(":")[1]).trim());
}
buffer.append(str);
}
if (contentLength > 0) {
content = buffer.substring(buffer.length() - contentLength);
} else {
content = buffer.toString();
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("[call{" + requestUrl + "}]出错");
}
return content;
}
}

111
src/main/java/com/fr/plugin/third/party/jsdiaij/oauth/IdsQuery.java

@ -0,0 +1,111 @@
package com.fr.plugin.third.party.jsdiaij.oauth;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.json.JSONObject;
import com.fr.plugin.third.party.jsdiaij.config.CustomDataConfig;
import com.fr.web.utils.WebUtils;
import com.trs.ids.oauth.IDSAPICall;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class IdsQuery {
/**
* 获取用户信息
*
* @return
* @throws Exception
*/
public synchronized static String queryUsers(int userCount) throws Exception {
int pageSize = 100000;
if (userCount == 0) {
return "";
} else if (userCount >= 1) {
pageSize = userCount;
}
CustomDataConfig config = CustomDataConfig.getInstance();
String url = config.getIdsServiceUrl() + "?idsServiceType=remoteapi";
IDSAPICall idsapiCall = new IDSAPICall(url, config.getAppName(), config.getSecretKey(), config.getDigestAlgorithm());
String method = "qPagedUsersByFilter";
String data = "userName=admin&startPos=0&pageSize=" + pageSize + "&searchFilters=actived:=:true";
String content = idsapiCall.Call2Json(method, data);
LogKit.info("用户接口信息:\n"+content);
return content;
}
public synchronized static String getUserId(HttpServletRequest req) throws Exception {
CustomDataConfig config = CustomDataConfig.getInstance();
String token = WebUtils.getHTTPRequestParameter(req, config.getTokenName());
if (StringKit.isEmpty(token)) {
return "";
}
String url = config.getIdsServiceUrl() + "?idsServiceType=httpssoservice";
IDSAPICall idsapiCall = new IDSAPICall(url, config.getAppName(), config.getSecretKey(), config.getDigestAlgorithm());
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put("clientIP", req.getRemoteAddr());
paramMap.put("coSessionId", UUID.randomUUID().toString());
paramMap.put("ssoSessionId", token.split("_")[0]);
String method = "findUserBySSOID";
String content = idsapiCall.Call2Json(method, paramMap);
if (StringKit.isEmpty(content)) {
return "";
}
LogKit.info("IDS 获取用户名\n" + content);
JSONObject jsonObject = new JSONObject(content);
int code = jsonObject.getInt("code");
if (code != 200) {
return "";
}
JSONObject dataJson = jsonObject.getJSONObject("data");
if (dataJson == null) {
return "";
}
JSONObject userJson = dataJson.getJSONObject("user");
if (dataJson == null) {
return "";
}
String userId = userJson.getString("userName");
if (StringKit.isEmpty(userId)) {
return "";
}
userId = userId.toLowerCase();
return userId;
}
public synchronized static String searchGroups() throws Exception {
CustomDataConfig config = CustomDataConfig.getInstance();
String url = config.getIdsServiceUrl() + "?idsServiceType=remoteapi";
IDSAPICall idsapiCall = new IDSAPICall(url, config.getAppName(), config.getSecretKey(), config.getDigestAlgorithm());
String method = "searchGroups";
String data = "userName=admin";
String content = idsapiCall.Call2Json(method, data);
LogKit.info("部门接口信息:\n"+content);
return content;
}
public synchronized static String searchUserGroupsMapping() throws Exception {
CustomDataConfig config = CustomDataConfig.getInstance();
String url = config.getIdsServiceUrl() + "?idsServiceType=remoteapi";
IDSAPICall idsapiCall = new IDSAPICall(url, config.getAppName(), config.getSecretKey(), config.getDigestAlgorithm());
String method = "searchUserGroupsMapping";
String data = "";
String content = idsapiCall.Call2Json(method, data);
LogKit.info("部门中间表接口信息:\n"+content);
return content;
}
}

249
src/main/java/com/trs/idm/client/actor/IDSUser.java

@ -0,0 +1,249 @@
package com.trs.idm.client.actor;
public class IDSUser {
private int userId;
private String userName;
private String nickName;//昵称
private String trueName;//真实姓名
private String creditID;//身份证
private String realNameStatus;//实名认证
private String email;
private String mobile;
private String tel;
private String position;//职称
private int gender;//性别
private String createdDate;
private String nation;//国家
private String province;//身份
private String city;//城市
private String address;
private com.trs.idm.client.actor.SSOUser ssoUser;
public IDSUser(com.trs.idm.client.actor.SSOUser ssoUser){
this.ssoUser = ssoUser;
this.userId = Integer.parseInt(showNull(this.ssoUser.getProperty("userId"), "0"));
this.userName = this.ssoUser.getUserName();
this.nickName = this.ssoUser.getNickName();
this.trueName = this.ssoUser.getTrueName();
this.realNameStatus = this.ssoUser.getProperty("realNameStatus");
this.mobile = this.ssoUser.getProperty("mobile");
this.email = this.ssoUser.getMail();
this.tel = this.ssoUser.getProperty("tel");
this.position = this.ssoUser.getProperty("profession");
this.creditID = this.ssoUser.getProperty("creditID");
this.gender = Integer.parseInt(showNull(this.ssoUser.getProperty("gender"), "3"));
this.nation = this.ssoUser.getProperty("nation");
this.province = this.ssoUser.getProperty("province");
this.city = this.ssoUser.getProperty("city");
this.address = this.ssoUser.getProperty("IDSEXT_RESIDENT_COMMUNITY");
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getTrueName() {
return trueName;
}
public void setTrueName(String trueName) {
this.trueName = trueName;
}
public String getCreditID() {
return creditID;
}
public void setCreditID(String creditID) {
this.creditID = creditID;
}
public String getRealNameStatus() {
return realNameStatus;
}
public void setRealNameStatus(String realNameStatus) {
this.realNameStatus = realNameStatus;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
public String getNation() {
return nation;
}
public void setNation(String nation) {
this.nation = nation;
}
public String getProvince() {
return province;
}
public void setProvince(String province) {
this.province = province;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public com.trs.idm.client.actor.SSOUser getSsoUser() {
return ssoUser;
}
public void setSsoUser(com.trs.idm.client.actor.SSOUser ssoUser) {
this.ssoUser = ssoUser;
}
/**
* 性别名称
* @return
*/
public String getGenderName(){
if(this.gender == 1){
return "男";
}else if(this.gender == 2){
return "女";
}
return "保密";
}
/**
* 用户认证类型
* @return
*/
public String getRealNameStatusStr(){
String realNameStatusStr = "";
if("PASSED_WITHREALNAME".equals(realNameStatus)){
realNameStatusStr = "普通实名认证";
}
else if("PASSED_ADVANCED".equals(realNameStatus)){
realNameStatusStr = "高级实名认证";
}
else{
realNameStatusStr = "未通过实名认证";
}
return realNameStatusStr;
}
/**
* 高级实名认证
* @return
*/
public boolean isAdvanced(){
if(isEmpty(this.getRealNameStatus())){
return false;
}
if("PASSED_ADVANCED".equals(this.getRealNameStatus())){
return true;
}
return false;
}
private boolean isEmpty(String str){
return (str == null || str.trim().length() == 0) ? true : false;
}
private String showNull(String str, String defaultValue){
return isEmpty(str) ? defaultValue : str;
}
}

151
src/main/java/com/trs/idm/client/actor/TRSIDSServletAppActor.java

@ -0,0 +1,151 @@
package com.trs.idm.client.actor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
/**
*
* Title: Filter集成模式 <BR>
* Description: <BR>
* 注意事项<BR>
* 1同步退出
* 必须使用IDS的退出地址
* 必须设置身份同步中的同步的目标为IDS服务器可以调用到的地址如配置127.0.0.1或者localhost这些IDS服务器无法访问到的地址无法进行同步退出
* 2使用匿名登入方式
* 设置trsids-agent.properties中allow.anonymous的值y
*/
public class TRSIDSServletAppActor extends StdHttpSessionBasedActor {
private static Logger logger;
static {
logger = Logger.getLogger(TRSIDSServletAppActor.class);
}
/**
* 添加组织
* 协作应用同步添加组织的实现.返回 true, 表示同步成功;否则表示同步失败
*
*/
@Override
public boolean addGroup(SSOGroup group, HttpServletRequest req) {
// TODO Auto-generated method stub
return super.addGroup(group, req);
}
/**
* 删除组织
* 协作应用同步删除组织的实现.返回 true, 表示同步成功;否则表示同步失败
*/
@Override
public boolean delGroup(SSOGroup group, HttpServletRequest req) {
// TODO Auto-generated method stub
return super.delGroup(group, req);
}
/**
* 更新组织
* 协作应用同步更新组织的实现.返回 true, 表示同步成功;否则表示同步失败
*/
@Override
public boolean updateGroup(SSOGroup group, HttpServletRequest req) {
// TODO Auto-generated method stub
return super.updateGroup(group, req);
}
//协作应用同步增加用户的实现.返回 true, 表示同步成功;否则表示同步失败
@Override
public boolean addUser(SSOUser ssoUser, HttpServletRequest arg1) throws ActorException {
logger.debug("IDS调用-添加用户【" + ssoUser.getUserName() + "】");
return true;
}
@Override
public boolean disableUser(SSOUser ssoUser) throws ActorException {
logger.debug("IDS调用-禁用用户【" + ssoUser.getUserName() + "】");
return true;
}
@Override
public boolean enableUser(SSOUser ssoUser) throws ActorException {
logger.debug("IDS调用-启用用户【" + ssoUser.getUserName() + "】");
return true;
}
//从协作应用的自有登录页面的表单中获取用户名(匿名应用使用自已的登录页面需要实现)
@Override
public String extractUserName(HttpServletRequest request) throws ActorException {
return request.getParameter("userName");
}
//从协作应用的自有登录页面的表单中获取密码(匿名应用使用自已的登录页面需要实现)
@Override
public String extractUserPwd(HttpServletRequest request) throws ActorException {
return request.getParameter("password");
}
//协作应用同步删除用户的实现. 返回 true, 表示同步成功;否则表示同步失败.
@Override
public boolean removeUser(SSOUser ssoUser, HttpServletRequest arg1) throws ActorException {
logger.debug("IDS调用-删除用户【" + ssoUser.getUserName() + "】");
return true;
}
//协作应用同步更新用户的实现. 返回 true, 表示同步成功;否则表示同步失败.
@Override
public boolean updateUser(SSOUser ssoUser, HttpServletRequest request) throws ActorException {
String userName = ssoUser.getUserName();
logger.debug("IDS调用-修改用户【" + userName + "】");
return true;
}
@Override
public boolean userExist(SSOUser ssoUser) throws ActorException {
logger.debug("IDS调用-判断是否存在用户");
return false;
}
//检查登录:判断协作应用当前 Session 是否登录
@Override
public boolean checkLocalLogin(HttpSession session) throws ActorException {
IDSUser loginUser = (IDSUser)session.getAttribute("loginUser");
logger.debug("IDS调用-验证用户是否存在: " + loginUser);
if (null != loginUser) {
return true;
}
return false;
}
/**
* 执行登录加载登录的统一用户到协作应用的当前会话(Session 对象),
* 完成协作应用自己的登录逻辑(不需要再次对用户进行认证, 只需要加载)
* @Title:
* @Description: TODO
* void
*/
@Override
public void loadLoginUser(HttpServletRequest request, SSOUser ssoUser) throws ActorException {
logger.debug(ssoUser.getProperties());
logger.debug("IDS调用-用户登入: " + ssoUser.getUserName());
IDSUser loginUser = new IDSUser(ssoUser);
request.getSession().setAttribute("loginUser", loginUser);
}
//注销退出:完成协作应用自己的退出登录的逻辑
@Override
public void logout(HttpSession session) throws ActorException {
session.invalidate();
}
public static IDSUser getLoginUser(HttpServletRequest request){
IDSUser loginUser = (IDSUser) request.getSession().getAttribute("loginUser");
return loginUser;
}
}

387
src/main/java/com/trs/ids/oauth/DesUtil.java

@ -0,0 +1,387 @@
/*
* Title: TRS 身份服务器 Copyright: Copyright (c) 2004-2011, TRS信息技术股份有限公司. All rights reserved. License: see the license
* file. Company: TRS信息技术股份有限公司(www.trs.com.cn)
*
* Created: shixin@2011-3-2 上午08:18:45
*/
package com.trs.ids.oauth;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.log4j.Logger;
import com.trs.idm.util.Base64Util;
import com.trs.idm.util.StringHelper;
/**
* DES加密处理工具类.主要用来对数据进行DES加密/解密操作 <BR>
*
* @author TRS信息技术有限公司
* @since TRS
*/
public class DesUtil {
/**
* DES算法名称
*/
private final static String DES_ALGORITHM_NAME = "DES";
/**
* 默认的DES算法转换方式
*/
private final static String DES_ALGORITHM_TRANSFORMATION_DEFAULT = "DES/ECB/PKCS5Padding";
private static final Logger logger = Logger.getLogger(DesUtil.class);
private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
/**
* 根据指定密钥对数据DES加密返回16进制字符串数据<br>
* 默认转换模式transformation为DES/ECB/PKCS5Padding
*
* @param toEncryptData
* 需要加密的数据
* @param keyData
* 密钥数据内容, 使用该数据的byte[]缓冲区前 8 个字节作为密钥
* @return 返回加密后的数据以16进制字符串形式表示 @
*
* @creator TRS
*/
public static String encryptToHex(byte[] toEncryptData, String keyData) {
byte[] encryptedData = doEncrypt(getKeyByData(keyData), toEncryptData, DES_ALGORITHM_TRANSFORMATION_DEFAULT);
if (null == encryptedData) {
return "";
}
return bytesToHex(encryptedData, 0, encryptedData.length);
}
/**
* 指定密钥和转换方式进行数据加密
*
* @param key
* 密钥
* @param toEncryptData
* 要加密的数据
* @param transformation
* 转换的名称例如 DES/CBC/PKCS5Padding有关标准转换名称的信息请参见 Java
* Cryptography Architecture Reference Guide 的附录 A
* @return 加密后的数据
*
* @creator TRS
*/
public static byte[] doEncrypt(Key key, byte[] toEncryptData, String transformation) {
if (null == toEncryptData) {
return null;
}
// Get a cipher object
Cipher cipher = getCipher(key, Cipher.ENCRYPT_MODE, transformation);
// Encrypt
byte[] encryptedData = null;
try {
encryptedData = cipher.doFinal(toEncryptData);
} catch (IllegalBlockSizeException e) {
} catch (BadPaddingException e) {
}
return encryptedData;
}
/**
* 获取Cipher加密和解密对象
*
* @param key
* 密钥
* @param cipherMode
* Cipher的操作模式为以下之一ENCRYPT_MODEDECRYPT_MODEWRAP_MODE
* UNWRAP_MODE
* @param transformation
* 转换的名称例如 DES/CBC/PKCS5Padding有关标准转换名称的信息请参见 Java
* Cryptography Architecture Reference Guide 的附录 A
* @return
* @creator TRS
*/
public static Cipher getCipher(Key key, int cipherMode, String transformation) {
Cipher cipher = null;
try {
cipher = Cipher.getInstance(transformation);
} catch (NoSuchAlgorithmException e) {
} catch (NoSuchPaddingException e) {
}
try {
cipher.init(cipherMode, key);
} catch (InvalidKeyException e) {
}
return cipher;
}
/**
* 根据指定密钥对DES加密数据进行解密
*
* @pram encryptedDataHex 加密字符串(十六进制)
* @param keyData
* 密钥
* @return 解密字符串
* @throws Throwable
*
* @creator TRS
*/
public static String decrypt(String encryptedDataHex, String keyData) {
if (encryptedDataHex == null || encryptedDataHex.length() == 0) {
return "";
}
String decryptedHexStr = DesUtil.decryptToHex(StringHelper.toBytes(encryptedDataHex), keyData);
return hexToStr(decryptedHexStr);
}
/**
* 根据指定的密钥数据内容对数据进行DES解密并返回16进制字符串数据<br>
* 默认转换模式transformation为DES/ECB/PKCS5Padding
*
* @param toDecryptData
* 要解密的数据
* @param keyData
* DES密钥数据使用该数据的byte[]缓冲区前 8 个字节作为密钥
* @return 返回解密后的数据以16进制字符串形式表示 @
*
* @creator TRS
*/
public static String decryptToHex(byte[] toDecryptData, String keyData) {
byte[] decryptedData = doDecrypt(getKeyByData(keyData), toDecryptData, DES_ALGORITHM_TRANSFORMATION_DEFAULT);
if (null == decryptedData) {
return "";
}
return bytesToHex(decryptedData, 0, decryptedData.length);
}
/**
* 指定密钥和转换方式进行数据解密
*
* @param key
* 密钥
* @param toDecryptData
* 要解密的数据
* @param transformation
* * 转换的名称例如 DES/CBC/PKCS5Padding有关标准转换名称的信息请参见 Java
* Cryptography Architecture Reference Guide 的附录 A
* @return 解密后的数据
* @since
* @creator TRS
*/
public static byte[] doDecrypt(Key key, byte[] toDecryptData, String transformation) {
if (null == toDecryptData) {
return null;
}
// Get a cipher object
Cipher cipher = getCipher(key, Cipher.DECRYPT_MODE, transformation);
// Decrypt
byte[] decryptedData = null;
try {
decryptedData = cipher.doFinal(toDecryptData);
} catch (IllegalBlockSizeException e) {
} catch (BadPaddingException e) {
}
return decryptedData;
}
/**
* 根据指定的算法名称和密钥规范获取密钥
*
* @param algorithm
* 所请求的秘密密钥算法的标准名称, "DES"有关标准算法名称的信息请参阅 Java Cryptography
* Architecture Reference Guide 中的附录 A
* @param keySpec
* 组成加密密钥的密钥内容的透明规范
* @return
* @creator TRS
*/
public static SecretKey getKey(String algorithm, KeySpec keySpec) {
SecretKeyFactory keyFactory = null;
try {
keyFactory = SecretKeyFactory.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
}
try {
return keyFactory.generateSecret(keySpec);
} catch (InvalidKeySpecException e) {
}
return null;
}
/**
* 根据密钥数据生成DES密钥
*
* @param keyData
* DES密钥数据使用该数据的byte[]缓冲区前 8 个字节作为密钥
* @return DES密钥
*
* @creator TRS
*/
public static SecretKey getKeyByData(String keyData) {
DESKeySpec desKeySpec = null;
try {
desKeySpec = new DESKeySpec(keyData.getBytes());
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return getKey(DES_ALGORITHM_NAME, desKeySpec);
}
/**
* 将给定的字节数组用十六进制字符串表示.
*/
public static String toString(byte[] data) {
if (data == null) {
return "null!";
}
int l = data.length;
char[] out = new char[l << 1];
// two characters form the hex value.
for (int i = 0, j = 0; i < l; i++) {
out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = DIGITS[0x0F & data[i]];
}
return new String(out);
}
/**
* 把输入的字节树组逐字节转化为其16进制的文本描述形式
*
* @param buf
* 输入的字节树组
* @param off
* 需要转化的开始位置
* @param len
* 需要转化的结束位置
* @return 转化结果
*/
public final static String bytesToHex(byte[] buf, int off, int len) {
char[] out = new char[len * 2];
for (int i = 0, j = 0; i < len; i++) {
int a = buf[off++];
out[j++] = DIGITS[(a >>> 4) & 0X0F];
out[j++] = DIGITS[a & 0X0F];
}
return (new String(out));
}
/**
*
* @param ch
* @param index
* @return
*/
static int toDigit(char ch, int index) {
int digit = Character.digit(ch, 16);
if (digit == -1) {
throw new RuntimeException("Illegal hexadecimal charcter " + ch + " at index " + index);
}
return digit;
}
public static String hexToStr(String hex) {
return new String(toBytes(hex));
}
/**
* 将给定的十六进制字符串转化为字节数组. <BR>
* <code>toString(byte[] data)</code>作用相反.
*
* @throws RuntimeException
* 当给定十六进制字符串的长度为奇数时或给定字符串包含非十六进制字符.
* @see #toString(byte[])
*/
public static byte[] toBytes(String str) {
if (str == null) {
return null;
}
char[] data = str.toCharArray();
int len = data.length;
if ((len & 0x01) != 0) {
throw new RuntimeException("Odd number of characters!");
}
byte[] out = new byte[len >> 1];
// two characters form the hex value.
for (int i = 0, j = 0; j < len; i++) {
int f = toDigit(data[j], j) << 4;
j++;
f = f | toDigit(data[j], j);
j++;
out[i] = (byte) (f & 0xFF);
}
return out;
}
/**
*
* 对指定的字符串进行加密
*
* @param data
* 需要加密的数据
*
* @param digestAlgorithm
* 签名算法
* @param secretKey
* 密钥
* @return 返回签名和加密数据组成的串
*
* @throws Exception
*/
public static String encrypt(String data, String digestAlgorithm, String secretKey) throws Exception {
// 2、根据拼成的整串生成消息摘要签名
MessageDigest md = MessageDigest.getInstance(digestAlgorithm);
md.update(data.getBytes("UTF-8"));
byte[] digestByte = md.digest();
String digest = StringHelper.toString(digestByte);
if (logger.isDebugEnabled()) {
logger.debug("caller create digest is [" + digest + "] by digestAlgorithm [" + digestAlgorithm + "] , secretKey [" + secretKey + "] !");
}
// 3、对拼成的整串做base64编码
String dataAfterBase64Encode = Base64Util.encode(data, "UTF-8");
if (logger.isDebugEnabled()) {
logger.debug("after base64 encode data is [" + dataAfterBase64Encode + "] , before base64 encode data is [" + data + "] !");
}
// 4、对base64编码后的消息做DES加密
String dataAfterDESEncode = DesUtil.encryptToHex(dataAfterBase64Encode.getBytes("UTF-8"), secretKey);
if (logger.isDebugEnabled()) {
logger.debug("after des encrypt data is [" + dataAfterDESEncode + "] , secretKey is [" + secretKey + "] !");
}
// 5、将消息摘要与加密后的数据拼成整串 格式:摘要签名&加密后的数据
String finalData = digest + "&" + dataAfterDESEncode;
if (logger.isDebugEnabled()) {
logger.debug("caller post ids encrypted data is [" + finalData + "] , digest is [" + digest + "] , dataAfterDESEncode is ["
+ dataAfterDESEncode + "] !");
}
return finalData;
}
}

247
src/main/java/com/trs/ids/oauth/IDSAPICall.java

@ -0,0 +1,247 @@
package com.trs.ids.oauth;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.log4j.Logger;
import com.trs.idm.util.Base64Util;
import com.trs.idm.util.StringHelper;
public class IDSAPICall {
/**
* 接口服务地址 需要到具体到接口地址
*/
private String serviceUrl;
private String secretKey;
private String digestAlgorithm;
private String appName;
private String responseType;
private static final Logger logger = Logger.getLogger(IDSAPICall.class);
/**
* 错误提示消息摘要不合法
*/
private static final String ERRPR_DIGEST_ILLEGALITY = "error.digest.illegality";
/**
* 错误提示IDS响应格式不合法
*/
private static final String ERROR_RESPONSE_ILLEGALITY = "error.response.illegality";
/**
* 错误提示调用IDS接口发送异常(网络异常等)
*/
private static final String ERROR_CALLING_EXCEPTION = "error.calling.exception";
/**
* 构造函数
*
* @param serviceUrl
* 接口服务url
* @param secretKey
* 密钥
* @param digestAlgorithm
* 签名算法 MD5SHA等注意区分大小写
*/
public IDSAPICall(String serviceUrl, String appName, String secretKey, String digestAlgorithm) {
this.serviceUrl = serviceUrl;
this.secretKey = secretKey;
this.appName = appName;
this.digestAlgorithm = digestAlgorithm;
this.responseType = "json";
}
public String Call(String method, String data) throws Exception {
PostMethod methodPost = null;
if (isHttpSSOAPI(serviceUrl)) {
methodPost = new PostMethod(serviceUrl + "&serviceName=" + method);
methodPost.addParameter("coAppName", appName);
} else {
methodPost = new PostMethod(serviceUrl + "&method=" + method);
methodPost.addParameter("appName", appName);
}
methodPost.addParameter("type", responseType);
String encryptedData = DesUtil.encrypt(data, digestAlgorithm, secretKey);
methodPost.addParameter("data", encryptedData);
HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(methodPost);
} catch (Exception e) {
logger.error("calling ids api has exception !", e);
throw new Exception(ERROR_CALLING_EXCEPTION, e);
}
String responsePost = new String(methodPost.getResponseBody(), "UTF-8");
String[] digestAndResult = StringHelper.split(responsePost, "&");
if (digestAndResult.length != 2) {
logger.error("response from ids format is illegality ! after split is digestAndResult [" + digestAndResult + "]");
throw new Exception(ERROR_RESPONSE_ILLEGALITY);
}
String digestOfServer = digestAndResult[0];
String result = digestAndResult[1];
// 8、对响应结果进行解密
String afterDESResult = DesUtil.decrypt(result, secretKey);
if (logger.isDebugEnabled()) {
logger.debug("after des decrypt response is [" + afterDESResult + "] , decrypt secretKey is [" + secretKey + "] !");
}
// 9、对解密后的结果做base64反解
String plaintextResponse = Base64Util.decode(afterDESResult, "UTF-8");
if (logger.isDebugEnabled()) {
logger.debug("after base64 decode plaintext response is [" + plaintextResponse + "] , before base64 decode response is ["
+ afterDESResult + "] !");
}
// 10、本地生成消息摘要与IDS返回的摘要对比,如果不相等则说明数据在传输过程中被篡改过
MessageDigest sd = MessageDigest.getInstance(digestAlgorithm);
sd.update(plaintextResponse.getBytes("UTF-8"));
String digestOfAgent = StringHelper.toString(sd.digest());
if (false == digestOfAgent.equals(digestOfServer)) {
logger.error("response from ids digest [" + digestOfServer + "] not eq client create digest [" + digestOfAgent + "] !");
throw new Exception(ERRPR_DIGEST_ILLEGALITY);
}
return plaintextResponse;
}
public String Call2Json(String method, String data) throws Exception {
this.responseType = "json";
return Call(method, data);
}
public String Call2Xml(String method, String data) throws Exception {
this.responseType = "xml";
return Call(method, data);
}
public String Call(String method, Map<String, String> params) throws Exception {
String data = "";
if (null != params && !params.isEmpty()) {
for (Iterator<Entry<String, String>> iterator = params.entrySet().iterator(); iterator.hasNext();) {
Entry<String, String> v = (Entry<String, String>) iterator.next();
if (isEmpty(data)) {
data = v.getKey() + "=" + v.getValue();
} else {
data += "&" + v.getKey() + "=" + v.getValue();
}
}
}
return Call(method, data);
}
public String Call2Json(String method, Map<String, String> params) throws Exception {
this.responseType = "json";
return Call(method, params);
}
public String Call2Xml(String method, Map<String, String> params) throws Exception {
this.responseType = "xml";
return Call(method, params);
}
public static boolean isEmpty(String str) {
return (str == null || str.trim().length() == 0) ? true : false;
}
private static boolean isHttpSSOAPI(String serviceUrl) {
return serviceUrl.contains("idsServiceType=httpssoservice");
}
public static String accessToken(String serviceUrl, String clientId, String clientSecret, String code, String callbackUrl) throws Exception {
String accessTokenUrl = serviceUrl
+ "&method=accessToken"
+ "&client_id=" + clientId
+ "&client_secret=" + clientSecret
+ "&grant_type=authorization_code"
+ "&code=" + code
+ "&redirect_uri=" + URLEncoder.encode(callbackUrl, "UTF-8");
return call(accessTokenUrl, "GET");
}
public static String userInfo(String serviceUrl, String accessToken, String clientId, String clientSecret) throws Exception {
String userInfoUrl = serviceUrl
+ "&method=getUser"
+ "&token_type=bearer"
+ "&access_token=" + accessToken
+ "&client_id=" + clientId
+ "&client_secret=" + clientSecret;
return call(userInfoUrl, "GET");
}
public static String call(String requestUrl, String requestMethod) throws Exception {
return call(requestUrl, requestMethod, null);
}
public static String call(String requestUrl, String requestMethod, String outputStr) throws Exception {
String content = "";
StringBuffer buffer = new StringBuffer();
try {
URL url = new URL(requestUrl);
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod(requestMethod);
if ("GET".equalsIgnoreCase(requestMethod))
httpUrlConn.connect();
// 当有数据需要提交时
if (null != outputStr) {
OutputStream outputStream = httpUrlConn.getOutputStream();
// 注意编码格式,防止中文乱码
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
int contentLength = 0;
// 将返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
while ((str = bufferedReader.readLine()) != null) {
int flag = str.indexOf("Content-Length");
if (flag != -1) {
contentLength = Integer.parseInt((str.split(":")[1]).trim());
}
buffer.append(str);
}
if (contentLength > 0) {
content = buffer.substring(buffer.length() - contentLength);
} else {
content = buffer.toString();
}
bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();
} catch (Exception e) {
e.printStackTrace();
throw new Exception("[call{" + requestUrl + "}]出错");
}
return content;
}
}

52
src/main/java/com/trs/ids/oauth/Test.java

@ -0,0 +1,52 @@
/**
* Power By percyLee
* Copyright: Copyright (c) 2015 percyLee<BR>
*
* @author percyLee (Email:shininglxj@163.com)
* @version 1.0 2015-1-14
*/
package com.trs.ids.oauth;
import java.util.HashMap;
import java.util.Map;
import com.trs.idm.util.Base64Util;
/**
* Title: <BR>
* Description: <BR>
* TODO <BR>
*/
public class Test {
public static final String IDS_URL = "http://gwt.haicang.gov.cn/ids/service?idsServiceType=remoteapi";
/**
* 加密密钥
*/
public static final String SECRETKEY = "HCFR@123!6";
/**
* 消息摘要加密算法
*/
public static final String DIGESTALGORITHM = "MD5";
/**
* 协作应用名
*/
public static final String APP_NAME = "HCFRKSHZHFXPT";
public static void main(String[] args) throws Exception {
IDSAPICall idsapiCall = new IDSAPICall(IDS_URL,APP_NAME,SECRETKEY,DIGESTALGORITHM);
String method="qPagedUsersByFilter";
String data ="userName=admin&qUserNames=gwtest&startPos=0&pageSize=1000";
data ="userName=admin&startPos=0&pageSize=100000&searchFilters=actived:=:true";
//data ="userName=admin&qUserNames=督察组&startPos=0&pageSize=10&searchFilters=actived:=:true";
method ="searchGroups";
data ="userName=admin";
//method ="searchUserGroupsMapping";
//data ="";
String aa = idsapiCall.Call(method,data);
System.out.println(aa);
}
}
Loading…
Cancel
Save