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