LAPTOP-SB56SG4Q\86185
3 years ago
7 changed files with 243 additions and 1 deletions
Binary file not shown.
@ -1,3 +1,6 @@
|
||||
# open-JSD-7942 |
||||
|
||||
JSD-7942 开源任务材料 |
||||
JSD-7942 开源任务材料\ |
||||
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 |
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<plugin> |
||||
<id>com.fr.plugin.ctfo.sso</id> |
||||
<name><![CDATA[oauth2单点登录]]></name> |
||||
<active>yes</active> |
||||
<version>1.2</version> |
||||
<env-version>10.0</env-version> |
||||
<jartime>2018-07-31</jartime> |
||||
<vendor>fr.open</vendor> |
||||
<description><![CDATA[oauth2单点登录]]></description> |
||||
<change-notes><![CDATA[]]></change-notes> |
||||
<extra-decision> |
||||
<GlobalRequestFilterProvider class="com.fr.plugin.ctfo.sso.Oauth2Filter"/> |
||||
</extra-decision> |
||||
<function-recorder class="com.fr.plugin.ctfo.sso.Oauth2Filter"/> |
||||
</plugin> |
@ -0,0 +1,9 @@
|
||||
|
||||
此次完成功能如下 |
||||
a、单点登录 |
||||
|
||||
1、将压缩文件解压后的xplatform.properties配置文件拷贝至 %部署路径%/WEB-INF/resources, 并修改对应配置 |
||||
|
||||
2、安装本插件,插件安装见连接http://help.finereport.com/doc-view-2198.html |
||||
|
||||
3、进入系统测试单点登录,访问地址为http://ip:port/webroot/decision |
@ -0,0 +1,204 @@
|
||||
package com.fr.plugin.ctfo.sso; |
||||
|
||||
import com.fr.base.PropertiesUtils; |
||||
import com.fr.common.util.Assert; |
||||
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.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.general.http.HttpToolbox; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.transform.FunctionRecorder; |
||||
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.io.IOException; |
||||
import java.net.URLEncoder; |
||||
import java.time.Instant; |
||||
import java.util.Collections; |
||||
import java.util.Properties; |
||||
import java.util.stream.Stream; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @since 2021/5/25 |
||||
*/ |
||||
@FunctionRecorder |
||||
public class Oauth2Filter extends AbstractGlobalRequestFilterProvider { |
||||
|
||||
private static final String[] NOT_FILTER = { |
||||
"/decision/file", |
||||
"/decision/resources", |
||||
"/system", |
||||
"/materials.min.js.map", |
||||
"/remote", |
||||
"/login", |
||||
"/login/config", |
||||
}; |
||||
|
||||
private final String apiAuthorize; |
||||
|
||||
private final String apiAppKey; |
||||
|
||||
private final String apiAppSecret; |
||||
|
||||
private final String apiGetToken; |
||||
|
||||
private final String apiGetUser; |
||||
|
||||
public Oauth2Filter() { |
||||
Properties props = PropertiesUtils.getProperties("xplatform"); |
||||
apiAuthorize = getValue(props, "api.authorize"); |
||||
apiAppKey = getValue(props, "api.app-key"); |
||||
apiAppSecret = getValue(props, "api.app-secret"); |
||||
apiGetToken = getValue(props, "api.get-token"); |
||||
apiGetUser = getValue(props, "api.get-user"); |
||||
} |
||||
|
||||
private String getValue(Properties props, String key) { |
||||
String value = props.getProperty(key); |
||||
Assert.hasText(value, "配置项[" + key + "]不能为空"); |
||||
return value; |
||||
} |
||||
|
||||
@Override |
||||
public String filterName() { |
||||
return "ctfoOauth2"; |
||||
} |
||||
|
||||
@Override |
||||
public String[] urlPatterns() { |
||||
return new String[]{"/*"}; |
||||
} |
||||
|
||||
@Override |
||||
public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { |
||||
final String url = request.getRequestURL().toString(); |
||||
FineLoggerFactory.getLogger().info("sso >> URL of this request => {}", url); |
||||
try { |
||||
if (isLogin(request) || Stream.of(NOT_FILTER).anyMatch(url::contains)) { |
||||
FineLoggerFactory.getLogger().info("sso >> 已登录或默认可放行的请求地址"); |
||||
chain.doFilter(request, response); |
||||
return; |
||||
} |
||||
|
||||
String code = request.getParameter("code"); |
||||
if (StringUtils.isBlank(code)) { |
||||
FineLoggerFactory.getLogger().info("sso >> Parameter['code'] 值为空, 跳转到登录页"); |
||||
toAuthorize(request, response); |
||||
return; |
||||
} |
||||
|
||||
FineLoggerFactory.getLogger().info("sso >> Parameter['code'] => [{}]", code); |
||||
String token; |
||||
try { |
||||
token = getAccessToken(request, code); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error("sso >> 获取access token失败", e); |
||||
chain.doFilter(request, response); |
||||
return; |
||||
} |
||||
|
||||
FineLoggerFactory.getLogger().info("sso >> AccessToken => [{}]", token); |
||||
String username; |
||||
try { |
||||
username = getUsername(token); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error("sso >> 获取用户名失败", e); |
||||
chain.doFilter(request, response); |
||||
return; |
||||
} |
||||
|
||||
FineLoggerFactory.getLogger().info("sso >> username => [{}]", token); |
||||
login(username, request, response); |
||||
chain.doFilter(request, response); |
||||
} catch (Exception e) { |
||||
throw new RuntimeException(e); |
||||
} |
||||
} |
||||
|
||||
private void toAuthorize(HttpServletRequest request, HttpServletResponse response) throws IOException { |
||||
String urlPattern = "%s?response_type=code&client_id=%s&redirect_uri=%s&oauth_timestamp=%s"; |
||||
String rURI = request.getRequestURL().toString(); |
||||
// if (request.getQueryString() != null) {
|
||||
// rURI += "?" + request.getQueryString();
|
||||
// }
|
||||
rURI = URLEncoder.encode(rURI, "utf-8"); |
||||
String url = String.format(urlPattern, apiAuthorize, apiAppKey, rURI, Instant.now().toEpochMilli()); |
||||
FineLoggerFactory.getLogger().info("sso >> 登录认证地址 => [{}]", url); |
||||
response.sendRedirect(url); |
||||
} |
||||
|
||||
private String getAccessToken(HttpServletRequest request, String code) throws IOException, IllegalAccessException { |
||||
String api = "%s?grant_type=authorization_code&oauth_timestamp=%s&client_id=%s&client_secret=%s&code=%s&redirect_uri=%s"; |
||||
String rURI = request.getRequestURL().toString(); |
||||
rURI = URLEncoder.encode(rURI, "utf-8"); |
||||
// if (request.getQueryString() != null) {
|
||||
// rURI += "?" + request.getQueryString();
|
||||
// }
|
||||
api = String.format(api, apiGetToken, Instant.now().toEpochMilli(), apiAppKey, apiAppSecret, code, rURI); |
||||
FineLoggerFactory.getLogger().info("sso >> CODE换取AccessToken的接口地址 => [{}]", api); |
||||
String response = HttpToolbox.post(api, Collections.emptyMap()); |
||||
FineLoggerFactory.getLogger().info("sso >> CODE换取AccessToken的接口返回内容 => [{}]", response); |
||||
JSONObject res = new JSONObject(response); |
||||
if (res.has("access_token") && StringUtils.isNotBlank(res.getString("access_token"))) { |
||||
return res.getString("access_token"); |
||||
} |
||||
throw new IllegalAccessException(); |
||||
} |
||||
|
||||
private String getUsername(String token) throws IOException, IllegalAccessException { |
||||
String api = String.format("%s?access_token=%s", apiGetUser, token); |
||||
FineLoggerFactory.getLogger().info("sso >> 获取用户信息接口地址 => [{}]", api); |
||||
String response = HttpToolbox.get(api); |
||||
FineLoggerFactory.getLogger().info("sso >> 获取用户信息接口地址返回内容 => [{}]", response); |
||||
JSONObject res = new JSONObject(response); |
||||
if (res.has("attributes")) { |
||||
JSONObject attrs = res.getJSONObject("attributes"); |
||||
if (attrs.has("account_no") && StringUtils.isNotBlank(attrs.getString("account_no"))) { |
||||
return attrs.getString("account_no"); |
||||
} |
||||
} |
||||
throw new IllegalAccessException(); |
||||
} |
||||
|
||||
private void login(String username, HttpServletRequest request, HttpServletResponse response) { |
||||
try { |
||||
User user = UserService.getInstance().getUserByUserName(username); |
||||
if (user == null) { |
||||
FineLoggerFactory.getLogger().error("sso >> User \"{}\" does not exist", username); |
||||
return; |
||||
} |
||||
FineLoggerFactory.getLogger().info("sso >> Getted user: {}", user); |
||||
String token = LoginService.getInstance().login(request, response, username); |
||||
FineLoggerFactory.getLogger().info("sso >> Getted login token: {}", token); |
||||
request.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token); |
||||
FineLoggerFactory.getLogger().info("sso >> User[{}] login successfully", username); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error("sso >> Failed to login with[" + username + "]", e); |
||||
} |
||||
} |
||||
|
||||
private boolean isLogin(HttpServletRequest request) { |
||||
String oldToken = TokenResource.COOKIE.getToken(request); |
||||
return oldToken != null && checkTokenValid(request, (String) oldToken); |
||||
} |
||||
|
||||
private 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; |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
api.app-key=1238912731982 |
||||
api.app-secret=1293102832190380 |
||||
api.authorize=http://114.242.227.113:10000/login/esc-sso/oauth2.0/authorize |
||||
api.get-token=http://114.242.227.113:10000/login/esc-sso/oauth2.0/accessToken |
||||
api.get-user=http://114.242.227.113:10000/login/esc-sso/oauth2.0/profile |
Loading…
Reference in new issue