Browse Source

提交开源任务材料

10.0
LAPTOP-SB56SG4Q\86185 3 years ago
parent
commit
46b3a5d007
  1. BIN
      JSD-7565需求确认书.docx
  2. 5
      README.md
  3. 18
      plugin.xml
  4. 64
      src/main/java/com/fr/plugin/nfsq/sso/DesECBUtil.java
  5. 479
      src/main/java/com/fr/plugin/nfsq/sso/HttpUtil.java
  6. 40
      src/main/java/com/fr/plugin/nfsq/sso/Params.java
  7. 537
      src/main/java/com/fr/plugin/nfsq/sso/SsoFilter.java
  8. 103
      src/main/java/com/fr/plugin/nfsq/sso/SsoHttpHandler.java
  9. 19
      src/main/java/com/fr/plugin/nfsq/sso/SsoRequestHandlerBridge.java
  10. 18
      src/main/java/com/fr/plugin/nfsq/sso/SsoRequestURLAliasBridge.java

BIN
JSD-7565需求确认书.docx

Binary file not shown.

5
README.md

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

18
plugin.xml

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.nfsq.sso</id>
<name><![CDATA[获取token]]></name>
<active>yes</active>
<version>1.19</version>
<env-version>10.0</env-version>
<jartime>2018-07-31</jartime>
<vendor>fr.open</vendor>
<description><![CDATA[获取token]]></description>
<change-notes><![CDATA[]]></change-notes>
<extra-decision>
<GlobalRequestFilterProvider class="com.fr.plugin.nfsq.sso.SsoFilter"/>
<HttpHandlerProvider class="com.fr.plugin.nfsq.sso.SsoRequestHandlerBridge"/>
<URLAliasProvider class="com.fr.plugin.nfsq.sso.SsoRequestURLAliasBridge" />
</extra-decision>
<function-recorder class="com.fr.plugin.nfsq.sso.SsoRequestHandlerBridge"/>
</plugin>

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

@ -0,0 +1,64 @@
package com.fr.plugin.nfsq.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 fr.open
* @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("UTF-8"));
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");
}
}

479
src/main/java/com/fr/plugin/nfsq/sso/HttpUtil.java

