commit
3bbd60c3f0
24 changed files with 1381 additions and 0 deletions
@ -0,0 +1,7 @@ |
|||||||
|
|
||||||
|
# open-JSD-9826 |
||||||
|
|
||||||
|
JSD-9826 BI与客户系统集成,实现4A单点登录认证\ |
||||||
|
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||||
|
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||||
|
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 |
@ -0,0 +1,121 @@ |
|||||||
|
|
||||||
|
apply plugin: 'java' |
||||||
|
|
||||||
|
|
||||||
|
ext { |
||||||
|
/** |
||||||
|
* 项目中依赖的jar的路径 |
||||||
|
* 1.如果依赖的jar需要打包到zip中,放置在lib根目录下 |
||||||
|
* 2.如果依赖的jar仅仅是编译时需要,防止在lib下子目录下即可 |
||||||
|
*/ |
||||||
|
libPath = "$projectDir/../webroot/WEB-INF/lib" |
||||||
|
|
||||||
|
/** |
||||||
|
* 是否对插件的class进行加密保护,防止反编译 |
||||||
|
*/ |
||||||
|
guard = false |
||||||
|
|
||||||
|
def pluginInfo = getPluginInfo() |
||||||
|
pluginPre = "fine-plugin" |
||||||
|
pluginName = pluginInfo.id |
||||||
|
pluginVersion = pluginInfo.version |
||||||
|
|
||||||
|
outputPath = "$projectDir/../webroot/WEB-INF/plugins/plugin-" + pluginName + "-1.0/classes" |
||||||
|
} |
||||||
|
|
||||||
|
group = 'com.fr.plugin' |
||||||
|
version = '10.0' |
||||||
|
sourceCompatibility = '8' |
||||||
|
|
||||||
|
sourceSets { |
||||||
|
main { |
||||||
|
java.outputDir = file(outputPath) |
||||||
|
output.resourcesDir = file(outputPath) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ant.importBuild("encrypt.xml") |
||||||
|
//定义ant变量 |
||||||
|
ant.projectDir = projectDir |
||||||
|
ant.references["compile.classpath"] = ant.path { |
||||||
|
fileset(dir: libPath, includes: '**/*.jar') |
||||||
|
fileset(dir: ".",includes:"**/*.jar" ) |
||||||
|
} |
||||||
|
|
||||||
|
classes.dependsOn('clean') |
||||||
|
|
||||||
|
task copyFiles(type: Copy,dependsOn: 'classes'){ |
||||||
|
from outputPath |
||||||
|
into "$projectDir/classes" |
||||||
|
} |
||||||
|
|
||||||
|
task preJar(type:Copy,dependsOn: guard ? 'compile_encrypt_javas' : 'compile_plain_javas'){ |
||||||
|
from "$projectDir/classes" |
||||||
|
into "$projectDir/transform-classes" |
||||||
|
include "**/*.*" |
||||||
|
} |
||||||
|
jar.dependsOn("preJar") |
||||||
|
|
||||||
|
task makeJar(type: Jar,dependsOn: preJar){ |
||||||
|
from fileTree(dir: "$projectDir/transform-classes") |
||||||
|
baseName pluginPre |
||||||
|
appendix pluginName |
||||||
|
version pluginVersion |
||||||
|
destinationDir = file("$buildDir/libs") |
||||||
|
|
||||||
|
doLast(){ |
||||||
|
delete file("$projectDir/classes") |
||||||
|
delete file("$projectDir/transform-classes") |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
task copyFile(type: Copy,dependsOn: ["makeJar"]){ |
||||||
|
from "$buildDir/libs" |
||||||
|
from("$projectDir/lib") { |
||||||
|
include "*.jar" |
||||||
|
} |
||||||
|
from "$projectDir/plugin.xml" |
||||||
|
into file("$buildDir/temp/plugin") |
||||||
|
} |
||||||
|
|
||||||
|
task zip(type:Zip,dependsOn:["copyFile"]){ |
||||||
|
from "$buildDir/temp/plugin" |
||||||
|
destinationDir file("$buildDir/install") |
||||||
|
baseName pluginPre |
||||||
|
appendix pluginName |
||||||
|
version pluginVersion |
||||||
|
} |
||||||
|
|
||||||
|
//控制build时包含哪些文件,排除哪些文件 |
||||||
|
processResources { |
||||||
|
// exclude everything |
||||||
|
// 用*.css没效果 |
||||||
|
// exclude '**/*.css' |
||||||
|
// except this file |
||||||
|
// include 'xx.xml' |
||||||
|
} |
||||||
|
|
||||||
|
/*读取plugin.xml中的version*/ |
||||||
|
def getPluginInfo(){ |
||||||
|
def xmlFile = file("plugin.xml") |
||||||
|
if (!xmlFile.exists()) { |
||||||
|
return ["id":"none", "version":"1.0.0"] |
||||||
|
} |
||||||
|
def plugin = new XmlParser().parse(xmlFile) |
||||||
|
def version = plugin.version[0].text() |
||||||
|
def id = plugin.id[0].text() |
||||||
|
return ["id":id,"version":version] |
||||||
|
} |
||||||
|
|
||||||
|
repositories { |
||||||
|
mavenLocal() |
||||||
|
maven { |
||||||
|
url = uri('http://mvn.finedevelop.com/repository/maven-public/') |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
dependencies { |
||||||
|
//使用本地jar |
||||||
|
implementation fileTree(dir: 'lib', include: ['**/*.jar']) |
||||||
|
implementation fileTree(dir: libPath, include: ['**/*.jar']) |
||||||
|
} |
Binary file not shown.
@ -0,0 +1,13 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
<project> |
||||||
|
<target name="compile_encrypt_javas" depends="copyFiles"> |
||||||
|
<echo message="加密文件"/> |
||||||
|
<echo message="${projectDir}"/> |
||||||
|
<taskdef name="pretreatment" classname="com.fr.plugin.pack.PluginPretreatmentTask"> |
||||||
|
<classpath refid="compile.classpath"/> |
||||||
|
</taskdef> |
||||||
|
<pretreatment baseDir="${projectDir}"/> |
||||||
|
</target> |
||||||
|
<target name="compile_plain_javas" depends="copyFiles"> |
||||||
|
</target> |
||||||
|
</project> |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,24 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
<plugin> |
||||||
|
<id>com.fr.plugin.foauth.login</id> |
||||||
|
<name><![CDATA[4a单点登录插件]]></name> |
||||||
|
<active>yes</active> |
||||||
|
<version>1.0.1</version> |
||||||
|
<env-version>10.0</env-version> |
||||||
|
<jartime>2020-07-31</jartime> |
||||||
|
<vendor>fr.open</vendor> |
||||||
|
<description> |
||||||
|
1.0.1- 新增登录成功后重定向功能 |
||||||
|
</description> |
||||||
|
|
||||||
|
<lifecycle-monitor class="com.fr.plugin.FLLifeCycleMonitor"/> |
||||||
|
<extra-decision> |
||||||
|
<!-- <PassportProvider class="com.fr.plugin.FLPassportProvider"/>--> |
||||||
|
<!-- <WebResourceProvider class="com.fr.plugin.LogindJSHandler"/>--> |
||||||
|
<!-- 长连接 --> |
||||||
|
<HttpHandlerProvider class="com.fr.plugin.FLHttpHander"/> |
||||||
|
<!-- 短连接 --> |
||||||
|
<URLAliasProvider class="com.fr.plugin.FLURLAliasBridge"/> |
||||||
|
</extra-decision> |
||||||
|
<function-recorder class="com.fr.plugin.FLURLAliasBridge"/> |
||||||
|
</plugin> |
@ -0,0 +1,196 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fanruan.api.data.ConnectionKit; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.log.FineLoggerProvider; |
||||||
|
|
||||||
|
import java.math.BigDecimal; |
||||||
|
import java.sql.*; |
||||||
|
import java.util.*; |
||||||
|
|
||||||
|
public class DBUtils { |
||||||
|
String db_name = ""; |
||||||
|
|
||||||
|
private static FineLoggerProvider logger = FineLoggerFactory.getLogger(); |
||||||
|
|
||||||
|
public DBUtils(String db_name) { |
||||||
|
this.db_name = db_name; |
||||||
|
} |
||||||
|
|
||||||
|
public DBUtils() { |
||||||
|
this.db_name = "FRDW"; |
||||||
|
} |
||||||
|
|
||||||
|
public com.fr.data.impl.Connection getDbConnect() { |
||||||
|
return ConnectionKit.getConnection(db_name); |
||||||
|
} |
||||||
|
|
||||||
|
public List<Map<String, Object>> select(String sql, Object... params) { |
||||||
|
logger.info("query data by sql:" + sql + Arrays.toString(params)); |
||||||
|
try { |
||||||
|
com.fr.data.impl.Connection dbConnect = getDbConnect(); |
||||||
|
Connection con = dbConnect.createConnection(); |
||||||
|
PreparedStatement preparedStatement = con.prepareStatement(sql); |
||||||
|
setParams(preparedStatement, params); |
||||||
|
ResultSet rs = preparedStatement.executeQuery(sql); |
||||||
|
// 获得记录的详细信息,然后获得总列数
|
||||||
|
ResultSetMetaData resMetaData = rs.getMetaData(); |
||||||
|
int colNum = resMetaData.getColumnCount(); |
||||||
|
// 用对象保存数据
|
||||||
|
String name = ""; |
||||||
|
String value = ""; |
||||||
|
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); |
||||||
|
while (rs.next()) { |
||||||
|
Map<String, Object> cells = new HashMap<String, Object>(); |
||||||
|
for (int i = 0; i < colNum; i++) { |
||||||
|
name = resMetaData.getColumnLabel(i); |
||||||
|
if (cells.get(name) != null) { |
||||||
|
name = resMetaData.getColumnLabel(i); |
||||||
|
} |
||||||
|
if (rs.getObject(i) != null && resMetaData.getColumnTypeName(i).equals("DATETIME") || resMetaData.getColumnTypeName(i).equals("TIMESTAMP")) { |
||||||
|
value = rs.getObject(i).toString(); |
||||||
|
cells.put(name, value.substring(0, value.length() - 2)); |
||||||
|
} else { |
||||||
|
cells.put(name, rs.getString(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
list.add(cells); |
||||||
|
} |
||||||
|
// 释放数据库资源
|
||||||
|
rs.close(); |
||||||
|
preparedStatement.close(); |
||||||
|
con.close(); |
||||||
|
return list; |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public int exec(String sql, String date) throws Exception { |
||||||
|
logger.info("query data by sql:{} 时间:{}", sql, date); |
||||||
|
Connection con = null; |
||||||
|
CallableStatement call = null; |
||||||
|
try { |
||||||
|
com.fr.data.impl.Connection dbConnect = getDbConnect(); |
||||||
|
con = dbConnect.createConnection(); |
||||||
|
call = con.prepareCall(sql); |
||||||
|
call.registerOutParameter(1, Types.INTEGER); |
||||||
|
call.execute(); |
||||||
|
Integer ret = call.getInt(1); |
||||||
|
return ret; |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
throw e; |
||||||
|
} finally { |
||||||
|
if (call != null) { |
||||||
|
call.close(); |
||||||
|
} |
||||||
|
if (con != null) { |
||||||
|
con.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, Object> findOneRow(String sql, Object... params) { |
||||||
|
List<Map<String, Object>> select = select(sql, params); |
||||||
|
if (select != null) { |
||||||
|
if (!select.isEmpty()) { |
||||||
|
return select.get(0); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean checkExist(String sql, Object... params) throws Exception { |
||||||
|
Connection connection = getDbConnect().createConnection(); |
||||||
|
PreparedStatement pstmt = connection.prepareStatement(sql); |
||||||
|
setParams(pstmt, params); |
||||||
|
try { |
||||||
|
ResultSet resultSet = pstmt.executeQuery(); |
||||||
|
if (resultSet.next()) { |
||||||
|
return resultSet.getInt(1) > 0; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} finally { |
||||||
|
connection.close(); |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
private void setParams(PreparedStatement pstmt, Object... params) throws SQLException { |
||||||
|
if (params.length > 0) { |
||||||
|
int length = params.length; |
||||||
|
for (int i = 1; i <= length; i++) { |
||||||
|
pstmt.setObject(i, params[i - 1]); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int exSqlUpdate(String sql, Object... params) throws Exception { |
||||||
|
logger.info("update data by sql:" + sql + " params " + Arrays.toString(params)); |
||||||
|
PreparedStatement pstmt = null; |
||||||
|
Connection connection = null; |
||||||
|
try { |
||||||
|
com.fr.data.impl.Connection dbConnect = getDbConnect(); |
||||||
|
connection = dbConnect.createConnection(); |
||||||
|
pstmt = connection.prepareStatement(sql); |
||||||
|
setParams(pstmt, params); |
||||||
|
int i = pstmt.executeUpdate(); |
||||||
|
return i; |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("执行更新SQL报错: sql:{}", e, sql); |
||||||
|
} finally { |
||||||
|
if (pstmt != null) { |
||||||
|
pstmt.close(); |
||||||
|
} |
||||||
|
if (connection != null) { |
||||||
|
connection.close(); |
||||||
|
} |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 取查询结果集字段 |
||||||
|
* |
||||||
|
* @param sql |
||||||
|
* @param params |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public List<Map<String, String>> exQuery(String sql, Object... params) throws Exception { |
||||||
|
logger.info("query data by sql:" + sql + " params " + Arrays.toString(params)); |
||||||
|
com.fr.data.impl.Connection dbConnect = getDbConnect(); |
||||||
|
Connection connection = dbConnect.createConnection(); |
||||||
|
PreparedStatement pstmt = connection.prepareStatement(sql); |
||||||
|
setParams(pstmt, params); |
||||||
|
ResultSet resultSet = pstmt.executeQuery(); |
||||||
|
ResultSetMetaData resMetaData = resultSet.getMetaData(); |
||||||
|
int columnCount = resMetaData.getColumnCount(); |
||||||
|
List<Map<String, String>> arrs = new ArrayList<Map<String, String>>(); |
||||||
|
while (resultSet.next()) { |
||||||
|
String name; |
||||||
|
String value; |
||||||
|
Map<String, String> one = new HashMap<String, String>(); |
||||||
|
for (int i = 1; i <= columnCount; i++) { |
||||||
|
name = resMetaData.getColumnLabel(i); |
||||||
|
if (one.get(name) != null) { |
||||||
|
name = resMetaData.getColumnLabel(i); |
||||||
|
} |
||||||
|
if (resultSet.getObject(i) != null && resMetaData.getColumnTypeName(i).equals("DATETIME") || resMetaData.getColumnTypeName(i).equals("TIMESTAMP")) { |
||||||
|
value = resultSet.getObject(i).toString(); |
||||||
|
one.put(name, value.substring(0, value.length() - 2)); |
||||||
|
} else { |
||||||
|
one.put(name, resultSet.getString(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
arrs.add(one); |
||||||
|
} |
||||||
|
pstmt.close(); |
||||||
|
connection.close(); |
||||||
|
return arrs; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,108 @@ |
|||||||
|
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 FLConfig extends DefaultConfiguration { |
||||||
|
|
||||||
|
private static volatile FLConfig config = null; |
||||||
|
@Identifier(value = "valAddr", name = "接口地址", description = "接口地址", status = Status.SHOW) |
||||||
|
private Conf<String> valAddr = Holders.simple(""); |
||||||
|
|
||||||
|
@Identifier(value = "loginClientSecret", name = "secret", description = "Secret", status = Status.SHOW) |
||||||
|
private Conf<String> loginClientSecret = Holders.simple(""); |
||||||
|
@Identifier(value = "threeDdKey", name = "3dsKey", description = "3dsKey", status = Status.SHOW) |
||||||
|
private Conf<String> threeDdKey = Holders.simple("xxx"); |
||||||
|
@Identifier(value = "frUrl", name = "当前fr系统地址", description = "", status = Status.SHOW) |
||||||
|
private Conf<String> frUrl = Holders.simple("http://localhost:8075/webroot/decision"); |
||||||
|
|
||||||
|
@Identifier(value = "method", name = "单点请求方式", description = "单点请求方式", status = Status.SHOW) |
||||||
|
private Conf<String> method = Holders.simple(""); |
||||||
|
|
||||||
|
public static FLConfig getInstance() { |
||||||
|
if (config == null) { |
||||||
|
config = ConfigContext.getConfigInstance(FLConfig.class); |
||||||
|
} |
||||||
|
return config; |
||||||
|
} |
||||||
|
/* |
||||||
|
public String getService() { |
||||||
|
return service.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setService(String service) { |
||||||
|
this.service.set(service); |
||||||
|
}*/ |
||||||
|
|
||||||
|
public String getFrUrl() { |
||||||
|
return frUrl.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setFrUrl(String frUrl) { |
||||||
|
this.frUrl.set(frUrl); |
||||||
|
} |
||||||
|
|
||||||
|
public String getLoginClientSecret() { |
||||||
|
return loginClientSecret.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getThreeDdKey() { |
||||||
|
return threeDdKey.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setThreeDdKey(String threeDdKey) { |
||||||
|
this.threeDdKey.set(threeDdKey); |
||||||
|
} |
||||||
|
|
||||||
|
public String getMethod() { |
||||||
|
return method.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setMethod(String method) { |
||||||
|
this.method.set(method); |
||||||
|
} |
||||||
|
|
||||||
|
public void setLoginClientSecret(String loginClientSecret) { |
||||||
|
this.loginClientSecret.set(loginClientSecret); |
||||||
|
} |
||||||
|
|
||||||
|
/* public String getAppid() { |
||||||
|
return appid.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setAppid(String appid) { |
||||||
|
this.appid.set(appid); |
||||||
|
}*/ |
||||||
|
|
||||||
|
public String getValAddr() { |
||||||
|
return valAddr.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setValAddr(String valAddr) { |
||||||
|
this.valAddr.set(valAddr); |
||||||
|
} |
||||||
|
|
||||||
|
/* public String getSysCode() { |
||||||
|
return syscode.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSyscode(String syscode) { |
||||||
|
this.syscode.set(syscode); |
||||||
|
}*/ |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() throws CloneNotSupportedException { |
||||||
|
FLConfig cloned = (FLConfig) super.clone(); |
||||||
|
cloned.valAddr = (Conf<String>) valAddr.clone(); |
||||||
|
// cloned.service = (Conf<String>) service.clone();
|
||||||
|
// cloned.appid = (Conf<String>) appid.clone();
|
||||||
|
cloned.loginClientSecret = (Conf<String>) loginClientSecret.clone(); |
||||||
|
cloned.frUrl = (Conf<String>) frUrl.clone(); |
||||||
|
// cloned.syscode = (Conf<String>) syscode.clone();
|
||||||
|
return cloned; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.decision.fun.HttpHandler; |
||||||
|
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; |
||||||
|
import com.fr.plugin.handler.FLLoginCallBackHander; |
||||||
|
|
||||||
|
public class FLHttpHander extends AbstractHttpHandlerProvider { |
||||||
|
|
||||||
|
private HttpHandler[] actions = new HttpHandler[]{new FLLoginCallBackHander()}; |
||||||
|
|
||||||
|
@Override |
||||||
|
public HttpHandler[] registerHandlers() { |
||||||
|
return actions; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.plugin.context.PluginContext; |
||||||
|
import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; |
||||||
|
|
||||||
|
public class FLLifeCycleMonitor extends AbstractPluginLifecycleMonitor { |
||||||
|
@Override |
||||||
|
public void afterRun(PluginContext pluginContext) { |
||||||
|
FLConfig.getInstance(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void beforeStop(PluginContext pluginContext) { |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.decision.authorize.Passport; |
||||||
|
import com.fr.decision.fun.impl.AbstractPassportProvider; |
||||||
|
import com.fr.decision.webservice.bean.authentication.PassportBean; |
||||||
|
|
||||||
|
public class FLPassportProvider extends AbstractPassportProvider { |
||||||
|
public static final String PASSPORT_TYPE = "oauth2"; |
||||||
|
|
||||||
|
@Override |
||||||
|
public String passportType() { |
||||||
|
return PASSPORT_TYPE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends PassportBean> classForPassportBean() { |
||||||
|
return Oauth2Bean.class; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends Passport> classForPassportConfig() { |
||||||
|
return Oauth2Passport.class; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.decision.fun.impl.AbstractURLAliasProvider; |
||||||
|
import com.fr.decision.webservice.url.alias.URLAlias; |
||||||
|
import com.fr.decision.webservice.url.alias.URLAliasFactory; |
||||||
|
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||||
|
import com.fr.plugin.transform.FunctionRecorder; |
||||||
|
|
||||||
|
/** |
||||||
|
* 将长连接转换为短连接 |
||||||
|
* 参考文档: |
||||||
|
* https://wiki.fanruan.com/display/PD/com.fr.decision.fun.URLAliasProvider
|
||||||
|
*/ |
||||||
|
@FunctionRecorder |
||||||
|
public class FLURLAliasBridge extends AbstractURLAliasProvider |
||||||
|
{ |
||||||
|
|
||||||
|
@Override |
||||||
|
@ExecuteFunctionRecord |
||||||
|
public URLAlias[] registerAlias() { |
||||||
|
//像这样配置之后再访问/api就可以通过http(s)://ip:port/webroot/decision/url/api。 进行访问
|
||||||
|
return new URLAlias[]{ |
||||||
|
URLAliasFactory.createPluginAlias("/oauth2/login", "/login", true), |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.decision.fun.impl.AbstractWebResourceProvider; |
||||||
|
import com.fr.decision.web.MainComponent; |
||||||
|
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||||
|
import com.fr.plugin.transform.FunctionRecorder; |
||||||
|
import com.fr.stable.fun.Authorize; |
||||||
|
import com.fr.web.struct.Atom; |
||||||
|
@Authorize(callSignKey = "com.fr.plugin.custom.logo" ) |
||||||
|
@FunctionRecorder |
||||||
|
public class LogindJSHandler extends AbstractWebResourceProvider { |
||||||
|
|
||||||
|
/** |
||||||
|
* 需要附加到的主组件 |
||||||
|
* |
||||||
|
* @return 主组件 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Override |
||||||
|
@ExecuteFunctionRecord |
||||||
|
public Atom attach() { |
||||||
|
return MainComponent.KEY; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 客户端所需的组件 |
||||||
|
* |
||||||
|
* @return 组件 |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public Atom client() { |
||||||
|
return LoginedLogoComponent.KEY; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fr.plugin.transform.ExecuteFunctionRecord; |
||||||
|
import com.fr.plugin.transform.FunctionRecorder; |
||||||
|
import com.fr.web.struct.Component; |
||||||
|
import com.fr.web.struct.Filter; |
||||||
|
import com.fr.web.struct.browser.RequestClient; |
||||||
|
import com.fr.web.struct.category.ScriptPath; |
||||||
|
import com.fr.web.struct.category.StylePath; |
||||||
|
@FunctionRecorder() |
||||||
|
public class LoginedLogoComponent extends Component { |
||||||
|
public static final LoginedLogoComponent KEY = new LoginedLogoComponent(); |
||||||
|
/** |
||||||
|
* 返回需要引入的JS脚本路径 |
||||||
|
* @param client 请求客户端描述 |
||||||
|
* @return JS脚本路径 |
||||||
|
*/ |
||||||
|
@ExecuteFunctionRecord |
||||||
|
public ScriptPath script( RequestClient client ) { |
||||||
|
PluginLicense pluginLicense = PluginLicenseManager.getInstance().getPluginLicenseByID("com.fr.plugin.custom.logo"); |
||||||
|
if (pluginLicense.isAvailable()) { |
||||||
|
// 做认证通过的事情
|
||||||
|
return ScriptPath.build("com/fr/plugin/web/logined.js"); |
||||||
|
} else { |
||||||
|
// 做认证未通过的事情
|
||||||
|
return ScriptPath.build("com/fr/plugin/web/webnuy.js"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 返回需要引入的CSS样式路径 |
||||||
|
* @param client 请求客户端描述 |
||||||
|
* @return CSS样式路径 |
||||||
|
*/ |
||||||
|
public StylePath style( RequestClient client ) { |
||||||
|
//如果不需要就直接返回 StylePath.EMPTY;
|
||||||
|
return StylePath.EMPTY; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 通过给定的资源过滤器控制是否加载这个资源 |
||||||
|
* @return 资源过滤器 |
||||||
|
*/ |
||||||
|
public Filter filter() { |
||||||
|
return new Filter(){ |
||||||
|
@Override |
||||||
|
public boolean accept() { |
||||||
|
//任何情况下我们都在平台组件加载时加载我们的组件
|
||||||
|
return true; |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fanruan.api.decision.auth.bean.BasePassportBean; |
||||||
|
import com.fr.decision.authorize.Passport; |
||||||
|
import com.fr.third.fasterxml.jackson.annotation.JsonSubTypes; |
||||||
|
|
||||||
|
@JsonSubTypes.Type(value = Oauth2Bean.class, name = "LdapAuthenticBean") |
||||||
|
public class Oauth2Bean extends BasePassportBean<Oauth2Passport>{ |
||||||
|
|
||||||
|
@Override |
||||||
|
public String markType() { |
||||||
|
return FLPassportProvider.PASSPORT_TYPE; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public BasePassportBean<Oauth2Passport> createPassportBean(Oauth2Passport oauth2Passport) { |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Passport createPassport() { |
||||||
|
Oauth2Passport oauth2Passport = new Oauth2Passport(); |
||||||
|
return oauth2Passport; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
package com.fr.plugin; |
||||||
|
|
||||||
|
import com.fanruan.api.conf.HolderKit; |
||||||
|
import com.fanruan.api.decision.auth.BasePassport; |
||||||
|
import com.fanruan.api.net.http.HttpKit; |
||||||
|
import com.fanruan.api.util.AssistKit; |
||||||
|
import com.fanruan.api.util.StringKit; |
||||||
|
import com.fr.config.Identifier; |
||||||
|
import com.fr.config.holder.Conf; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class Oauth2Passport extends BasePassport { |
||||||
|
@Override |
||||||
|
public String markType() { |
||||||
|
return FLPassportProvider.PASSPORT_TYPE; |
||||||
|
} |
||||||
|
|
||||||
|
@Identifier("emptytoken") |
||||||
|
private Conf<String> emptytoken = HolderKit.simple(StringKit.EMPTY); |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return AssistKit.hashCode(emptytoken.get()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() throws CloneNotSupportedException { |
||||||
|
return super.clone(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getEmptytoken() { |
||||||
|
return emptytoken.get(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setEmptytoken(String emptytoken) { |
||||||
|
this.emptytoken.set(emptytoken); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object obj) { |
||||||
|
if (!(obj instanceof Oauth2Passport)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
Oauth2Passport target = (Oauth2Passport) obj; |
||||||
|
return AssistKit.equals(target.getEmptytoken(), this.getEmptytoken()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean checkTicket(String username, String inputPassword, String savedPassword, String hashPassword) { |
||||||
|
//调用接口验证账号密码
|
||||||
|
FLConfig flConfig = FLConfig.getInstance(); |
||||||
|
String url = String.format("%s/am/identity/authenticate?username=%s&password=%s&uri=service=initService", flConfig.getValAddr(), username, inputPassword); |
||||||
|
try { |
||||||
|
String resp = HttpKit.get(url); |
||||||
|
return StringUtils.contains(resp,"token.id="); |
||||||
|
} catch (IOException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
package com.fr.plugin;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import com.fr.log.FineLoggerFactory;
import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.params.KeyParameter;
/**
* 3DES加密
*
* @author xxx
* @date 2017-10-19
*/
public class ThreeDESUtil {
private static final byte[] HEX_DIGITS = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70};
private static DESEngine cipher = new DESEngine();
private static byte[] groupingEncrypt(byte[] key, byte[] data) {
int range = 8;
int iRet = data.length % range;
byte[] out;
if (iRet > 0) {
int length = data.length + (range - iRet);
out = new byte[length];
}
else {
out = new byte[data.length];
}
cipher.init(true, new KeyParameter(key));
int i;
for (i = 0; i < data.length / range; i++) {
cipher.processBlock(data, i * range, out, i * range);
}
if (iRet > 0) {
byte[] temp = new byte[range];
System.arraycopy(data, i * range, temp, 0, iRet);
temp[iRet] = -128;
cipher.processBlock(temp, 0, out, i * range);
}
byte[] toasc = new byte[out.length * 2];
int k = 0;
int j = 0;
for (i = 0; i < out.length; i++) {
k = out[i];
toasc[j++] = HEX_DIGITS[k >>> 4 & 0xf];
toasc[j++] = HEX_DIGITS[k & 0xf];
}
return toasc;
}
private static byte[] groupingDecrypt(byte[] key, byte[] data) {
byte[] result = null;
int range = 2;
int group = 8;
int k = 0;
byte[] tobyte = new byte[data.length / range];
for (int i = 0; i < data.length; i += range) {
char ch;
if (data[i] <= 57) {
ch = (char)(data[i] & 0xf);
}
else {
ch = (char)((data[i] & 0xf) + 9);
}
ch <<= '\004';
if (data[i + 1] <= 57) {
ch |= data[i + 1] & 0xf;
}
else {
ch |= (data[i + 1] & 0xf) + 9;
}
tobyte[k] = (byte)ch;
k++;
}
cipher.init(false, new KeyParameter(key));
if (tobyte.length % group == 0) {
byte[] out = new byte[tobyte.length];
for (int i = 0; i < tobyte.length / group; i++) {
cipher.processBlock(tobyte, i * group, out, i * group);
}
int len = padCount(out);
result = new byte[out.length - len];
System.arraycopy(out, 0, result, 0, out.length - len);
return result;
}
else {
return result;
}
}
private static int padCount(byte[] in) {
int count;
for (count = in.length; count > 0; count--) {
if (in[count - 1] != 0) {
break;
}
}
int minNum = -128;
if (in[count - 1] == minNum) {
return (in.length - count) + 1;
}
else {
return in.length - count;
}
}
/**
* 加密
*
* @param code
* @return
*/
public static final String encode(String code, String key) {
if (code == null) {
return null;
}
else {
try {
byte[] cryptogragh = groupingEncrypt(key.getBytes(StandardCharsets.ISO_8859_1), code.getBytes(StandardCharsets.UTF_8.toString()));
return new String(cryptogragh, StandardCharsets.UTF_8.toString());
}
catch (UnsupportedEncodingException e) {
FineLoggerFactory.getLogger().error(e.toString(), e);
return null;
}
}
}
/**
* 解密
*
* @param code
* @return
*/
public static final String decode(String code, String key) {
if (code == null) {
return null;
}
else {
try {
byte[] debyte = groupingDecrypt(key.getBytes(StandardCharsets.ISO_8859_1), code.getBytes(StandardCharsets.UTF_8.toString()));
return debyte != null ? new String(debyte, StandardCharsets.UTF_8.toString()) : null;
}
catch (UnsupportedEncodingException e) {
FineLoggerFactory.getLogger().error(e.toString(), e);
return null;
}
}
}
} |
@ -0,0 +1,10 @@ |
|||||||
|
package com.fr.plugin.exception; |
||||||
|
|
||||||
|
public class ValidException extends RuntimeException{ |
||||||
|
public ValidException() { |
||||||
|
} |
||||||
|
|
||||||
|
public ValidException(String message) { |
||||||
|
super(message); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,323 @@ |
|||||||
|
package com.fr.plugin.handler; |
||||||
|
|
||||||
|
import com.auth0.jwt.JWT; |
||||||
|
import com.auth0.jwt.JWTVerifier; |
||||||
|
import com.auth0.jwt.algorithms.Algorithm; |
||||||
|
import com.auth0.jwt.impl.PublicClaims; |
||||||
|
import com.auth0.jwt.interfaces.Claim; |
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT; |
||||||
|
import com.fanruan.api.net.http.HttpKit; |
||||||
|
import com.fanruan.api.net.http.rs.HttpRequest; |
||||||
|
import com.fanruan.api.net.http.rs.TextResponseHandle; |
||||||
|
import com.finebi.utils.CollectionUtils; |
||||||
|
import com.fr.data.NetworkHelper; |
||||||
|
import com.fr.decision.authority.data.User; |
||||||
|
import com.fr.decision.fun.impl.BaseHttpHandler; |
||||||
|
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.decision.webservice.v10.user.UserService; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.DBUtils; |
||||||
|
import com.fr.plugin.FLConfig; |
||||||
|
import com.fr.plugin.ThreeDESUtil; |
||||||
|
import com.fr.plugin.exception.ValidException; |
||||||
|
import com.fr.security.JwtUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.web.Device; |
||||||
|
import com.fr.third.jodd.util.URLDecoder; |
||||||
|
import com.fr.third.org.apache.http.entity.ContentType; |
||||||
|
import com.fr.third.org.apache.http.nio.entity.NStringEntity; |
||||||
|
import com.fr.third.springframework.web.bind.annotation.RequestMethod; |
||||||
|
import com.fr.web.utils.WebUtils; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import javax.servlet.http.HttpSession; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
public class FLLoginCallBackHander extends BaseHttpHandler { |
||||||
|
DBUtils dbUtils = new DBUtils("secret-key"); |
||||||
|
|
||||||
|
public static Map<String, Claim> verifyToken(String token, String unifySecred, String key) throws Exception { |
||||||
|
String decode = ThreeDESUtil.decode(unifySecred, key); |
||||||
|
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(decode)).build(); |
||||||
|
Map<String, Claim> mapValue = null; |
||||||
|
if (verifier != null) { |
||||||
|
DecodedJWT jwt = verifier.verify(token); |
||||||
|
if (jwt != null) { |
||||||
|
mapValue = jwt.getClaims(); |
||||||
|
} |
||||||
|
} |
||||||
|
return mapValue; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public RequestMethod getMethod() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getPath() { |
||||||
|
return "/login"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isPublic() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private String findSecretKey() { |
||||||
|
String sql = "select APP_SECRET from sm2_uuid_secret ORDER BY UPDATE_TIME DESC"; |
||||||
|
try { |
||||||
|
List<Map<String, String>> result = dbUtils.exQuery(sql); |
||||||
|
if (CollectionUtils.isEmpty(result)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
String secret = result.get(0).get("APP_SECRET"); |
||||||
|
FineLoggerFactory.getLogger().info("oauth login secret :{}", secret); |
||||||
|
return secret; |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("oauth login exception :{}", e.getMessage(), e); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void getMethodHandle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
String token = req.getParameter("token"); |
||||||
|
String loginName = req.getParameter("loginName"); |
||||||
|
String serviceId = req.getParameter("serviceId"); |
||||||
|
String redirectUrl = req.getParameter("redirectUrl"); |
||||||
|
FineLoggerFactory.getLogger().info("oauth login[get] token:{},loginName:{},serviceId:{},redirectUrl:{}", token, loginName, serviceId, redirectUrl); |
||||||
|
redirectUrl = URLDecoder.decode(redirectUrl); |
||||||
|
if (StringUtils.isNotBlank(token)) { |
||||||
|
String applySexret = findSecretKey(); |
||||||
|
//1. token有效期验证
|
||||||
|
/* if (StringUtils.isNotEmpty(applySexret)) { |
||||||
|
Map<String, Claim> map; |
||||||
|
try { |
||||||
|
map = verifyToken(token, applySexret); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("token校验失败--------------" + e.toString()); |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
return; |
||||||
|
} |
||||||
|
Date date = map.get(PublicClaims.EXPIRES_AT).asDate(); |
||||||
|
int exp = date.compareTo(new Date()); |
||||||
|
if (exp < 0) { |
||||||
|
WebUtils.printAsString(res, "token过期,请重新跳转登录"); |
||||||
|
return; |
||||||
|
} |
||||||
|
}*/ |
||||||
|
//2. 调用接口获取用户信息
|
||||||
|
String username = validGetTokenGetUsername(serviceId, token, loginName); |
||||||
|
UserService userService = UserService.getInstance(); |
||||||
|
User user = userService.getUserByUserName(username); |
||||||
|
if (user != null) { |
||||||
|
login(req, res, username); |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
// String frUrl = xtlConfig.getFrUrl();
|
||||||
|
sendRedirect(res, redirectUrl); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "用户" + username + "在帆软系统中不存在"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
// sendRedirect(res, goAuth());
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void postMethodHandle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
String token = req.getParameter("pwdaToken"); |
||||||
|
String loginName = req.getParameter("acctId"); |
||||||
|
String syscode = req.getParameter("syscode"); |
||||||
|
String redirectUrl = req.getParameter("redirectUrl"); |
||||||
|
FineLoggerFactory.getLogger().info("oauth login[post] pwdaToken:{},acctId:{},syscode:{},redirectUrl:{}", token, loginName, syscode, redirectUrl); |
||||||
|
redirectUrl = URLDecoder.decode(redirectUrl); |
||||||
|
if (StringUtils.isNotBlank(token)) { |
||||||
|
String applySexret = findSecretKey(); |
||||||
|
//1. token有效期验证
|
||||||
|
if (StringUtils.isNotEmpty(applySexret)) { |
||||||
|
Map<String, Claim> map; |
||||||
|
try { |
||||||
|
map = verifyToken(token, applySexret, FLConfig.getInstance().getThreeDdKey()); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("token校验失败--------------" + e.toString()); |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
return; |
||||||
|
} |
||||||
|
Date date = map.get(PublicClaims.EXPIRES_AT).asDate(); |
||||||
|
int exp = date.compareTo(new Date()); |
||||||
|
if (exp < 0) { |
||||||
|
WebUtils.printAsString(res, "token过期,请重新跳转登录"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
//2. 调用接口获取用户信息
|
||||||
|
String username = validPostTokenGetUsername(syscode, token, loginName); |
||||||
|
UserService userService = UserService.getInstance(); |
||||||
|
User user = userService.getUserByUserName(username); |
||||||
|
if (user != null) { |
||||||
|
login(req, res, username); |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
//String frUrl = redirectUrl;//xtlConfig.getFrUrl();
|
||||||
|
sendRedirect(res, redirectUrl); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "用户" + username + "在帆软系统中不存在"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
try { |
||||||
|
String method = FLConfig.getInstance().getMethod(); |
||||||
|
if (StringUtils.isEmpty(method)) { |
||||||
|
if ("POST".equals(req.getMethod())) {//post提交方式处理逻辑
|
||||||
|
postMethodHandle(req, res); |
||||||
|
} else { |
||||||
|
getMethodHandle(req, res); |
||||||
|
} |
||||||
|
} else if ("GET".equals(method.toUpperCase())) { |
||||||
|
getMethodHandle(req, res); |
||||||
|
} else if ("POST".equals(method.toUpperCase())) { |
||||||
|
postMethodHandle(req, res); |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "请求方式配置异常"); |
||||||
|
} |
||||||
|
} catch (ValidException e) { |
||||||
|
WebUtils.printAsString(res, e.getMessage()); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
WebUtils.printAsString(res, "处理异常"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String validGetTokenGetUsername(String service, String token, String userName) throws IOException { |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
String valAddr = xtlConfig.getValAddr(); |
||||||
|
String url = String.format("%s/checkBwdaToken", valAddr); |
||||||
|
JSONObject req = new JSONObject(); |
||||||
|
req.put("SERVICEID", service); |
||||||
|
req.put("LOGINNAME", userName); |
||||||
|
req.put("TOKEN", token); |
||||||
|
String reqJson = req.toString(); |
||||||
|
url += "?args=" + ThreeDESUtil.encode(reqJson, xtlConfig.getThreeDdKey()); |
||||||
|
; |
||||||
|
FineLoggerFactory.getLogger().info("验证token请求地址:{}", url); |
||||||
|
String resp = HttpKit.get(url, null); |
||||||
|
|
||||||
|
/** |
||||||
|
* SERVICEID 应用标识,由4A统一分配 |
||||||
|
* RSP 成功标识0成功 非0失败 |
||||||
|
* LOGINACCOUNT 当前登录主帐号。应用侧获取当前主帐号 |
||||||
|
* ERRDESC 错误描述,仅当rsp非0时有效 |
||||||
|
*/ |
||||||
|
FineLoggerFactory.getLogger().info("验证token结果响应:{}", resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
String data = entries.getString("data"); |
||||||
|
entries = new JSONObject(data); |
||||||
|
if (Objects.equals(0, entries.getNumberOfInteger("RSP"))) { |
||||||
|
FineLoggerFactory.getLogger().info("验证token登录成功,获取用户名:{}", entries.getString("LOGINACCOUNT")); |
||||||
|
return entries.getString("LOGINACCOUNT"); |
||||||
|
} else { |
||||||
|
throw new ValidException("4a校验异常"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String validPostTokenGetUsername(String syscode, String token, String userName) throws IOException { |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
String valAddr = xtlConfig.getValAddr(); |
||||||
|
String url = String.format("%s/checkProwadaToken", valAddr); |
||||||
|
JSONObject req = new JSONObject(); |
||||||
|
req.put("SYSCODE", syscode); |
||||||
|
req.put("ACCTID", userName); |
||||||
|
req.put("TOKEN", token); |
||||||
|
String reqJson = req.toString(); |
||||||
|
url += "?args=" + ThreeDESUtil.encode(reqJson, xtlConfig.getThreeDdKey()); |
||||||
|
String data = ThreeDESUtil.encode(reqJson, xtlConfig.getThreeDdKey()); |
||||||
|
FineLoggerFactory.getLogger().info("验证token请求地址:{}", url); |
||||||
|
JSONObject reqBody = new JSONObject(); |
||||||
|
reqBody.put("args", data); |
||||||
|
String resp = TextResponseHandle.DEFAULT.parse(HttpKit.execute(HttpRequest.custom() |
||||||
|
.url(url) |
||||||
|
.post(new NStringEntity(reqBody.toString(), ContentType.APPLICATION_JSON)).build())); |
||||||
|
// String resp = HttpKit.post(url, null);
|
||||||
|
/** |
||||||
|
* SYSCODE 应用标识,由4A统一分配 |
||||||
|
* RSP 成功标识0成功 非0失败 |
||||||
|
* ACCTNAME 当前登录主帐号登录名 |
||||||
|
* ORGCODE 当前登录账号身份的组织编码 |
||||||
|
* ERRDESC 错误描述,仅当rsp非0时有效 |
||||||
|
*/ |
||||||
|
FineLoggerFactory.getLogger().info("验证token结果响应:{}", resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
String respData = entries.getString("data"); |
||||||
|
entries = new JSONObject(respData); |
||||||
|
if (Objects.equals(0, entries.getNumberOfInteger("RSP"))) { |
||||||
|
return entries.getString("USERCODE"); |
||||||
|
} else { |
||||||
|
throw new ValidException("4a校验异常"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void sendRedirect(HttpServletResponse res, String url) throws Exception { |
||||||
|
// WebUtils.printAsString(res, "ok");
|
||||||
|
if (StringUtils.isEmpty(url)) { |
||||||
|
url = FLConfig.getInstance().getFrUrl(); |
||||||
|
} |
||||||
|
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); |
||||||
|
res.setHeader("Location", url); |
||||||
|
FineLoggerFactory.getLogger().info("登录成功,跳转url:", url); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private boolean login(HttpServletRequest req, HttpServletResponse res, String username) { |
||||||
|
try { |
||||||
|
String oldToken = TokenResource.COOKIE.getToken(req); |
||||||
|
if ((oldToken == null) || (!checkTokenValid(req, oldToken, username))) { |
||||||
|
HttpSession session = req.getSession(true); |
||||||
|
String token = LoginService.getInstance().login(req, res, username); |
||||||
|
session.setAttribute("fine_auth_token", token); |
||||||
|
FineLoggerFactory.getLogger().error("fr CookieFilter is over with username is ###" + username); |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
FineLoggerFactory.getLogger().error("no need login: {}", username); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean checkTokenValid(HttpServletRequest req, String token, String currentUserName) { |
||||||
|
try { |
||||||
|
if (!ComparatorUtils.equals(currentUserName, JwtUtils.parseJWT(token).getSubject())) { |
||||||
|
FineLoggerFactory.getLogger().info("username changed:" + currentUserName); |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
Device device = NetworkHelper.getDevice(req); |
||||||
|
LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, device)); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch (Exception var5) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,286 @@ |
|||||||
|
package com.fr.plugin.handler; |
||||||
|
|
||||||
|
import com.auth0.jwt.JWT; |
||||||
|
import com.auth0.jwt.JWTVerifier; |
||||||
|
import com.auth0.jwt.algorithms.Algorithm; |
||||||
|
import com.auth0.jwt.impl.PublicClaims; |
||||||
|
import com.auth0.jwt.interfaces.Claim; |
||||||
|
import com.auth0.jwt.interfaces.DecodedJWT; |
||||||
|
import com.fanruan.api.net.http.HttpKit; |
||||||
|
import com.finebi.utils.CollectionUtils; |
||||||
|
import com.fr.data.NetworkHelper; |
||||||
|
import com.fr.decision.authority.data.User; |
||||||
|
import com.fr.decision.fun.impl.BaseHttpHandler; |
||||||
|
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.decision.webservice.v10.user.UserService; |
||||||
|
import com.fr.general.ComparatorUtils; |
||||||
|
import com.fr.json.JSONObject; |
||||||
|
import com.fr.log.FineLoggerFactory; |
||||||
|
import com.fr.plugin.DBUtils; |
||||||
|
import com.fr.plugin.FLConfig; |
||||||
|
import com.fr.plugin.ThreeDESUtil; |
||||||
|
import com.fr.plugin.exception.ValidException; |
||||||
|
import com.fr.security.JwtUtils; |
||||||
|
import com.fr.stable.StringUtils; |
||||||
|
import com.fr.stable.web.Device; |
||||||
|
import com.fr.third.springframework.web.bind.annotation.RequestMethod; |
||||||
|
import com.fr.web.utils.WebUtils; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
import javax.servlet.http.HttpSession; |
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
public class FLPostLoginCallBackHander extends BaseHttpHandler { |
||||||
|
DBUtils dbUtils = new DBUtils("secret-key"); |
||||||
|
|
||||||
|
public static Map<String, Claim> verifyToken(String token, String unifySecred) throws Exception { |
||||||
|
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(unifySecred)).build(); |
||||||
|
Map<String, Claim> mapValue = null; |
||||||
|
if (verifier != null) { |
||||||
|
DecodedJWT jwt = verifier.verify(token); |
||||||
|
if (jwt != null) { |
||||||
|
mapValue = jwt.getClaims(); |
||||||
|
} |
||||||
|
} |
||||||
|
return mapValue; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public RequestMethod getMethod() { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getPath() { |
||||||
|
return "/login/post"; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isPublic() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private String findSecretKey() { |
||||||
|
String sql = "select APP_SECRET from sm2_uuid_secret ORDER BY UPDATE_TIME DESC"; |
||||||
|
try { |
||||||
|
List<Map<String, String>> result = dbUtils.exQuery(sql); |
||||||
|
if (CollectionUtils.isEmpty(result)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
String secret = result.get(0).get("APP_SECRET"); |
||||||
|
FineLoggerFactory.getLogger().info("oauth login secret :{}", secret); |
||||||
|
return secret; |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("oauth login exception :{}", e.getMessage(), e); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void getMethodHandle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
String token = req.getParameter("token"); |
||||||
|
String loginName = req.getParameter("loginName"); |
||||||
|
String serviceId = req.getParameter("serviceId"); |
||||||
|
FineLoggerFactory.getLogger().info("oauth login[get] token:{},loginName:{},serviceId:{}", token, loginName, serviceId); |
||||||
|
if (StringUtils.isNotBlank(token)) { |
||||||
|
String applySexret = findSecretKey(); |
||||||
|
//1. token有效期验证
|
||||||
|
/* if (StringUtils.isNotEmpty(applySexret)) { |
||||||
|
Map<String, Claim> map; |
||||||
|
try { |
||||||
|
map = verifyToken(token, applySexret); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("token校验失败--------------" + e.toString()); |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
return; |
||||||
|
} |
||||||
|
Date date = map.get(PublicClaims.EXPIRES_AT).asDate(); |
||||||
|
int exp = date.compareTo(new Date()); |
||||||
|
if (exp < 0) { |
||||||
|
WebUtils.printAsString(res, "token过期,请重新跳转登录"); |
||||||
|
return; |
||||||
|
} |
||||||
|
}*/ |
||||||
|
//2. 调用接口获取用户信息
|
||||||
|
String username = validGetTokenGetUsername(serviceId, token, loginName); |
||||||
|
UserService userService = UserService.getInstance(); |
||||||
|
User user = userService.getUserByUserName(username); |
||||||
|
if (user != null) { |
||||||
|
login(req, res, username); |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
String frUrl = xtlConfig.getFrUrl(); |
||||||
|
sendRedirect(res, frUrl); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "用户" + username + "在帆软系统中不存在"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
// sendRedirect(res, goAuth());
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void postMethodHandle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
String token = req.getParameter("pwdaToken"); |
||||||
|
String loginName = req.getParameter("acctId"); |
||||||
|
String syscode = req.getParameter("syscode"); |
||||||
|
FineLoggerFactory.getLogger().info("oauth login[get] pwdaToken:{},acctId:{},syscode:{}", token, loginName, syscode); |
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(token)) { |
||||||
|
String applySexret = findSecretKey(); |
||||||
|
//1. token有效期验证
|
||||||
|
if (StringUtils.isNotEmpty(applySexret)) { |
||||||
|
Map<String, Claim> map; |
||||||
|
try { |
||||||
|
map = verifyToken(token, applySexret); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error("token校验失败--------------" + e.toString()); |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
return; |
||||||
|
} |
||||||
|
Date date = map.get(PublicClaims.EXPIRES_AT).asDate(); |
||||||
|
int exp = date.compareTo(new Date()); |
||||||
|
if (exp < 0) { |
||||||
|
WebUtils.printAsString(res, "token过期,请重新跳转登录"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
//2. 调用接口获取用户信息
|
||||||
|
String username = validPostTokenGetUsername(syscode, token, loginName); |
||||||
|
UserService userService = UserService.getInstance(); |
||||||
|
User user = userService.getUserByUserName(username); |
||||||
|
if (user != null) { |
||||||
|
login(req, res, username); |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
String frUrl = xtlConfig.getFrUrl(); |
||||||
|
sendRedirect(res, frUrl); |
||||||
|
return; |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "用户" + username + "在帆软系统中不存在"); |
||||||
|
return; |
||||||
|
} |
||||||
|
} else { |
||||||
|
WebUtils.printAsString(res, "token校验失败"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { |
||||||
|
try { |
||||||
|
postMethodHandle(req, res); |
||||||
|
} catch (ValidException e) { |
||||||
|
WebUtils.printAsString(res, e.getMessage()); |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
WebUtils.printAsString(res, "处理异常"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String validGetTokenGetUsername(String service, String token, String userName) throws IOException { |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
String valAddr = xtlConfig.getValAddr(); |
||||||
|
String url = String.format("%s/checkBwdaToken", valAddr); |
||||||
|
JSONObject req = new JSONObject(); |
||||||
|
req.put("SERVICEID", service); |
||||||
|
req.put("LOGINNAME", userName); |
||||||
|
req.put("TOKEN", token); |
||||||
|
String reqJson = req.toString(); |
||||||
|
url += "?args=" + ThreeDESUtil.encode(reqJson, xtlConfig.getThreeDdKey()); |
||||||
|
; |
||||||
|
FineLoggerFactory.getLogger().info("验证token请求地址:{}", url); |
||||||
|
String resp = HttpKit.get(url, null); |
||||||
|
|
||||||
|
/** |
||||||
|
* SERVICEID 应用标识,由4A统一分配 |
||||||
|
* RSP 成功标识0成功 非0失败 |
||||||
|
* LOGINACCOUNT 当前登录主帐号。应用侧获取当前主帐号 |
||||||
|
* ERRDESC 错误描述,仅当rsp非0时有效 |
||||||
|
*/ |
||||||
|
FineLoggerFactory.getLogger().info("验证token结果响应:{}", resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
String data = entries.getString("data"); |
||||||
|
entries = new JSONObject(data); |
||||||
|
if (Objects.equals(0, entries.getNumberOfInteger("RSP"))) { |
||||||
|
FineLoggerFactory.getLogger().info("验证token登录成功,获取用户名:{}", entries.getString("LOGINACCOUNT")); |
||||||
|
return entries.getString("LOGINACCOUNT"); |
||||||
|
} else { |
||||||
|
throw new ValidException("4a校验异常"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String validPostTokenGetUsername(String syscode, String token, String userName) throws IOException { |
||||||
|
FLConfig xtlConfig = FLConfig.getInstance(); |
||||||
|
String valAddr = xtlConfig.getValAddr(); |
||||||
|
String url = String.format("%s/checkProwadaToken", valAddr); |
||||||
|
JSONObject req = new JSONObject(); |
||||||
|
req.put("SYSCODE", syscode); |
||||||
|
req.put("ACCTID", userName); |
||||||
|
req.put("TOKEN", token); |
||||||
|
String reqJson = req.toString(); |
||||||
|
url += "?args=" + ThreeDESUtil.encode(reqJson, xtlConfig.getThreeDdKey()); |
||||||
|
String resp = HttpKit.get(url, null); |
||||||
|
/** |
||||||
|
* SYSCODE 应用标识,由4A统一分配 |
||||||
|
* RSP 成功标识0成功 非0失败 |
||||||
|
* ACCTNAME 当前登录主帐号登录名 |
||||||
|
* ORGCODE 当前登录账号身份的组织编码 |
||||||
|
* ERRDESC 错误描述,仅当rsp非0时有效 |
||||||
|
*/ |
||||||
|
FineLoggerFactory.getLogger().info("验证token结果响应:{}", resp); |
||||||
|
JSONObject entries = new JSONObject(resp); |
||||||
|
if (Objects.equals(0, entries.getNumberOfInteger("RSP"))) { |
||||||
|
return entries.getString("USERCODE"); |
||||||
|
} else { |
||||||
|
throw new ValidException("4a校验异常"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void sendRedirect(HttpServletResponse res, String url) { |
||||||
|
res.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); |
||||||
|
res.setHeader("Location", url); |
||||||
|
} |
||||||
|
|
||||||
|
private boolean login(HttpServletRequest req, HttpServletResponse res, String username) { |
||||||
|
try { |
||||||
|
String oldToken = TokenResource.COOKIE.getToken(req); |
||||||
|
if ((oldToken == null) || (!checkTokenValid(req, oldToken, username))) { |
||||||
|
HttpSession session = req.getSession(true); |
||||||
|
String token = LoginService.getInstance().login(req, res, username); |
||||||
|
session.setAttribute("fine_auth_token", token); |
||||||
|
FineLoggerFactory.getLogger().error("fr CookieFilter is over with username is ###" + username); |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
FineLoggerFactory.getLogger().error("no need login: {}", username); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean checkTokenValid(HttpServletRequest req, String token, String currentUserName) { |
||||||
|
try { |
||||||
|
if (!ComparatorUtils.equals(currentUserName, JwtUtils.parseJWT(token).getSubject())) { |
||||||
|
FineLoggerFactory.getLogger().info("username changed:" + currentUserName); |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
Device device = NetworkHelper.getDevice(req); |
||||||
|
LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, device)); |
||||||
|
return true; |
||||||
|
} |
||||||
|
} catch (Exception var5) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
;(function ($) { |
||||||
|
|
||||||
|
BI.config("dec.user.setting.authentications", function (items) { |
||||||
|
items.push({ |
||||||
|
value: "oauth2", |
||||||
|
text: "统一认证", |
||||||
|
"@class": "com.fr.plugin.Oauth2Bean", |
||||||
|
component: { |
||||||
|
type: "dec.plugin.custom_oatuh2" |
||||||
|
} |
||||||
|
}); |
||||||
|
return items; |
||||||
|
}); |
||||||
|
var Ldaps = BI.inherit(BI.Widget, { |
||||||
|
|
||||||
|
props: { |
||||||
|
baseCls: "", |
||||||
|
}, |
||||||
|
render: function () { |
||||||
|
var self = this, o = this.options; |
||||||
|
return { |
||||||
|
type: "bi.vertical", |
||||||
|
bgap: 15, |
||||||
|
items: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
getValue: function () { |
||||||
|
return {}; |
||||||
|
} |
||||||
|
}); |
||||||
|
BI.shortcut("dec.plugin.custom_oatuh2", Ldaps); |
||||||
|
})(jQuery) |
Loading…
Reference in new issue