Browse Source

提交开源任务材料

10.0
LAPTOP-SB56SG4Q\86185 4 years ago
parent
commit
7fc6c5988e
  1. BIN
      JSD-8277 -需求确认书V1.1.docx
  2. 5
      README.md
  3. 17
      plugin.xml
  4. 6
      readme.txt
  5. 90
      src/main/java/com/fr/plugin/xxxx/sso/CommonUtils.java
  6. 41
      src/main/java/com/fr/plugin/xxxx/sso/CustomLogInOutEventProvider.java
  7. 165
      src/main/java/com/fr/plugin/xxxx/sso/SsoFilter.java
  8. 23
      src/main/resources/xxxx.properties
  9. 23
      xxxx.properties

BIN
JSD-8277 -需求确认书V1.1.docx

Binary file not shown.

5
README.md

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

17
plugin.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.xxxx.sso</id>
<name><![CDATA[xxxx单点登录]]></name>
<active>yes</active>
<version>1.1</version>
<env-version>10.0</env-version>
<jartime>2018-07-31</jartime>
<vendor>fr.open</vendor>
<description><![CDATA[xxxx单点登录]]></description>
<change-notes><![CDATA[]]></change-notes>
<extra-decision>
<GlobalRequestFilterProvider class="com.fr.plugin.xxxx.sso.SsoFilter"/>
<LogInOutEventProvider class="com.fr.plugin.xxxx.sso.CustomLogInOutEventProvider"/>
</extra-decision>
<function-recorder class="com.fr.plugin.xxxx.sso.SsoFilter"/>
</plugin>

6
readme.txt

@ -0,0 +1,6 @@
此次完成功能如下
a、单点登录
1、将压缩文件解压后的tengyuejz.properties配置文件拷贝至 %部署路径%/WEB-INF/resources
2、安装本插件,插件安装见连接http://help.finereport.com/doc-view-2198.html
3、进入系统测试单点登录,访问地址为http://ip:port/webroot/decision

90
src/main/java/com/fr/plugin/xxxx/sso/CommonUtils.java

@ -0,0 +1,90 @@
package com.fr.plugin.xxxx.sso;
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.v10.login.LoginService;
import com.fr.decision.webservice.v10.login.TokenResource;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.stable.web.Device;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Properties;
/**
* @author fr.open
* @since 2021/7/12
*/
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) {
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) {
throw new RuntimeException(e);
}
}
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, username);
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 +"\"登录失败");
}
}
}

41
src/main/java/com/fr/plugin/xxxx/sso/CustomLogInOutEventProvider.java

