Browse Source

提交开源代码

10.0
LAPTOP-SB56SG4Q\86185 3 years ago
parent
commit
40ec74d788
  1. BIN
      JSD-7639-5860-需求文档V1.docx
  2. 4
      README.md
  3. 17
      plugin.xml
  4. 64
      src/main/java/com/fr/plugin/jsd3998/sso/DesECBUtil.java
  5. 113
      src/main/java/com/fr/plugin/jsd3998/sso/H5SsoHandler.java
  6. 95
      src/main/java/com/fr/plugin/jsd3998/sso/SsoHttpHandler.java
  7. 20
      src/main/java/com/fr/plugin/jsd3998/sso/SsoRequestHandlerBridge.java
  8. 19
      src/main/java/com/fr/plugin/jsd3998/sso/SsoRequestURLAliasBridge.java
  9. 2
      sso.properties
  10. 13
      使用说明.txt

BIN
JSD-7639-5860-需求文档V1.docx

Binary file not shown.

4
README.md

@ -1,3 +1,5 @@
# open-JSD-7639
JSD-7639、JSD-5860 开源任务代码
JSD-7639、JSD-5860 开源任务代码\
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
仅作为开发者学习参考使用!禁止用于任何商业用途!

17
plugin.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.jsd3998.sso</id>
<name><![CDATA[移动端h5单点登录需求]]></name>
<active>yes</active>
<version>1.9</version>
<env-version>10.0</env-version>
<jartime>2018-07-31</jartime>
<vendor>fr.open</vendor>
<description><![CDATA[移动端h5单点登录需求]]></description>
<change-notes><![CDATA[]]></change-notes>
<extra-decision>
<HttpHandlerProvider class="com.fr.plugin.jsd3998.sso.SsoRequestHandlerBridge"/>
<URLAliasProvider class="com.fr.plugin.jsd3998.sso.SsoRequestURLAliasBridge" />
</extra-decision>
<function-recorder class="com.fr.plugin.jsd3998.sso.SsoRequestHandlerBridge"/>
</plugin>

64
src/main/java/com/fr/plugin/jsd3998/sso/DesECBUtil.java

@ -0,0 +1,64 @@
package com.fr.plugin.jsd3998.sso;
import com.fr.third.org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
/**
* @author Holger
* @date 2019/1/18
*/
public class DesECBUtil {
/**
* 加密数据
*
* @param encryptString
* @param encryptKey
* @return
* @throws Exception
*/
public static String encryptDES(String encryptString, String encryptKey) throws Exception {
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(getKey(encryptKey), "DES"));
byte[] encryptedData = cipher.doFinal(encryptString.getBytes("gb2312"));
return Base64.encodeBase64String(encryptedData);
}
/**
* key 不足8位补位
*
* @param
*/
public static byte[] getKey(String keyRule) {
Key key = null;
byte[] keyByte = keyRule.getBytes();
// 创建一个空的八位数组,默认情况下为0
byte[] byteTemp = new byte[8];
// 将用户指定的规则转换成八位数组
for (int i = 0; i < byteTemp.length && i < keyByte.length; i++) {
byteTemp[i] = keyByte[i];
}
key = new SecretKeySpec(byteTemp, "DES");
return key.getEncoded();
}
/***
* 解密数据
* @param decryptString
* @param decryptKey
* @return
* @throws Exception
*/
public static String decryptDES(String decryptString, String decryptKey) throws Exception {
byte[] sourceBytes = Base64.decodeBase64(decryptString);
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(getKey(decryptKey), "DES"));
byte[] decoded = cipher.doFinal(sourceBytes);
return new String(decoded, "UTF-8");
}
}

113
src/main/java/com/fr/plugin/jsd3998/sso/H5SsoHandler.java

