pioneer
2 years ago
commit
daa061aaa5
12 changed files with 757 additions and 0 deletions
@ -0,0 +1,7 @@ |
|||||||
|
|
||||||
|
# open-JSD-9872 |
||||||
|
|
||||||
|
JSD-9872 SSO单点集成\ |
||||||
|
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||||
|
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||||
|
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 |
Binary file not shown.
@ -0,0 +1,24 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
<plugin> |
||||||
|
<id>com.eco.plugin.zzl.oauth2.mt</id> |
||||||
|
<name><![CDATA[美团单点]]></name> |
||||||
|
<active>yes</active> |
||||||
|
<version>1.10.5</version> |
||||||
|
<env-version>10.0</env-version> |
||||||
|
<jartime>2021-02-10</jartime> |
||||||
|
<vendor>fr.open</vendor> |
||||||
|
<main-package>com.fr.plugin</main-package> |
||||||
|
<!--用来记录这个任务的创建时间--> |
||||||
|
<description><![CDATA[ |
||||||
|
|
||||||
|
]]></description> |
||||||
|
<!--任务ID: 9872--> |
||||||
|
<create-day>2022-5-10 17:03:49</create-day> |
||||||
|
<extra-decision> |
||||||
|
<HttpHandlerProvider class="com.fr.plugin.http.MTHttpHandler"/> |
||||||
|
<URLAliasProvider class="com.fr.plugin.http.MTUrlAliasProvider"/> |
||||||
|
<GlobalRequestFilterProvider class="com.fr.plugin.filter.MT1Filter"/> |
||||||
|
</extra-decision> |
||||||
|
<lifecycle-monitor class="com.fr.plugin.MTLifeCycleMonitor"/> |
||||||
|
<function-recorder class="com.fr.plugin.FunctionRecoder"/> |
||||||
|
</plugin> |
@ -0,0 +1,12 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||||
|
import com.fr.plugin.transform.FunctionRecorder; |
||||||
|
|
||||||
|
@FunctionRecorder |
||||||
|
public class FunctionRecoder { |
||||||
|
@ExecuteFunctionRecord |
||||||
|
public void exe(){ |
||||||
|
System.out.println("插件功能埋点,虽然不会执行,除非上架应用"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.config.*; |
||||||
|
import com.fr.config.holder.Conf; |
||||||
|
import com.fr.config.holder.factory.Holders; |
||||||
|
|
||||||
|
@Visualization(category = "xx单点配置") |
||||||
|
public class MTConfig extends DefaultConfiguration { |
||||||
|
|
||||||
|
private static volatile MTConfig config = null; |
||||||
|
|
||||||
|
public static MTConfig getInstance() { |
||||||
|
if (config == null) { |
||||||
|
config = ConfigContext.getConfigInstance(MTConfig.class); |
||||||
|
} |
||||||
|
return config; |
||||||
|
} |
||||||
|
|
||||||
|
@Identifier(value = "clientId", name = "clientId", description = "描述", status = Status.SHOW) |
||||||
|
private Conf<String> clientId = Holders.simple(""); |
||||||
|
@Identifier(value = "clientSecret", name = "clientSecret", description = "描述", status = Status.SHOW) |
||||||
|
private Conf<String> clientSecret = Holders.simple(""); |
||||||
|
@Identifier(value = "notExistUrl", name = "用户不存在调整地址", description = "用户不存在调整地址URL", status = Status.SHOW) |
||||||
|
private Conf<String> notExistUrl = Holders.simple("https://xx/bi/has-error?message=%22%E7%94%A8%E6%88%B7%E4%B8%8D%E5%AD%98%E5%9C%A8%22"); |
||||||
|
@Identifier(value = "apiUrl", name = "接口地址", description = "描述", status = Status.SHOW) |
||||||
|
private Conf<String> apiUrl = Holders.simple(""); |
||||||
|
@Identifier(value = "frUrl", name = "fr地址", description = "描述", status = Status.SHOW) |
||||||
|
private Conf<String> frUrl = Holders.simple("http://localhost:8080/webroot/decision/"); |
||||||
|
|
||||||
|
public String getNotExistUrl() { |
||||||
|
return notExistUrl.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setNotExistUrl( String notExistUrl) { |
||||||
|
this.notExistUrl .set(notExistUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public String getClientId() { |
||||||
|
return clientId.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setClientId(String clientId) { |
||||||
|
this.clientId.set(clientId); |
||||||
|
} |
||||||
|
|
||||||
|
public String getClientSecret() { |
||||||
|
return clientSecret.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setClientSecret(String clientSecret) { |
||||||
|
this.clientSecret.set(clientSecret); |
||||||
|
} |
||||||
|
|
||||||
|
public String getApiUrl() { |
||||||
|
return apiUrl.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setApiUrl(String apiUrl) { |
||||||
|
this.apiUrl.set(apiUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public String getFrUrl() { |
||||||
|
return frUrl.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setFrUrl(String frUrl) { |
||||||
|
this.frUrl.set(frUrl); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() throws CloneNotSupportedException { |
||||||
|
MTConfig cloned = (MTConfig) super.clone(); |
||||||
|
cloned.clientId = (Conf<String>) this.clientId.clone(); |
||||||
|
cloned.clientSecret = (Conf<String>) this.clientSecret.clone(); |
||||||
|
cloned.apiUrl = (Conf<String>) this.apiUrl.clone(); |
||||||
|
cloned.frUrl = (Conf<String>) this.frUrl.clone(); |
||||||
|
cloned.notExistUrl = (Conf<String>) this.notExistUrl.clone(); |
||||||
|
return cloned; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.plugin.context.PluginContext; |
||||||
|
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||||
|
import com.fr.stable.fun.Authorize; |
||||||
|
|
||||||
|
@Authorize |
||||||
|
public class MTLifeCycleMonitor extends AbstractPluginLifecycleMonitor { |
||||||
|
@Override |
||||||
|
public void afterRun(PluginContext pluginContext) { |
||||||
|
MTConfig.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void beforeStop(PluginContext pluginContext) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,100 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; |
||||||
|
import com.fr.third.org.apache.http.client.methods.HttpGet; |
||||||
|
import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; |
||||||
|
import com.fr.third.org.apache.http.impl.client.HttpClients; |
||||||
|
import com.fr.third.org.apache.http.util.EntityUtils; |
||||||
|
|
||||||
|
import javax.crypto.Mac; |
||||||
|
import javax.crypto.spec.SecretKeySpec; |
||||||
|
import java.io.IOException; |
||||||
|
import java.text.DateFormat; |
||||||
|
import java.text.SimpleDateFormat; |
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
public class SsoHttpUtil { |
||||||
|
private static String publicKey = ""; |
||||||
|
|
||||||
|
public static String getPublicKey() { |
||||||
|
return publicKey; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static void initPublicKey() throws IOException { |
||||||
|
publicKey = getPublickey(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return 公钥 publickey |
||||||
|
*/ |
||||||
|
public static String getPublickey() throws IOException { |
||||||
|
MTConfig mtConfig = MTConfig.getInstance(); |
||||||
|
String apiUrl = mtConfig.getApiUrl(); |
||||||
|
String clientId = mtConfig.getClientId(); |
||||||
|
String clientSecret = mtConfig.getClientSecret(); |
||||||
|
|
||||||
|
String url = apiUrl + "/fedauth/api/publickey"; |
||||||
|
HttpGet httpGet = new HttpGet(url); |
||||||
|
|
||||||
|
// 设置header
|
||||||
|
String baUri = "/fedauth/api/publickey"; |
||||||
|
Map<String, String> map = SsoHttpUtil.getSignedHeaders("GET", baUri, clientId, clientSecret); |
||||||
|
httpGet.addHeader("Authorization", map.get("Authorization")); |
||||||
|
httpGet.addHeader("Content-Type", map.get("Content-Type")); |
||||||
|
httpGet.addHeader("Date", map.get("Date")); |
||||||
|
CloseableHttpClient httpClient = HttpClients.createDefault(); |
||||||
|
|
||||||
|
CloseableHttpResponse response = httpClient.execute(httpGet); |
||||||
|
if (response.getStatusLine().getStatusCode() == 200) { |
||||||
|
String responseString = EntityUtils.toString(response.getEntity(), "utf-8"); |
||||||
|
JSONObject jsonObject = new JSONObject(responseString); |
||||||
|
JSONObject data = jsonObject.getJSONObject("data"); |
||||||
|
return data.getString("publicKey"); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public static Map<String, String> getSignedHeaders(String method, String uri, String key, String token) { |
||||||
|
String date = BaUtil.getAuthDate(new Date()); |
||||||
|
method = method.toUpperCase(); |
||||||
|
String authorization = BaUtil.getAuthorization(uri, method, date, key, token); |
||||||
|
Map<String, String> headers = new HashMap<>(); |
||||||
|
headers.put("Authorization", authorization); |
||||||
|
headers.put("Content-Type", "application/json"); |
||||||
|
headers.put("Date", date); |
||||||
|
return headers; |
||||||
|
} |
||||||
|
|
||||||
|
private static class BaUtil { |
||||||
|
public static String getAuthDate(Date date) { |
||||||
|
DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH); |
||||||
|
df.setTimeZone(TimeZone.getTimeZone("GMT")); |
||||||
|
return df.format(date); |
||||||
|
} |
||||||
|
|
||||||
|
public static String getAuthorization(String uri, String method, String date, String clientId, String secret) { |
||||||
|
String stringToSign = method + " " + uri + "\n" + date; |
||||||
|
String signature = getSignature(stringToSign, secret); |
||||||
|
String authorization = "MWS " + clientId + ":" + signature; |
||||||
|
return authorization; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getSignature(String data, String secret) { |
||||||
|
try { |
||||||
|
SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), "HmacSHA1"); |
||||||
|
Mac mac = Mac.getInstance("HmacSHA1"); |
||||||
|
mac.init(signingKey); |
||||||
|
byte[] rawHmac = mac.doFinal(data.getBytes()); |
||||||
|
String result = Base64.getEncoder().encodeToString(rawHmac); |
||||||
|
result = result.replaceAll("\r|\n", ""); |
||||||
|
return result; |
||||||
|
} catch (Exception var6) { |
||||||
|
throw new RuntimeException("Failed to generate HMAC : " + var6.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,156 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
|
||||||
|
import com.fr.third.org.apache.commons.codec.digest.DigestUtils; |
||||||
|
|
||||||
|
import javax.crypto.Cipher; |
||||||
|
import java.security.Key; |
||||||
|
import java.security.KeyFactory; |
||||||
|
import java.security.spec.X509EncodedKeySpec; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Base64; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class TicketUtil { |
||||||
|
/** |
||||||
|
* 检查票据格式 |
||||||
|
* |
||||||
|
* @param ticket |
||||||
|
* @return 返回分割后的数组 header + payload + signature |
||||||
|
*/ |
||||||
|
public static String[] checkTicketFormat(String ticket) { |
||||||
|
if (ticket == null || ticket.isEmpty()) { |
||||||
|
throw new IllegalArgumentException("transform value can't be null or empty!"); |
||||||
|
} |
||||||
|
String[] strs = ticket.split("\\*"); |
||||||
|
if (strs.length != 3) { |
||||||
|
throw new IllegalArgumentException("ticket:" + ticket + " is illegal"); |
||||||
|
} |
||||||
|
return strs; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 校验票据签名 |
||||||
|
* |
||||||
|
* @param plainPart header*payload |
||||||
|
* @param signature signature |
||||||
|
* @param publicKey publicKey |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static boolean validateTicket(String plainPart, String signature, String publicKey) { |
||||||
|
try { |
||||||
|
byte[] encryptedData = Base64.getDecoder().decode(signature); |
||||||
|
byte[] decryptedData = decryptByPublicKey(Cipher.DECRYPT_MODE, encryptedData, publicKey); |
||||||
|
byte[] data = DigestUtils.md5(plainPart); |
||||||
|
|
||||||
|
if (decryptedData.length != data.length) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < data.length; i++) { |
||||||
|
if (decryptedData[i] != data[i]) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
return true; |
||||||
|
} catch (Exception e) { |
||||||
|
//log.error("Signature Error", e);
|
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 将元组格式的字符串转换为字符串数组,例如: |
||||||
|
* "(1,1111246415021011037,,,1553777365956)" -> ["1","1111246415021011037", "", "", "1550498840000"].length = 5 |
||||||
|
* "(1,(1234567890,suweijie02),1)" -> ["1", "(1234567890,suweijie02)", "1"].length = 3 |
||||||
|
* |
||||||
|
* @param text |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static List<String> splitBrackets(String text) { |
||||||
|
List<String> list = new ArrayList<>(); |
||||||
|
if (text == null || text.isEmpty()) { |
||||||
|
return list; |
||||||
|
} |
||||||
|
if (!text.startsWith("(") || !text.endsWith(")")) { |
||||||
|
list.add(text); |
||||||
|
return list; |
||||||
|
} |
||||||
|
int brackets = 0; |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (int i = 1; i < text.length() - 1; i++) { |
||||||
|
char ch = text.charAt(i); |
||||||
|
if (ch == ',' && brackets == 0) { |
||||||
|
list.add(sb.toString()); |
||||||
|
sb = new StringBuilder(); |
||||||
|
continue; |
||||||
|
} |
||||||
|
if (ch == '(') { |
||||||
|
brackets++; |
||||||
|
} else if (ch == ')') { |
||||||
|
brackets--; |
||||||
|
} |
||||||
|
sb.append(ch); |
||||||
|
} |
||||||
|
if (brackets != 0) { |
||||||
|
throw new IllegalArgumentException("text:" + text + "不符合正确的压缩格式"); |
||||||
|
} |
||||||
|
if (sb.length() > 0) { |
||||||
|
list.add(sb.toString()); |
||||||
|
} |
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 公钥解密 |
||||||
|
* |
||||||
|
* @param mode |
||||||
|
* @param data |
||||||
|
* @param pubKey |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
private static byte[] decryptByPublicKey(int mode, byte[] data, String pubKey) throws Exception { |
||||||
|
// 对密钥解密
|
||||||
|
byte[] keyBytes = Base64.getDecoder().decode(pubKey); |
||||||
|
|
||||||
|
// 取得公钥
|
||||||
|
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes); |
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); |
||||||
|
Key publicKey = keyFactory.generatePublic(x509KeySpec); |
||||||
|
|
||||||
|
// 对数据加解密
|
||||||
|
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); |
||||||
|
cipher.init(mode, publicKey); |
||||||
|
|
||||||
|
return cipher.doFinal(data); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception { |
||||||
|
//公钥
|
||||||
|
String publicKey = "从接口获取"; |
||||||
|
//id-token
|
||||||
|
String idToken = "(1,1111246415021011037,,,1553777365956)*(1,(2104577,sushiyu),0)*GoOeRQkLurl19UJDdVZk1uoUKlr4hhKCVFYg7tVC9bWuhDmnK6BAwpZuvDDX2/6MF3UrkcRWCdHfmI4WJTD2eg=="; |
||||||
|
//检查idToken,并返回分割后的数组 header + payload + signature
|
||||||
|
String[] strs = checkTicketFormat(idToken); |
||||||
|
|
||||||
|
//step1 是否过期
|
||||||
|
List<String> header = splitBrackets(strs[0]); |
||||||
|
long expire = Long.valueOf(header.get(4)); |
||||||
|
if (expire < System.currentTimeMillis()) { |
||||||
|
throw new Exception("ticket is expire"); |
||||||
|
} |
||||||
|
|
||||||
|
//step 2 验证签名
|
||||||
|
if (!validateTicket(strs[0] + "*" + strs[1], strs[2], publicKey)) { |
||||||
|
throw new IllegalArgumentException("ticket is illegal"); |
||||||
|
} |
||||||
|
|
||||||
|
//step3 获取用户信息
|
||||||
|
List<String> payload = splitBrackets(strs[1]); |
||||||
|
List<String> user = splitBrackets(payload.get(1)); |
||||||
|
Long uid = Long.parseLong(user.get(0)); |
||||||
|
String mis = user.get(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,203 @@ |
|||||||
|
package com.fr.plugin.filter; |
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fr.base.ServerConfig; |
||||||
|
import com.fr.data.NetworkHelper; |
||||||
|
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; |
||||||
|
import com.fr.decision.mobile.terminal.TerminalHandler; |
||||||
|
import com.fr.decision.webservice.v10.login.LoginService; |
||||||
|
import com.fr.decision.webservice.v10.login.TokenResource; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.MTConfig; |
||||||
|
import com.fr.plugin.SsoHttpUtil; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.web.Device; |
||||||
|
import com.fr.web.utils.WebUtils; |
||||||
|
|
||||||
|
import javax.servlet.FilterChain; |
||||||
|
import javax.servlet.FilterConfig; |
||||||
|
import javax.servlet.http.Cookie; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class MT1Filter extends AbstractGlobalRequestFilterProvider { |
||||||
|
@Override |
||||||
|
public String filterName() { |
||||||
|
return "MT1Filter"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String[] urlPatterns() { |
||||||
|
return new String[]{ |
||||||
|
"/*", |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void init(FilterConfig filterConfig) { |
||||||
|
super.init(filterConfig); |
||||||
|
//获取一下公钥
|
||||||
|
try { |
||||||
|
SsoHttpUtil.initPublicKey(); |
||||||
|
} catch (Exception e) { |
||||||
|
LogKit.error("美团初始化公钥失败", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) { |
||||||
|
try { |
||||||
|
if (isLogOut(req)) { |
||||||
|
delLoginOut(req, res); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (needFilter(req) && !isLogin(req)) { |
||||||
|
String loginUrl = MTConfig.getInstance().getApiUrl(); |
||||||
|
String clientId = MTConfig.getInstance().getClientId(); |
||||||
|
String frUrl = MTConfig.getInstance().getFrUrl(); |
||||||
|
String originalURL = getUrl(req); |
||||||
|
String callback = URLEncoder.encode(frUrl + "url/mtlogin?callback=" + URLEncoder.encode(originalURL, "UTF-8"), "UTF-8"); |
||||||
|
String redirectUrl = loginUrl + "/fedauth/authorize?client_id=" + clientId + "&redirect_uri=" + callback; |
||||||
|
sendRedirect(res, redirectUrl); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
filterChain.doFilter(req, res); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String getUrl(HttpServletRequest request) { |
||||||
|
StringBuilder builder=new StringBuilder( ); |
||||||
|
|
||||||
|
String url = "/"; |
||||||
|
try { |
||||||
|
url = request.getScheme()+"://" + request.getServerName()//服务器地址
|
||||||
|
+ ":" |
||||||
|
+ request.getServerPort() + request.getRequestURI(); |
||||||
|
builder.append(url); |
||||||
|
Enumeration<String> parameterNames = request.getParameterNames(); |
||||||
|
builder.append("?ttt=1"); |
||||||
|
while (parameterNames.hasMoreElements()) { |
||||||
|
String key = parameterNames.nextElement(); |
||||||
|
if(StringUtils.equals(key,"ticket")){ |
||||||
|
continue; |
||||||
|
} |
||||||
|
builder.append("&").append(key).append("=").append(URLEncoder.encode(request.getParameter(key),"UTF-8")); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
return builder.toString(); |
||||||
|
} |
||||||
|
private void delLoginOut(HttpServletRequest req, HttpServletResponse res) { |
||||||
|
try { |
||||||
|
//执行帆软内部的退出
|
||||||
|
LoginService.getInstance().logout(req, res); |
||||||
|
JSONObject jsonObject = new JSONObject(); |
||||||
|
MTConfig mtConfig = MTConfig.getInstance(); |
||||||
|
String apiUrl = mtConfig.getApiUrl(); |
||||||
|
String clientId = mtConfig.getClientId(); |
||||||
|
String callback = URLEncoder.encode(mtConfig.getFrUrl() + "url/mtlogin", "UTF-8"); |
||||||
|
String redirectUrl = apiUrl + "/fedauth/authorize?client_id=" + clientId + "&redirect_uri=" + callback; |
||||||
|
String logoutUrl = apiUrl + "/sson/logout?client_id=" + clientId + "&redirect_uri=" + URLEncoder.encode(redirectUrl, "UTF-8"); |
||||||
|
jsonObject.put("data", logoutUrl); |
||||||
|
WebUtils.printAsJSON(res, jsonObject); |
||||||
|
} catch (Exception e) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isLogOut(HttpServletRequest req) { |
||||||
|
String url = WebUtils.getOriginalURL(req); |
||||||
|
String servletNamePrefix = "/" + ServerConfig.getInstance().getServletName() + "/logout"; |
||||||
|
return url.contains(servletNamePrefix) && req.getMethod().equals("POST"); |
||||||
|
} |
||||||
|
|
||||||
|
private void login(HttpServletRequest req, HttpServletResponse res, String username) { |
||||||
|
String token = null; |
||||||
|
try { |
||||||
|
token = LoginService.getInstance().login(req, res, username); |
||||||
|
req.setAttribute("fine_auth_token", token); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
FineLoggerFactory.getLogger().error("login failed"); |
||||||
|
} |
||||||
|
FineLoggerFactory.getLogger().error("login success"); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isLogin(HttpServletRequest request) { |
||||||
|
String oldToken = TokenResource.COOKIE.getToken(request); |
||||||
|
return oldToken != null && checkTokenValid(request, (String) oldToken); |
||||||
|
} |
||||||
|
|
||||||
|
private void sendRedirect(HttpServletResponse res, String url) { |
||||||
|
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); |
||||||
|
res.setHeader("Location", url); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean needFilter(HttpServletRequest request) { |
||||||
|
String requestURI = request.getRequestURI(); |
||||||
|
if (StringUtils.isNotBlank(requestURI) && request.getMethod().equals("GET")) { |
||||||
|
if (requestURI.endsWith("decision")||requestURI.endsWith("decision/")) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (requestURI.endsWith("/view/form") || requestURI.endsWith("/view/report")) { |
||||||
|
if (StringUtils.isNotBlank(request.getParameter("viewlet"))) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
if ((requestURI.contains("/v5/api/conf/page") ||requestURI.contains("/v5/api/conf/page/") )&& request.getMethod().equals("GET")) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if (requestURI.contains("/v10/entry/access/") && request.getMethod().equals("GET")) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
if (requestURI.contains("/v5/design/report") && (requestURI.endsWith("/edit") || requestURI.endsWith("/view"))) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
if(request.getMethod().equals("GET")){ |
||||||
|
for (String filterUrl : filterUrls) { |
||||||
|
if (requestURI.endsWith(filterUrl)||requestURI.endsWith(filterUrl+"/")) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
private static List<String> filterUrls=new ArrayList<String>(); |
||||||
|
static { |
||||||
|
String servletName = ServerConfig.getInstance().getServletName(); |
||||||
|
filterUrls.add(servletName+"/dashboard"); |
||||||
|
filterUrls.add(servletName+"/dashboard/management"); |
||||||
|
filterUrls.add(servletName+"/directory"); |
||||||
|
filterUrls.add(servletName+"/user"); |
||||||
|
filterUrls.add(servletName+"/dashboard"); |
||||||
|
filterUrls.add(servletName+"/privilege"); |
||||||
|
filterUrls.add(servletName+"/timer"); |
||||||
|
} |
||||||
|
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; |
||||||
|
} |
||||||
|
|
||||||
|
private static void setCookie(HttpServletResponse response, String name, String value) { |
||||||
|
Cookie cookie = new Cookie(name, value); |
||||||
|
cookie.setPath("/"); |
||||||
|
response.addCookie(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.fr.plugin.http; |
||||||
|
|
||||||
|
import com.fr.decision.fun.HttpHandler; |
||||||
|
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; |
||||||
|
import com.fr.plugin.http.handler.*; |
||||||
|
|
||||||
|
public class MTHttpHandler extends AbstractHttpHandlerProvider { |
||||||
|
HttpHandler[] actions = new HttpHandler[]{ |
||||||
|
new ALLMtloginCallback1Handler(), |
||||||
|
}; |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpHandler[] registerHandlers() { |
||||||
|
return actions; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
package com.fr.plugin.http; |
||||||
|
|
||||||
|
import com.fr.decision.fun.impl.AbstractURLAliasProvider; |
||||||
|
import com.fr.decision.webservice.url.alias.URLAlias; |
||||||
|
import com.fr.decision.webservice.url.alias.URLAliasFactory; |
||||||
|
|
||||||
|
public class MTUrlAliasProvider extends AbstractURLAliasProvider { |
||||||
|
@Override |
||||||
|
public URLAlias[] registerAlias() { |
||||||
|
return new URLAlias[]{ |
||||||
|
URLAliasFactory.createPluginAlias("/mtlogin", "/mtloginCallback", true), |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,126 @@ |
|||||||
|
package com.fr.plugin.http.handler; |
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fanruan.api.net.http.HttpKit; |
||||||
|
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.json.JSONObject; |
||||||
|
import com.fr.plugin.MTConfig; |
||||||
|
import com.fr.plugin.SsoHttpUtil; |
||||||
|
import com.fr.plugin.TicketUtil; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.third.springframework.web.bind.annotation.RequestMethod; |
||||||
|
import com.fr.web.utils.WebUtils; |
||||||
|
import org.swingexplorer.Log; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class ALLMtloginCallback1Handler extends BaseHttpHandler { |
||||||
|
@Override |
||||||
|
public RequestMethod getMethod() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getPath() { |
||||||
|
return "/mtloginCallback" ; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isPublic() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
String code = req.getParameter("id-token"); |
||||||
|
String url = req.getParameter("callback"); |
||||||
|
// String accessToken = getAccessToken(code);
|
||||||
|
// String userInfo = getUserInfo(accessToken);
|
||||||
|
String userInfo = loginByTk(code); |
||||||
|
UserService userService = UserService.getInstance(); |
||||||
|
User user = userService.getUserByUserName(userInfo); |
||||||
|
if (user == null) { |
||||||
|
String notExistUrl = MTConfig.getInstance().getNotExistUrl(); |
||||||
|
sendRedirect(res, notExistUrl); |
||||||
|
return; |
||||||
|
} |
||||||
|
if (!user.isEnable()) { |
||||||
|
String notExistUrl = MTConfig.getInstance().getNotExistUrl(); |
||||||
|
sendRedirect(res, notExistUrl); |
||||||
|
return; |
||||||
|
} |
||||||
|
login(req,res,userInfo); |
||||||
|
LogKit.info("login success, userName=" + userInfo); |
||||||
|
if (StringUtils.isBlank(url)) { |
||||||
|
url = MTConfig.getInstance().getFrUrl(); |
||||||
|
} |
||||||
|
sendRedirect(res, url); |
||||||
|
} |
||||||
|
private void sendRedirect(HttpServletResponse res, String url) { |
||||||
|
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); |
||||||
|
res.setHeader("Location", url); |
||||||
|
} |
||||||
|
|
||||||
|
private void login(HttpServletRequest req, HttpServletResponse res, String username) { |
||||||
|
String token = null; |
||||||
|
try { |
||||||
|
token = LoginService.getInstance().login(req, res, username); |
||||||
|
req.setAttribute("fine_auth_token", token); |
||||||
|
} catch (Exception e) { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String loginByTk(String idToken) throws Exception { |
||||||
|
//检查idToken,并返回分割后的数组 header + payload + signature
|
||||||
|
LogKit.info("idToken:{}",idToken); |
||||||
|
String[] strs = TicketUtil.checkTicketFormat(idToken); |
||||||
|
|
||||||
|
//step1 是否过期
|
||||||
|
List<String> header = TicketUtil.splitBrackets(strs[0]); |
||||||
|
long expire = Long.valueOf(header.get(4)); |
||||||
|
if (expire < System.currentTimeMillis()) { |
||||||
|
throw new Exception("ticket is expire"); |
||||||
|
} |
||||||
|
|
||||||
|
if(StringUtils.isBlank( SsoHttpUtil.getPublicKey())){ |
||||||
|
SsoHttpUtil.initPublicKey(); |
||||||
|
if(StringUtils.isBlank( SsoHttpUtil.getPublicKey())){ |
||||||
|
throw new Exception("public key is null"); |
||||||
|
} |
||||||
|
} |
||||||
|
//step 2 验证签名
|
||||||
|
if (!TicketUtil.validateTicket(strs[0] + "*" + strs[1], strs[2], SsoHttpUtil.getPublicKey())) { |
||||||
|
throw new IllegalArgumentException("ticket is illegal"); |
||||||
|
} |
||||||
|
|
||||||
|
//step3 获取用户信息
|
||||||
|
List<String> payload = TicketUtil.splitBrackets(strs[1]); |
||||||
|
List<String> user = TicketUtil.splitBrackets(payload.get(1)); |
||||||
|
Long uid = Long.parseLong(user.get(0)); |
||||||
|
String mis = user.get(1); |
||||||
|
LogKit.info("成功获取:----- uid:{},mis:{}", uid, mis); |
||||||
|
return mis; |
||||||
|
} |
||||||
|
|
||||||
|
private String getAccessToken(String code) throws IOException { |
||||||
|
MTConfig mtConfig = MTConfig.getInstance(); |
||||||
|
String apiUrl = mtConfig.getApiUrl(); |
||||||
|
String url = String.format("%s/oauth2.0/access-token", apiUrl); |
||||||
|
Map<String, String> params = new HashMap<>(); |
||||||
|
params.put("code", code); |
||||||
|
params.put("t", System.currentTimeMillis() + ""); |
||||||
|
Map<String, String> headers = SsoHttpUtil.getSignedHeaders("GET", url, mtConfig.getClientId(), mtConfig.getClientSecret()); |
||||||
|
String resp = HttpKit.get(url, params, headers); |
||||||
|
LogKit.info("====getAccessToken url:{} params:{} header:{} resp:{}", url, params, headers, resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
return entries.getJSONObject("data").getString("accessToken"); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue