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