LAPTOP-SB56SG4Q\86185
3 years ago
6 changed files with 243 additions and 1 deletions
@ -1,3 +1,6 @@ |
|||||||
# open-JSD-7492 |
# open-JSD-7492 |
||||||
|
|
||||||
JSD-9492 开源任务代码 |
JSD-9492 开源任务代码\ |
||||||
|
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||||
|
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||||
|
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系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,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 |
@ -0,0 +1,5 @@ |
|||||||
|
api.app-key=xxxxx |
||||||
|
api.app-secret=xxxxx |
||||||
|
api.authorize=http://xxxxx/oauth2.0/authorize |
||||||
|
api.get-token=http://xxxxx/oauth2.0/accessToken |
||||||
|
api.get-user=http://xxxxx/oauth2.0/profile |
Loading…
Reference in new issue