@ -0,0 +1,113 @@
package com.fr.plugin.jsd3998.sso;
import com.fr.base.PropertiesUtils;
import com.fr.decision.authority.data.User;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.third.org.apache.commons.lang3.math.NumberUtils;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Calendar;
import java.util.Properties;
// @EnableMetrics
public class H5SsoHandler extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.GET;
}
@Override
public String getPath() {
return "/h5/callback";
}
@Override
public boolean isPublic() {
return true;
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
Properties props = PropertiesUtils.getProperties("sso");
String encryptKey = props.getProperty("encrypt.key");
Long ticketTimeoutInSeconds = NumberUtils.createLong(props.getProperty("ticket.timeoutInSeconds", "300"));
String ticket = request.getParameter("ticket");
FineLoggerFactory.getLogger().info("获取到的ticket值为[{}]", ticket);
if (StringUtils.isNotBlank(ticket)) {
ticket = DesECBUtil.decryptDES(ticket, encryptKey);
FineLoggerFactory.getLogger().info("解密后的ticket值为[{}]", ticket);
String[] tickets = ticket.split("\\+");
String username = tickets[0];
FineLoggerFactory.getLogger().info("获取到username为[{}]", username);
Long ticketTime = NumberUtils.createLong(tickets[1]);
Long nowTime = Calendar.getInstance().getTimeInMillis();
JSONObject res = new JSONObject();
if ((nowTime - ticketTime) > ticketTimeoutInSeconds * 1000) {
FineLoggerFactory.getLogger().info("ticket[{}]已过期", ticket);
request.getRequestDispatcher("/login.html").forward(request, response);
res.put("res", "ticket已过期");
WebUtils.printAsJSON(response, res);
return;
}
if (loginFromToken(request, response, username)) {
request.getRequestDispatcher( "/decision/url/mobile").forward(request, response);
} else {
res.put("res", "fail");
WebUtils.printAsJSON(response, res);
}
} else {
FineLoggerFactory.getLogger().info("未找到用户名,跳转到登录页面");
request.getRequestDispatcher("/login.html").forward(request, response);
}
}
protected boolean loginFromToken(HttpServletRequest req, HttpServletResponse res, String username) throws Exception {
try {
if (com.fr.stable.StringUtils.isNotEmpty(username)) {
FineLoggerFactory.getLogger().info("current username:" + username);
User user = UserService.getInstance().getUserByUserName(username);
FineLoggerFactory.getLogger().info("get user:" + user);
if (user == null) {
throw new UserNotExistException();
}
String token = LoginService.getInstance().login(req, res, username);
FineLoggerFactory.getLogger().info("get login token:" + token);
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token);
FineLoggerFactory.getLogger().info("username:" + username + " login success");
return true;
} else {
FineLoggerFactory.getLogger().warn("username is null!");
return false;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
// public static void main(String... args) throws Exception {
// String ticket = URLDecoder.decode("7O%2Fyt%2FGeLqg8fxjY4Lm8%2F31FkSgLZh3a", "utf-8");
// System.out.println(ticket);
// ticket = DesECBUtil.decryptDES(ticket, "1111111111111111111");
// System.out.println(ticket);
// String[] tickets = ticket.split("\\+");
// String username = tickets[0];
// System.out.println(username);
//
//
// String t = "1+" + Calendar.getInstance().getTimeInMillis();
// System.out.println(URLEncoder.encode(DesECBUtil.encryptDES(t, "1111111111111111111"), "utf-8"));
// }
}

95
src/main/java/com/fr/plugin/jsd3998/sso/SsoHttpHandler.java

@ -0,0 +1,95 @@
package com.fr.plugin.jsd3998.sso;
import com.fr.decision.authority.data.User;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.decision.webservice.Response;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.stable.StringUtils;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author luomiao
* @since 2020/08/28
*/
@EnableMetrics
public class SsoHttpHandler extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.GET;
}
@Override
public String getPath() {
return "/sso";
}
@Override
public boolean isPublic() {
return true;
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
String src = request.getParameter("src");
String username = request.getParameter("username");
if ("sys".equals(src) && StringUtils.isNotBlank(username)) {
JSONObject res = new JSONObject();
response.setContentType("application/json;charset=UTF-8");
if (loginFromToken(request, response, username)) {
res.put("res", "success");
WebUtils.printAsJSON(response, res);
} else {
res.put("res", "fail");
WebUtils.printAsJSON(response, res);
}
} else if (!"sys".equals(src)) {
FineLoggerFactory.getLogger().info("未找到用户名,跳转到登录页面");
request.getRequestDispatcher("/login.html").forward(request, response);
}
}
protected boolean loginFromToken(HttpServletRequest req, HttpServletResponse res, String username) throws Exception {
try {
if (com.fr.stable.StringUtils.isNotEmpty(username)) {
FineLoggerFactory.getLogger().info("current username:" + username);
User user = UserService.getInstance().getUserByUserName(username);
FineLoggerFactory.getLogger().info("get user:" + user);
if (user == null) {
throw new UserNotExistException();
}
String token = LoginService.getInstance().login(req, res, username);
FineLoggerFactory.getLogger().info("get login token:" + token);
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token);
FineLoggerFactory.getLogger().info("username:" + username + " login success");
return true;
} else {
FineLoggerFactory.getLogger().warn("username is null!");
return false;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
protected void sendError(HttpServletResponse response, String errorCode) {
Response res = Response.error(errorCode, errorCode);
try {
response.setContentType("application/json;charset=UTF-8");
WebUtils.printAsJSON(response, JSONObject.mapFrom(res));
} catch (Exception e) {
FineLoggerFactory.getLogger().error("输出响应错误失败", e);
}
}
}

20
src/main/java/com/fr/plugin/jsd3998/sso/SsoRequestHandlerBridge.java

@ -0,0 +1,20 @@
package com.fr.plugin.jsd3998.sso;
import com.fr.decision.fun.HttpHandler;
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider;
import com.fr.plugin.transform.FunctionRecorder;
/**
* @author luomiao
* @since 2020/08/28
*/
@FunctionRecorder
public class SsoRequestHandlerBridge extends AbstractHttpHandlerProvider {
@Override
public HttpHandler[] registerHandlers() {
return new HttpHandler[]{
new SsoHttpHandler(),
new H5SsoHandler()
};
}
}

19
src/main/java/com/fr/plugin/jsd3998/sso/SsoRequestURLAliasBridge.java

@ -0,0 +1,19 @@
package com.fr.plugin.jsd3998.sso;
import com.fr.decision.fun.impl.AbstractURLAliasProvider;
import com.fr.decision.webservice.url.alias.URLAlias;
import com.fr.decision.webservice.url.alias.URLAliasFactory;
/**
* @author luomiao
* @since 2020/08/28
*/
public class SsoRequestURLAliasBridge extends AbstractURLAliasProvider {
@Override
public URLAlias[] registerAlias() {
return new URLAlias[]{
URLAliasFactory.createPluginAlias("/sso", "/sso", true),
URLAliasFactory.createPluginAlias("/h5/callback", "/h5/callback", true)
};
}
}

2
sso.properties

@ -0,0 +1,2 @@
encrypt.key=1111111111111111111
ticket.timeoutInSeconds=300

13
使用说明.txt

@ -0,0 +1,13 @@
此次完成功能如下
a、单点登录
1、安装本插件,插件安装见连接http://help.finereport.com/doc-view-2198.html
2、将sso.properties件复制到 %tomcat_home%/webapps/webroot/WEB-INF/classes下, 并修改文件中的ticket加密密钥和时间戳超时时间
2、进入系统测试单点登录,访问地址为http://ip:port/webroot/decision/url/doH5Login,示例为本地地址http://localhost:8075/webroot/decision/url/h5/callback?ticket=XXXX 其中ticket的格式应为 用户名_时间戳
5、登录成功后会跳转到移动html5端首页。
如页面打印出“单点登录失败”可能原因是获取ticket失败或解析ticket中的用户名在系统中不存在
Loading…
Cancel
Save