@ -0,0 +1,41 @@
package com.fr.plugin.xxxx.sso;
import com.fr.decision.fun.impl.AbstractLogInOutEventProvider;
import com.fr.decision.webservice.login.LogInOutResultInfo;
import com.fr.general.PropertiesUtils;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Properties;
/**
* @Author fr.open
* @since 2021/7/12
**/
public class CustomLogInOutEventProvider extends AbstractLogInOutEventProvider {
private final String apiClientId;
private final String logoutURL;
private final String logoutRedirectURL;
public CustomLogInOutEventProvider() {
Properties props = PropertiesUtils.getProperties("xxxx");
this.apiClientId = CommonUtils.getProperty(props, "api.client-id", false);
this.logoutURL = CommonUtils.getProperty(props, "api.logout", false);
this.logoutRedirectURL = CommonUtils.getProperty(props, "api.logout-redirct-url", "http://www.baidu.com", true);
}
@Override
public String logoutAction(LogInOutResultInfo result) {
try {
return String.format("%s?redirctToUrl=%s&redirectToLogin=true&entityId=%s",
logoutURL,
URLEncoder.encode(logoutRedirectURL, "utf-8"),
apiClientId);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
}

165
src/main/java/com/fr/plugin/xxxx/sso/SsoFilter.java

@ -0,0 +1,165 @@
package com.fr.plugin.tengyuejz.sso;
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider;
import com.fr.general.PropertiesUtils;
import com.fr.general.http.HttpToolbox;
import com.fr.json.JSONArray;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.transform.FunctionRecorder;
import com.fr.stable.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Stream;
import static com.fr.plugin.tengyuejz.sso.CommonUtils.*;
/**
* @author fr.open
* @since 2021/7/12
*/
@FunctionRecorder
public class SsoFilter extends AbstractGlobalRequestFilterProvider {
private static String[] NOT_FILTER = {
"/decision/file",
"/decision/resources",
"/system",
"/materials.min.js.map",
"/remote",
"/login",
"/login/config"
};
private final String apiClientId;
private final String apiClientSecret;
private final String apiAuthorize;
private final String apiGetToken;
private final String apiGetUser;
private final String errorOutput;
private final String systemName;
private final String bipName;
private final String telephone;
public SsoFilter() {
Properties props = PropertiesUtils.getProperties("xxxx");
this.apiClientId = getProperty(props, "api.client-id", false);
this.apiClientSecret = getProperty(props, "api.client-secret", false);
this.apiAuthorize = getProperty(props, "api.authorize", false);
this.apiGetToken = getProperty(props, "api.get-token", false);
this.apiGetUser = getProperty(props, "api.get-user", false);
this.errorOutput = getProperty(props, "api.error-output", false);
this.systemName = getProperty(props, "info.system-name", false);
this.bipName = getProperty(props, "info.bip-name", false);
this.telephone = getProperty(props, "info.telephone", false);
}
@Override
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
if (isAccept(request)) {
next(request, response, chain);
return;
}
try {
String code = request.getParameter("code");
if (StringUtils.isBlank(code)) {
String redirectURL = URLEncoder.encode(request.getRequestURL().toString(), "utf-8");
String authorizeURL = String.format("%s?client_id=%s&redirect_uri=%s&response_type=code", apiAuthorize, apiClientId, redirectURL);
FineLoggerFactory.getLogger().info("没有在参数中找到code值,跳转到认证登录地址, 认证地址为\"{}\"", authorizeURL);
response.sendRedirect(authorizeURL);
return;
}
login(getUsername(getToken(code)), request, response);
next(request, response, chain);
} catch (Exception e) {
FineLoggerFactory.getLogger().error("单点登录处理失败.", e);
setError(response, e.getMessage());
}
}
@Override
public String filterName() {
return "sso";
}
@Override
public String[] urlPatterns() {
return new String[]{"/*"};
}
private boolean isAccept(HttpServletRequest request) {
String url = request.getRequestURL().toString();
return isLogin(request) || Stream.of(NOT_FILTER).anyMatch(url::contains);
}
private String getToken(String code) throws IOException {
Map<String, Object> params = new HashMap<>();
params.put("client_id", apiClientId);
params.put("client_secret", apiClientSecret);
params.put("code", code);
params.put("grant_type", "authorization_code");
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/x-www-form-urlencoded");
String res = HttpToolbox.post(apiGetToken, params, headers);
FineLoggerFactory.getLogger().info("获取Token接口返回内容: \"{}\"", res);
JSONObject body = new JSONObject(res);
if (body.has("access_token")) {
String token = body.getString("access_token");
FineLoggerFactory.getLogger().info("获取到的token值为: \"{}\"", token);
return token;
}
throw new RuntimeException("获取token失败");
}
private String getUsername(String token) throws IOException {
String api = String.format("%s?access_token=%s&client_id=%s", apiGetUser, token, apiClientId);
FineLoggerFactory.getLogger().info("获取用户信息接口访问地址为: \"{}\"", api);
String res = HttpToolbox.get(api);
FineLoggerFactory.getLogger().info("获取用户信息接口返回内容: \"{}\"", res);
JSONObject body = new JSONObject(res);
if (body.has("spRoleList")) {
JSONArray roles = body.getJSONArray("spRoleList");
if (roles.size() > 0) {
String username = roles.getString(0);
FineLoggerFactory.getLogger().info("获取到的用户名为: \"{}\"", username);
return username;
} else {
throw new RuntimeException("系统未授权, 当前用户是\"" + body.getString("displayName") + "\"");
}
}
throw new RuntimeException("访问获取用户信息接口失败");
}
private void setError(HttpServletResponse res, String reason) {
try {
String URL = String.format(
"%s?systemName=%s&bipName=%s&telephone=%s&reason=%s",
errorOutput,
URLEncoder.encode(systemName, "utf-8"),
URLEncoder.encode(bipName, "utf-8"),
URLEncoder.encode(telephone, "utf-8"),
URLEncoder.encode(reason, "utf-8")
);
res.sendRedirect(URL);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}

23
src/main/resources/xxxx.properties

@ -0,0 +1,23 @@
# 统一认证平台认证登录地址
api.authorize=https://xxx:8443/idp/oauth2/authorize
# 获取access_token的接口地址
api.get-token=https://xxx:8443/idp/oauth2/getToken
# 获取用户信息的接口地址
api.get-user=https://xxx:8443/idp/oauth2/getUserInfo
# 注销登录的接口地址
api.logout=https://xxx:8443/idp/profile/SAML2/Redirect/GLO
# 注销登录后跳转的地址
api.logout-redirct-url=http://xxx
# 错误信息输出地址
api.error-output=https://xxx:8443/idp/themes/error/defpage-403.html
# 认证平台的client_id
api.client-id=xxx
# 认证平台的client_secret
api.client-secret=xxxx
# 系统名称
info.system-name=xxxx
# 运维人员
info.bip-name=xxxx
# 运维人员服务电话
info.telephone=12345678901

23
xxxx.properties

@ -0,0 +1,23 @@
# 统一认证平台认证登录地址
api.authorize=https://xxx:8443/idp/oauth2/authorize
# 获取access_token的接口地址
api.get-token=https://xxx:8443/idp/oauth2/getToken
# 获取用户信息的接口地址
api.get-user=https://xxx:8443/idp/oauth2/getUserInfo
# 注销登录的接口地址
api.logout=https://xxx:8443/idp/profile/SAML2/Redirect/GLO
# 注销登录后跳转的地址
api.logout-redirct-url=http://xxx
# 错误信息输出地址
api.error-output=https://xxx:8443/idp/themes/error/defpage-403.html
# 认证平台的client_id
api.client-id=xxx
# 认证平台的client_secret
api.client-secret=xxxx
# 系统名称
info.system-name=xxxx
# 运维人员
info.bip-name=xxxx
# 运维人员服务电话
info.telephone=12345678901
Loading…
Cancel
Save