@ -0,0 +1,479 @@
package com.fr.plugin.nfsq.sso;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.stable.StringUtils;
import com.fr.third.org.apache.http.HttpResponse;
import com.fr.third.org.apache.http.HttpStatus;
import com.fr.third.org.apache.http.NameValuePair;
import com.fr.third.org.apache.http.client.HttpClient;
import com.fr.third.org.apache.http.client.entity.UrlEncodedFormEntity;
import com.fr.third.org.apache.http.client.methods.HttpPost;
import com.fr.third.org.apache.http.client.methods.HttpPut;
import com.fr.third.org.apache.http.config.Registry;
import com.fr.third.org.apache.http.config.RegistryBuilder;
import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import com.fr.third.org.apache.http.conn.ssl.SSLContexts;
import com.fr.third.org.apache.http.conn.ssl.TrustStrategy;
import com.fr.third.org.apache.http.entity.StringEntity;
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient;
import com.fr.third.org.apache.http.impl.client.HttpClientBuilder;
import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import com.fr.third.org.apache.http.message.BasicNameValuePair;
import com.fr.third.org.apache.http.util.EntityUtils;
import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @author fr.open
* @date 2019/4/2
*/
public class HttpUtil {
private static HostnameVerifier hv = new HostnameVerifier() {
@Override
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. "
+ session.getPeerHost());
return true;
}
};
/**
* 发送get请求
*
* @param url
* @param param
* @param header
* @return
* @throws IOException
*/
public static String sendGet(String url, Map<String, Object> param, Map<String, Object> header, String charset) {
String result = "";
BufferedReader in = null;
String urlNameString = url;
try {
if (param != null && !param.isEmpty()) {
urlNameString += "?";
urlNameString += param.entrySet()
.stream()
.map(entry -> entry.getKey() + "=" + entry.getValue().toString())
.collect(Collectors.joining("&"));
}
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
HttpURLConnection connection;
if (url.startsWith("https")) {
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
connection = (HttpURLConnection) realUrl.openConnection();
} else {
connection = (HttpURLConnection) realUrl.openConnection();
}
//设置超时时间
connection.setDoInput(true);
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(15000);
// 设置通用的请求属性
if (header != null) {
Iterator<Map.Entry<String, Object>> it = header.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Object> entry = it.next();
System.out.println(entry.getKey() + ":::" + entry.getValue());
connection.setRequestProperty(entry.getKey(), entry.getValue().toString());
}
}
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
if(connection.getResponseCode() == 200){
// 定义 BufferedReader输入流来读取URL的响应,设置utf8防止中文乱码
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), charset == null ? "utf-8" : charset));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
if (in != null) {
in.close();
}
}else {
in = new BufferedReader(new InputStreamReader(connection.getErrorStream(), charset == null ? "utf-8" : charset));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
if (in != null) {
in.close();
}
FineLoggerFactory.getLogger().error("Http post form code is {},message is {}",connection.getResponseCode(),result);
return StringUtils.EMPTY;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e, "get url error ,url is:{},error is {}", urlNameString, e.getMessage());
}
return result;
}
public static String sendPost(String url, Map<String, Object> header, JSONObject body) {
PrintWriter out = null;
BufferedReader in = null;
String result = null;
String res = null;
try {
String urlNameString = url;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
HttpURLConnection conn;
if (url.startsWith("https")) {
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
conn = (HttpURLConnection) realUrl.openConnection();
} else {
conn = (HttpURLConnection) realUrl.openConnection();
}
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
// conn.setRequestProperty("user-agent",
// "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
if (header != null) {
header.forEach((k, v) -> {
conn.setRequestProperty(k, String.valueOf(v));
});
}
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
//获取请求头
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
if (body != null) {
FineLoggerFactory.getLogger().error("content data: {}", body.toString());
FineLoggerFactory.getLogger().error("content cover data: {}", new String(body.toString().getBytes("UTF-8"), "UTF-8"));
out.print(new String(body.toString().getBytes("UTF-8"), "UTF-8"));
}
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
res = result;
if (res.startsWith("null")) {
res = res.replace("null", "");
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
//使用finally块来关闭输出流、输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
return res;
}
public static String doJSONPost(String url, Map<String, Object> header, JSONObject json, Map<String, Object> param, String chartset) {
HttpClient client = getHttpsClient();
/*if (url.startsWith("https")) {
SSLContext sslcontext = createIgnoreVerifySSL();
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
client = HttpClients.custom().setConnectionManager(connManager).build();
}*/
if (param != null && !param.isEmpty()) {
url += "?";
url += param.entrySet()
.stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining("&"));
}
HttpPost post = new HttpPost(url);
post.setHeader("accept", "*/*");
post.setHeader("connection", "Keep-Alive");
post.setHeader("Content-Type", "application/json");
if (header != null) {
header.forEach((k, v) -> {
post.setHeader(k, v.toString());
});
}
try {
StringEntity s = new StringEntity(json.toString(), chartset == null ? "UTF-8" : chartset);
s.setContentEncoding("UTF-8");
s.setContentType("application/json; charset=UTF-8");//发送json数据需要设置contentType
post.setEntity(s);
HttpResponse res = client.execute(post);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String result = EntityUtils.toString(res.getEntity());// 返回json格式:
return result;
} else {
FineLoggerFactory.getLogger().error("Http post form code is {},message is {}", res.getStatusLine().getStatusCode(), EntityUtils.toString(res.getEntity()));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
public static String doJSONPut(String url, Map<String, Object> header, JSONObject json, Map<String, Object> param, String chartset) {
HttpClient client = getHttpsClient();
/*if (url.startsWith("https")) {
SSLContext sslcontext = createIgnoreVerifySSL();
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
client = HttpClients.custom().setConnectionManager(connManager).build();
}*/
if (param != null && !param.isEmpty()) {
url += "?";
url += param.entrySet()
.stream()
.map(entry -> entry.getKey() + "=" + entry.getValue())
.collect(Collectors.joining("&"));
}
HttpPut post = new HttpPut(url);
post.setHeader("accept", "*/*");
post.setHeader("connection", "Keep-Alive");
post.setHeader("Content-Type", "application/json");
if (header != null) {
header.forEach((k, v) -> {
post.setHeader(k, v.toString());
});
}
try {
StringEntity s = new StringEntity(json.toString(), chartset == null ? "UTF-8" : chartset);
s.setContentEncoding("UTF-8");
s.setContentType("application/json; charset=UTF-8");//发送json数据需要设置contentType
post.setEntity(s);
HttpResponse res = client.execute(post);
if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String result = EntityUtils.toString(res.getEntity());// 返回json格式:
return result;
} else {
FineLoggerFactory.getLogger().error("Http post form code is {},message is {}", res.getStatusLine().getStatusCode(), EntityUtils.toString(res.getEntity()));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
public static String doFormPost(String url,Map<String, Object> header, Map<String, Object> map, String chartset) {
//声明返回结果
String result = "";
UrlEncodedFormEntity entity = null;
HttpResponse httpResponse = null;
HttpClient httpClient = null;
try {
// 创建连接
httpClient = getHttpsClient();
;
/*if (url.startsWith("https")) {
SSLContext sslcontext = createIgnoreVerifySSL();
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
HttpClients.custom().setConnectionManager(connManager);
httpClient = HttpClients.custom().setConnectionManager(connManager).build();
}*/
// 设置请求头和报文
HttpPost httpPost = new HttpPost(url);
if (header != null) {
header.forEach((k, v) -> {
httpPost.setHeader(k, v.toString());
});
}
//设置参数
List<NameValuePair> list = new ArrayList<NameValuePair>();
Iterator iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, String> elem = (Map.Entry<String, String>) iterator.next();
list.add(new BasicNameValuePair(elem.getKey(), elem.getValue()));
}
entity = new UrlEncodedFormEntity(list, chartset == null ? "UTF-8" : chartset);
httpPost.setEntity(entity);
//执行发送,获取相应结果
httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
result = EntityUtils.toString(httpResponse.getEntity());
} else {
FineLoggerFactory.getLogger().error("Http post form code is {},message is {}", httpResponse.getStatusLine().getStatusCode(), EntityUtils.toString(httpResponse.getEntity()));
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return result;
}
private static void trustAllHttpsCertificates() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager tm = new miTM();
trustAllCerts[0] = tm;
SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
/**
* encode url by UTF-8
*
* @param url url before encoding
* @return url after encoding
*/
public static String encodeUrl(String url) {
String eurl = url;
try {
eurl = URLEncoder.encode(url, "UTF-8");
} catch (UnsupportedEncodingException e) {
}
return eurl;
}
private static class miTM implements TrustManager,
X509TrustManager {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
}
public static SSLContext createIgnoreVerifySSL() {
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
// 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
X509TrustManager trustManager = new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
String paramString) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sc.init(null, new TrustManager[]{trustManager}, null);
return sc;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
private static CloseableHttpClient getHttpsClient() {
RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
// 指定信任密钥存储对象和连接套接字工厂
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// 信任任何链接
TrustStrategy anyTrustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {
// TODO Auto-generated method stub
return true;
}
};
SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build();
LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
registryBuilder.register("https", sslSF);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
Registry<ConnectionSocketFactory> registry = registryBuilder.build();
// 设置连接管理器
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
// 构建客户端
return HttpClientBuilder.create().setConnectionManager(connManager).build();
}
}

40
src/main/java/com/fr/plugin/nfsq/sso/Params.java

@ -0,0 +1,40 @@
package com.fr.plugin.nfsq.sso;
/**
* @Author fr.open
* @Date 2021/5/10
* @Description
**/
public class Params {
private String username;
private String accessToken;
private String refreshToken;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}

537
src/main/java/com/fr/plugin/nfsq/sso/SsoFilter.java

@ -0,0 +1,537 @@
package com.fr.plugin.nfsq.sso;
import com.fr.base.TemplateUtils;
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.bean.authentication.LoginRequestInfoBean;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.utils.DecisionStatusService;
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.HttpRequest;
import com.fr.general.http.HttpToolbox;
import com.fr.io.utils.ResourceIOUtils;
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 com.fr.web.utils.WebUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.Instant;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Author fr.open
* @Date 2020/9/10
* @Description
**/
@FunctionRecorder
public class SsoFilter extends AbstractGlobalRequestFilterProvider {
private final String CODE_KEY = "90bb6046";
@Override
public String filterName() {
return "nongfu";
}
@Override
public String[] urlPatterns() {
return new String[]{"/*"};
}
private static final String[] NOT_FILTER = {
"/decision/file",
"/decision/resources",
"/system",
"/materials.min.js.map",
"/remote",
"/login",
"/login/config",
"/getFineToken"
};
private String apiAuthorize;
private String apiAuthorizeResponseType;
private String apiClientId;
private String apiGetUser;
private String apiRefreshToken;
private String state;
public SsoFilter() {
InputStream in = ResourceIOUtils.read("/resources/xplatform.properties");
Properties properties = new Properties();
try {
properties.load(in);
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(),e);
}
this.apiAuthorize = properties.getProperty("api.authorize");
this.apiClientId = properties.getProperty("api.authorize.client_id");
this.apiAuthorizeResponseType = properties.getProperty("api.authorize.response_type");
this.apiGetUser = properties.getProperty("api.get-user");
this.apiRefreshToken = properties.getProperty("api.refresh-token");
this.state = properties.getProperty("api.authorize.state");
}
@Override
public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
String thisUrl = req.getRequestURL().toString();
FineLoggerFactory.getLogger().info("This request [{}] login status is [{}]", thisUrl, isLogin(req));
if (req.getRequestURI().endsWith("auth")) {
executeGetAuth(req, res);
return;
}
String code = req.getParameter("sign");
if (StringUtils.isNotBlank(code)) {
loginFromCode(code, req, res);
filter(req, res, filterChain);
return;
}
if (Stream.of(NOT_FILTER).anyMatch(thisUrl::contains) || isLogin(req) || isMobileDevice(req)) {
filter(req, res, filterChain);
return;
}
String prefix = null;
try {
prefix = TemplateUtils.render("${fineServletURL}");
if (req.getRequestURI().endsWith(prefix + "/login")) {
if (handlerWeChat(req, res)) {
return;
}
filter(req, res, filterChain);
return;
}
}catch (IllegalAccessException e){
redirectAuth(req, res);
return;
}catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
Params params = null;
try {
params = getUsername(req);
} catch (IllegalAccessException e) {
redirectAuth(req, res);
return;
}
FineLoggerFactory.getLogger().info("Getted username is [{}]", params.getUsername());
if (StringUtils.isNotBlank(params.getUsername())) {
Cookie at = new Cookie("access_token", params.getAccessToken());
at.setDomain("xxxx");
at.setMaxAge(7200);
Cookie rt = new Cookie("refresh_token", params.getRefreshToken());
rt.setDomain("xxxx");
rt.setMaxAge(7200);
res.addCookie(at);
res.addCookie(rt);
loginFromToken(req, res, params.getUsername());
try {
res.sendRedirect(getRedirectUriWithCachedParams(req));
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return;
}
redirectAuth(req, res);
}
private void redirectAuth(HttpServletRequest req, HttpServletResponse res) {
try {
res.sendRedirect(getAuthorizeUrl(req,res));
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(),e);
}
}
private boolean handlerWeChat(HttpServletRequest request, HttpServletResponse res) throws IOException, IllegalAccessException {
// 有帆软的登录信息
if (isLogin(request)) {
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> 已登录");
String token = getAccessToken(request);
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> token value is [{}]", token);
// 没有获取到access_token
if (StringUtils.isBlank(token)) {
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> token value is empty, 不做处理");
return false;
}
// 获取到了access_token, 比对帆软已登录的用户名和access_token对应的用户名
String username = getUsername(request, token).getUsername();
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> token 对应的用户名[{}]", username);
String username1 = LoginService.getInstance().getUserNameFromRequestCookie(request);
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> 已登录的用户名[{}]", username1);
if (Objects.equals(username1, username)) {
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> 两个用户名相同, 不做处理");
return false;
}
// 不一样的话使用access_token对应的用户名重新登录
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> 两个用户名不相同, 使用[{}]重新登录", username);
loginFromToken(request, res, username);
return false;
}
// 没有登录信息
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> 未登录");
String token = getAccessToken(request);
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> token value is [{}]", token);
if (StringUtils.isNotBlank(token)) {
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> token value is not empty, 处理自动登录逻辑");
Params params = getUsername(request, token);
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> 获取到的用户名[{}]", params.getUsername());
if (StringUtils.isNotBlank(params.getUsername()) && exist(params.getUsername())) {
Cookie at = new Cookie("access_token", params.getAccessToken());
at.setDomain("yst.com.cn");
Cookie rt = new Cookie("refresh_token", params.getRefreshToken());
rt.setDomain("yst.com.cn");
loginFromToken(request, res, params.getUsername());
res.sendRedirect(getRedirectUriWithCachedParams(request));
return true;
}
}
FineLoggerFactory.getLogger().info("/decision请求特殊处理 >>> token value is empty, 跳转到sso登录页");
res.sendRedirect(getAuthorizeUrl(request, res));
return true;
}
private String getAuthorizeUrl(HttpServletRequest request, HttpServletResponse res) throws UnsupportedEncodingException {
String urlPattern = "%s?response_type=%s&client_id=%s&redirect_uri=%s&_=%s&state=%s";
String state = cacheParams(request);
res.addCookie(new Cookie("FINE_REDIRECT_PARAM",state));
if (StringUtils.isNotBlank(state)) {
urlPattern += "&target=" + state;
}
String url = String.format(urlPattern,
apiAuthorize,
apiAuthorizeResponseType,
apiClientId,
URLEncoder.encode(request.getRequestURL().toString(), "utf-8"),
Instant.now().toEpochMilli(),
this.state
);
FineLoggerFactory.getLogger().info("授权登录页面[{}]", url);
return url;
}
private String cacheParams(HttpServletRequest request) {
Enumeration<String> names = request.getParameterNames();
Map<String, String> value = new HashMap<>();
while (names.hasMoreElements()) {
String name = names.nextElement();
value.put(name, request.getParameter(name));
}
if (value.isEmpty()) {
return StringUtils.EMPTY;
}
String key = UUID.randomUUID().toString();
try {
DecisionStatusService.originUrlStatusService().put(key, value);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return key;
}
/**
* 登录成功后将缓存中存储的url参数拼接入对应地址
*
* @param request
* @return
*/
private String getRedirectUriWithCachedParams(HttpServletRequest request) {
String redirectUri = request.getRequestURL().toString();
String key = request.getParameter("target");
if(StringUtils.isBlank(key)){
key = getCookieValue(request, "FINE_REDIRECT_PARAM");
}
if(StringUtils.isBlank(key)){
return redirectUri;
}
Map<String, String> value = new HashMap<>();
try {
value = DecisionStatusService.originUrlStatusService().get(key);
if (com.fr.stable.StringUtils.isNotBlank(key) && !value.isEmpty()) {
DecisionStatusService.originUrlStatusService().delete(key);
Map<String, String> finalValue = value;
redirectUri += "?" + value.keySet().stream().map(k -> String.format("%s=%s", k, finalValue.get(k))).collect(Collectors.joining("&"));
}
} catch (Exception e) {
e.printStackTrace();
}
return redirectUri;
}
private boolean exist(String username) {
User user = null;
try {
user = UserService.getInstance().getUserByUserName(username);
} catch (Exception e) {
e.printStackTrace();
}
return user != null;
}
private Params getUsername(HttpServletRequest request) throws IllegalAccessException {
String token = getAccessToken(request);
if(StringUtils.isBlank(token)){
FineLoggerFactory.getLogger().info("token is null");
return new Params();
}
return getUsername(request, token);
}
private Params getUsername(HttpServletRequest request, String accessToken) throws IllegalAccessException {
String url = apiGetUser + "?access_token=" + accessToken;
FineLoggerFactory.getLogger().info("Get user api address is [{}]", url);
try {
String res = HttpToolbox.executeAndParse(HttpRequest.custom().url(url)
.get()
.build());
FineLoggerFactory.getLogger().info("获取用户信息接口返回内容 ==> {}", res);
JSONObject body = new JSONObject(res);
if (body.getBoolean("success") && body.has("data")) {
body = body.getJSONObject("data");
if (body.has("account")) {
Params params = new Params();
params.setRefreshToken(getRefreshToken(request));
params.setUsername(body.getString("account"));
params.setAccessToken(accessToken);
return params;
}
}
if (body.has("message") && "token不合法".equals(body.getString("message"))) {
FineLoggerFactory.getLogger().info("Access Token [{}] 不合法, 使用Refresh Token[{}]重新获取", accessToken, getRefreshToken(request));
accessToken = getAccessTokenWithRefreshToken(request);
return getUsername(request, accessToken);
}
throw new IllegalAccessException();
}catch (IllegalAccessException e){
throw new IllegalAccessException();
}catch (Exception e) {
FineLoggerFactory.getLogger().error("获取用户名失败", e);
throw new RuntimeException(e);
}
}
private String getAccessTokenWithRefreshToken(HttpServletRequest request) throws Exception {
String url = apiRefreshToken + String.format("?refresh_token=%s&client_id=%s&grant_type=refresh_token", getRefreshToken(request), apiClientId);
FineLoggerFactory.getLogger().info("Refresh Token api address is [{}]", url);
String res = HttpToolbox.executeAndParse(HttpRequest.custom().url(url)
.get()
.build());
FineLoggerFactory.getLogger().info("刷新token接口返回内容 ==> {}", res);
JSONObject body = new JSONObject(res);
if (body.getBoolean("success") && body.has("data")) {
body = body.getJSONObject("data");
if (body.has("access_token")) {
return body.getString("access_token");
}
}
throw new IllegalAccessException();
}
private String getRefreshToken(HttpServletRequest request) {
return getValueFromRequest(request, "refresh_token");
}
private String getAccessToken(HttpServletRequest request) {
return getValueFromRequest(request, "access_token");
}
private String getValueFromRequest(HttpServletRequest request, String key) {
try {
String value = request.getParameter(key);
if (StringUtils.isEmpty(value)) {
value = getCookieValue(request, key);
}
if (StringUtils.isEmpty(value)) {
String params = request.getParameter("app");
params = params.substring(params.indexOf("#") + 1);
Map<String, String> values = Pattern.compile("&").splitAsStream(params).map(e -> e.split("=")).collect(Collectors.toMap(e -> e[0], e -> e[1]));
value = values.get(key);
}
return value;
} catch (Exception e) {
FineLoggerFactory.getLogger().error("Failed to get \"{}\" value from this request, cause by: ", key, e.getMessage());
FineLoggerFactory.getLogger().error("", e);
}
return "";
}
private String getCookieValue(HttpServletRequest request, String key) {
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies) {
if (StringUtils.equals(c.getName(), key)) {
return c.getValue();
}
}
return StringUtils.EMPTY;
}
private void loginFromCode(String code, HttpServletRequest req, HttpServletResponse res) {
FineLoggerFactory.getLogger().info("ssoFilter >>> inside login code param is {}", code);
try {
code = DesECBUtil.decryptDES(code, CODE_KEY);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
FineLoggerFactory.getLogger().info("ssoFilter >>> inside login code decode is {}", code);
String[] arr = code.split("_");
loginFromToken(req, res, arr[0]);
}
private void executeGetAuth(HttpServletRequest req, HttpServletResponse res) {
String uri = WebUtils.getHTTPRequestParameter(req, "redirect_uri");
String currentUsername = null;
try {
User user= null;
try {
user = UserService.getInstance().getUserByRequest(req);
}catch (Exception e){
}
if(user == null){
user = UserService.getInstance().getUserByRequestCookie(req);
}
currentUsername = user.getUserName();
String encryptDES = DesECBUtil.encryptDES(String.format("%s_%d", currentUsername, Instant.now().toEpochMilli()), CODE_KEY);
encryptDES = URLEncoder.encode(encryptDES, "UTF-8");
uri = uri.indexOf("?") == -1 ? uri + "?sign=" + encryptDES : uri + "&sign=" + encryptDES;
res.sendRedirect(uri);
FineLoggerFactory.getLogger().info("ssoFilter >>> inside redirect url is {}", uri);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean notExistUser(String username) {
User user = null;
try {
user = UserService.getInstance().getUserByUserName(username);
if (user == null) {
return true;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
private boolean hasCookie(HttpServletRequest req) {
if (req.getCookies() == null) {
return false;
}
return Stream.of(req.getCookies()).anyMatch(e -> "IAM_SESSION".equalsIgnoreCase(e.getName()));
}
public LoginRequestInfoBean getLoginInfo(HttpServletRequest req) {
try {
BufferedReader br = req.getReader();
String str = "";
String listString = "";
while ((str = br.readLine()) != null) {
listString += str;
}
JSONObject jsonObject = new JSONObject(listString);
LoginRequestInfoBean info = jsonObject.mapTo(LoginRequestInfoBean.class);
//info.setPassword(TransmissionTool.decrypt(info.isEncrypted(),info.getPassword()));
return info;
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return null;
}
private boolean loginFromToken(HttpServletRequest req, HttpServletResponse res, String username) {
try {
if (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;
}
private void filter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
try {
filterChain.doFilter(req, res);
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (ServletException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), 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;
}
public boolean isMobileDevice(HttpServletRequest request) {
String requestHeader = request.getHeader("user-agent");
String[] deviceArray = new String[]{"android", "iphone", "ios", "windows phone"};
if (requestHeader == null) {
return false;
}
requestHeader = requestHeader.toLowerCase();
for (int i = 0; i < deviceArray.length; i++) {
if (requestHeader.contains(deviceArray[i]) && request.getRequestURI().endsWith("/login")) {
FineLoggerFactory.getLogger().info("current request:{} is mobile request!", request.getRequestURI());
return true;
}
}
return false;
}
}

103
src/main/java/com/fr/plugin/nfsq/sso/SsoHttpHandler.java

@ -0,0 +1,103 @@
package com.fr.plugin.nfsq.sso;
import com.fr.decision.authority.data.User;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.general.PropertiesUtils;
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 fr.open
* @since 2020/08/28
*/
@EnableMetrics
public class SsoHttpHandler extends BaseHttpHandler {
private String apiUser = "";
public SsoHttpHandler() {
apiUser = PropertiesUtils.getProperties("xplatform").getProperty("api.get-user");
}
@Override
public RequestMethod getMethod() {
return RequestMethod.GET;
}
@Override
public String getPath() {
return "/getFineToken";
}
@Override
public boolean isPublic() {
return true;
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (StringUtils.isBlank(apiUser)) {
sendError(response, "apiUser config is null");
return;
}
String token = request.getParameter("access_token");
if (StringUtils.isBlank(token)) {
sendError(response, "token is null");
return;
}
String userName = getUsername(token);
if (StringUtils.isBlank(userName)) {
sendError(response, "get user is null");
return;
}
User user = UserService.getInstance().getUserByUserName(userName);
FineLoggerFactory.getLogger().info("get user:" + user);
if (user == null) {
sendError(response, "user not exist");
}
String fineToken = LoginService.getInstance().login(request, response, userName);
JSONObject jsonObject = new JSONObject("{\"codeDesc\":\"success\",\"success\":true,\"codeNum\":0}");
jsonObject.put("value", JSONObject.create().put("fine_oath_token", fineToken));
response.setContentType("application/json;charset=UTF-8");
WebUtils.printAsJSON(response, jsonObject);
}
private String getUsername(String accessToken) {
String url = apiUser + "?access_token=" + accessToken;
FineLoggerFactory.getLogger().info("Get user api address is [{}]", url);
try {
String res = HttpUtil.sendGet(url, null, null, null);
FineLoggerFactory.getLogger().info("获取用户信息接口返回内容 ==> {}", res);
JSONObject body = new JSONObject(res);
if (body.getBoolean("success") && body.has("data")) {
body = body.getJSONObject("data");
if (body.has("account")) {
return body.getString("account");
}
}
throw new IllegalAccessException();
} catch (Exception e) {
FineLoggerFactory.getLogger().error("获取用户名失败", e);
throw new RuntimeException(e);
}
}
protected void sendError(HttpServletResponse response, String errorCode) {
JSONObject jsonObject = new JSONObject("{\"codeDesc\":\"" + errorCode + "\",\"success\":false,\"codeNum\":70}");
try {
response.setContentType("application/json;charset=UTF-8");
WebUtils.printAsJSON(response, jsonObject);
} catch (Exception e) {
FineLoggerFactory.getLogger().error("输出响应错误失败", e);
}
}
}

19
src/main/java/com/fr/plugin/nfsq/sso/SsoRequestHandlerBridge.java

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

18
src/main/java/com/fr/plugin/nfsq/sso/SsoRequestURLAliasBridge.java

@ -0,0 +1,18 @@
package com.fr.plugin.nfsq.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 fr.open
* @since 2020/08/28
*/
public class SsoRequestURLAliasBridge extends AbstractURLAliasProvider {
@Override
public URLAlias[] registerAlias() {
return new URLAlias[]{
URLAliasFactory.createPluginAlias("/getFineToken", "/getFineToken", true),
};
}
}
Loading…
Cancel
Save