pioneer
2 years ago
commit
81169dd7af
14 changed files with 447 additions and 0 deletions
@ -0,0 +1,6 @@ |
|||||||
|
# open-JSD-9713 |
||||||
|
|
||||||
|
JSD-9713 单点登录认证\ |
||||||
|
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||||
|
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||||
|
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,22 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
<plugin> |
||||||
|
<id>com.eco.plugin.xxx.uasslogin</id> |
||||||
|
<name><![CDATA[登录验证]]></name> |
||||||
|
<active>yes</active> |
||||||
|
<version>1.0.0</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: 9713--> |
||||||
|
<create-day>2022-4-1 13:17:34</create-day> |
||||||
|
<extra-decision> |
||||||
|
<GlobalRequestFilterProvider class="com.fr.plugin.filter.UASSLOGIN1Filter"/> |
||||||
|
</extra-decision> |
||||||
|
<lifecycle-monitor class="com.fr.plugin.UASSLOGINLifeCycleMonitor"/> |
||||||
|
<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,47 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.config.*; |
||||||
|
import com.fr.config.holder.Conf; |
||||||
|
import com.fr.config.holder.factory.Holders; |
||||||
|
|
||||||
|
@Visualization(category = "登录验证配置") |
||||||
|
public class UASSLOGINConfig extends DefaultConfiguration { |
||||||
|
|
||||||
|
private static volatile UASSLOGINConfig config = null; |
||||||
|
|
||||||
|
public static UASSLOGINConfig getInstance() { |
||||||
|
if (config == null) { |
||||||
|
config = ConfigContext.getConfigInstance(UASSLOGINConfig.class); |
||||||
|
} |
||||||
|
return config; |
||||||
|
} |
||||||
|
@Identifier(value = "apiUrl", name = "接口地址前缀", description = "描述", status = Status.SHOW) |
||||||
|
private Conf<String> apiUrl = Holders.simple("http://*.*.*.*:88"); |
||||||
|
@Identifier(value = "secret", name = "认证秘钥", description = "在配置main_config.properties的des3privacykey内容", status = Status.SHOW) |
||||||
|
private Conf<String> secret = Holders.simple(""); |
||||||
|
|
||||||
|
public String getApiUrl() { |
||||||
|
return apiUrl.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setApiUrl( String apiUrl) { |
||||||
|
this.apiUrl .set(apiUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public String getSecret() { |
||||||
|
return secret.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSecret( String secret) { |
||||||
|
this.secret.set(secret); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() throws CloneNotSupportedException { |
||||||
|
UASSLOGINConfig cloned = (UASSLOGINConfig) super.clone(); |
||||||
|
cloned.apiUrl = (Conf<String>) this.apiUrl.clone(); |
||||||
|
cloned.secret = (Conf<String>) this.secret.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 UASSLOGINLifeCycleMonitor extends AbstractPluginLifecycleMonitor { |
||||||
|
@Override |
||||||
|
public void afterRun(PluginContext pluginContext) { |
||||||
|
UASSLOGINConfig.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void beforeStop(PluginContext pluginContext) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,65 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fanruan.api.net.http.HttpKit; |
||||||
|
import com.fr.decision.authorize.impl.AbstractPassport; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.plugin.tools.ToolDES; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class USAAPassport extends AbstractPassport { |
||||||
|
@Override |
||||||
|
public boolean checkTicket(String username, String inputPassword, String savedPassword, String hashPassword) { |
||||||
|
boolean checkTicket = false; |
||||||
|
String st = null; |
||||||
|
try { |
||||||
|
st = getSt(username, inputPassword); |
||||||
|
if (StringUtils.isBlank(st)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
String un = getUserInfo(st); |
||||||
|
if (StringUtils.equals(un,username)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
LogKit.error("认证失败:",e); |
||||||
|
return false; |
||||||
|
} |
||||||
|
return checkTicket; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String markType() { |
||||||
|
return "USAA"; |
||||||
|
} |
||||||
|
|
||||||
|
private String getSt(String name, String pwd) throws IOException { |
||||||
|
String encrypt = ToolDES.encrypt(pwd); |
||||||
|
UASSLOGINConfig uassloginConfig = UASSLOGINConfig.getInstance(); |
||||||
|
String url = String.format("%s/ssouas/ssologincheck?loginname=%s&password=%s", uassloginConfig.getApiUrl(), name, encrypt); |
||||||
|
String resp = HttpKit.get(url); |
||||||
|
LogKit.info("访问:{} 获取st 响应:{}", url, resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
String err = entries.getString("err"); |
||||||
|
if (StringUtils.equals(err, "1")) { |
||||||
|
String st = entries.getString("st"); |
||||||
|
return st; |
||||||
|
} |
||||||
|
return resp; |
||||||
|
} |
||||||
|
private String getUserInfo(String st) throws IOException { |
||||||
|
UASSLOGINConfig uassloginConfig = UASSLOGINConfig.getInstance(); |
||||||
|
String userInfoUrl = String.format("%s/ssouas/loginuass?st=%s", uassloginConfig.getApiUrl(), st); |
||||||
|
String resp = HttpKit.get(userInfoUrl); |
||||||
|
LogKit.info("访问:{} 获取userInfo 响应:{}", userInfoUrl, resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
String err = entries.getString("err"); |
||||||
|
if (StringUtils.equals(err, "1")) { |
||||||
|
String userName = entries.getString("userName"); |
||||||
|
return userName; |
||||||
|
} |
||||||
|
return ""; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
package com.fr.plugin.filter; |
||||||
|
|
||||||
|
import com.fr.base.ServerConfig; |
||||||
|
import com.fr.data.NetworkHelper; |
||||||
|
import com.fr.decision.authority.base.constant.type.operation.ManualOperationType; |
||||||
|
import com.fr.decision.authority.base.constant.type.operation.SyncOperationType; |
||||||
|
import com.fr.decision.config.FSConfig; |
||||||
|
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.USAAPassport; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.web.Device; |
||||||
|
import com.fr.web.utils.WebUtils; |
||||||
|
import com.fr.plugin.context.PluginContexts; |
||||||
|
|
||||||
|
import javax.servlet.FilterChain; |
||||||
|
import javax.servlet.FilterConfig; |
||||||
|
import javax.servlet.ServletException; |
||||||
|
import javax.servlet.http.Cookie; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class UASSLOGIN1Filter extends AbstractGlobalRequestFilterProvider { |
||||||
|
@Override |
||||||
|
public String filterName() { |
||||||
|
return "UASSLOGIN1Filter"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String[] urlPatterns() { |
||||||
|
return new String[]{ |
||||||
|
"/decision/login", |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void init(FilterConfig filterConfig) { |
||||||
|
super.init(filterConfig); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) { |
||||||
|
try { |
||||||
|
if (PluginContexts.currentContext().isAvailable()) { |
||||||
|
doLoginCheck(req, res, filterChain); |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "插件名:《xxxxx》插件id:com.eco.plugin.xxx.uasslogin 插件授权过期 请联系销售"); |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void doLoginCheck(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws ServletException, IOException { |
||||||
|
if (StringUtils.equals("POST", req.getMethod())) { |
||||||
|
USAAPassport usaaPassport = new USAAPassport(); |
||||||
|
FSConfig.getInstance().setPassport(ManualOperationType.KEY, usaaPassport); |
||||||
|
usaaPassport = new USAAPassport(); |
||||||
|
FSConfig.getInstance().setPassport(SyncOperationType.KEY, usaaPassport); |
||||||
|
filterChain.doFilter(req, res); |
||||||
|
} else { |
||||||
|
filterChain.doFilter(req, res); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
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 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,53 @@ |
|||||||
|
package com.fr.plugin.tools; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import javax.crypto.*; |
||||||
|
import javax.crypto.spec.DESKeySpec; |
||||||
|
|
||||||
|
import sun.misc.BASE64Encoder; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.security.InvalidKeyException; |
||||||
|
import java.security.NoSuchAlgorithmException; |
||||||
|
import java.security.SecureRandom; |
||||||
|
import java.security.spec.InvalidKeySpecException; |
||||||
|
|
||||||
|
public class EncryptTool |
||||||
|
{ |
||||||
|
private byte[] encryptString(byte[] data, byte[] rawKeyData) |
||||||
|
throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, IllegalStateException |
||||||
|
{ |
||||||
|
SecureRandom sr = new SecureRandom(); |
||||||
|
DESKeySpec dks = new DESKeySpec(rawKeyData); |
||||||
|
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); |
||||||
|
SecretKey key = keyFactory.generateSecret(dks); |
||||||
|
Cipher cipher = Cipher.getInstance("DES"); |
||||||
|
cipher.init(1, key, sr); |
||||||
|
byte[] encryptedData = cipher.doFinal(data); |
||||||
|
return encryptedData; |
||||||
|
} |
||||||
|
|
||||||
|
public String encryptString(String rawStr, String rawKey) |
||||||
|
throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, IllegalStateException, IOException |
||||||
|
{ |
||||||
|
byte[] rawStrData = rawStr.getBytes(); |
||||||
|
byte[] rawKeyData = rawKey.getBytes(); |
||||||
|
byte[] encryptData = encryptString(rawStrData, rawKeyData); |
||||||
|
String encryptStr = new BASE64Encoder().encode(encryptData); |
||||||
|
byte[] c = encryptStr.getBytes(); |
||||||
|
StringBuffer strBuf = new StringBuffer(); |
||||||
|
for (int i = 0; i < c.length; ++i) |
||||||
|
{ |
||||||
|
int t = c[i]; |
||||||
|
String str = Integer.toHexString(t); |
||||||
|
if (str.length() == 1) |
||||||
|
strBuf.append(0); |
||||||
|
strBuf.append(Integer.toHexString(t)); |
||||||
|
} |
||||||
|
return strBuf.toString(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,120 @@ |
|||||||
|
package com.fr.plugin.tools; |
||||||
|
|
||||||
|
|
||||||
|
import com.fanruan.api.log.LogKit; |
||||||
|
import com.fr.plugin.UASSLOGINConfig; |
||||||
|
|
||||||
|
import javax.crypto.Cipher; |
||||||
|
import javax.crypto.SecretKey; |
||||||
|
import javax.crypto.spec.SecretKeySpec; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
|
||||||
|
|
||||||
|
public class ToolDES { |
||||||
|
//public final static String PRIVACY_KEY = WebContant.DES_PRIVACYKEY;
|
||||||
|
public final static String PRIVACY_KEY; |
||||||
|
private static final String Algorithm = "DESede"; // 定义
|
||||||
|
private static final String encoding = "UTF8"; |
||||||
|
// 密钥
|
||||||
|
private static byte[] keyBytes = null; |
||||||
|
|
||||||
|
static { |
||||||
|
// String temp = "chinamobileimpgwandother" ;
|
||||||
|
PRIVACY_KEY = UASSLOGINConfig.getInstance().getSecret(); |
||||||
|
keyBytes = UASSLOGINConfig.getInstance().getSecret().getBytes(StandardCharsets.UTF_8); |
||||||
|
} |
||||||
|
|
||||||
|
// keybyte为加密密钥,长度为24字节
|
||||||
|
// src为被加密的数据缓冲区(源)
|
||||||
|
public static byte[] encryptMode(byte[] keybyte, byte[] src) { |
||||||
|
try { |
||||||
|
// 生成密钥
|
||||||
|
SecretKey deskey = new SecretKeySpec(keybyte, Algorithm); |
||||||
|
|
||||||
|
// 加密
|
||||||
|
Cipher c1 = Cipher.getInstance(Algorithm); |
||||||
|
c1.init(Cipher.ENCRYPT_MODE, deskey); |
||||||
|
return c1.doFinal(src); |
||||||
|
} catch (java.lang.Exception e) { |
||||||
|
LogKit.error("", e); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
// keybyte为加密密钥,长度为24字节
|
||||||
|
// src为加密后的缓冲区
|
||||||
|
public static byte[] decryptMode(byte[] keybyte, byte[] src) throws Exception { |
||||||
|
|
||||||
|
// 生成密钥
|
||||||
|
SecretKey deskey = new SecretKeySpec(keybyte, Algorithm); |
||||||
|
|
||||||
|
// 解密
|
||||||
|
Cipher c1 = Cipher.getInstance(Algorithm); |
||||||
|
c1.init(Cipher.DECRYPT_MODE, deskey); |
||||||
|
return c1.doFinal(src); |
||||||
|
} |
||||||
|
|
||||||
|
// 转换成十六进制字符串
|
||||||
|
private static String byte2hexString(byte[] bytes) { |
||||||
|
StringBuffer buf = new StringBuffer(bytes.length * 2); |
||||||
|
for (int i = 0; i < bytes.length; i++) { |
||||||
|
if (((int) bytes[i] & 0xff) < 0x10) { |
||||||
|
buf.append("0"); |
||||||
|
} |
||||||
|
buf.append(Long.toString((int) bytes[i] & 0xff, 16)); |
||||||
|
} |
||||||
|
return buf.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
// 将十六进制字符串byte数组
|
||||||
|
private static byte[] hexString2byte(String hexString) { |
||||||
|
if (hexString == null || hexString.length() % 2 != 0) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
byte[] hanzi = new byte[hexString.length() / 2]; |
||||||
|
for (int i = 0; i < hexString.length(); i += 2) { |
||||||
|
hanzi[i / 2] = (byte) (Integer.parseInt(hexString.substring(i, i + 2), 16) & 0xff); |
||||||
|
} |
||||||
|
return hanzi; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密字符串 |
||||||
|
* |
||||||
|
* @param src 源字符串 |
||||||
|
* @return 加密后的字符串 |
||||||
|
*/ |
||||||
|
public static String encrypt(String src) { |
||||||
|
String key = PRIVACY_KEY; |
||||||
|
String result = null; |
||||||
|
if (src == null) { |
||||||
|
return result; |
||||||
|
} |
||||||
|
try { |
||||||
|
EncryptTool ent = new EncryptTool(); |
||||||
|
// 加密字符串
|
||||||
|
LogKit.debug("加密字符串:" + ent); |
||||||
|
result = ent.encryptString(src, key); |
||||||
|
|
||||||
|
} catch (Exception e) { |
||||||
|
LogKit.error("Exception occurred while encrypting [ " + src + " ] ,key[" + key + "],", e); |
||||||
|
return null; |
||||||
|
} |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
public static byte[] getKeyBytes(String key) { |
||||||
|
if (key != null && "".equals(key)) { |
||||||
|
key = PRIVACY_KEY; |
||||||
|
} |
||||||
|
if (key != null) { |
||||||
|
keyBytes = key.getBytes(); |
||||||
|
} |
||||||
|
return keyBytes; |
||||||
|
} |
||||||
|
|
||||||
|
} |
After Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in new issue