7 changed files with 319 additions and 1 deletions
@ -1,3 +1,6 @@
|
||||
# open-JSD-9066 |
||||
|
||||
JSD-9066 FR单点接口密码自定义解密 |
||||
JSD-9066 FR单点接口密码自定义解密\ |
||||
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 |
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<plugin> |
||||
<id>com.fr.plugin.xxxx.cqjg.jump</id> |
||||
<main-package>com.fr.plugin.xxxx.cqjg.jump</main-package> |
||||
<name><![CDATA[跳转Chrome]]></name> |
||||
<active>yes</active> |
||||
<version>1.4</version> |
||||
<env-version>10.0</env-version> |
||||
<jartime>2018-07-31</jartime> |
||||
<vendor>xxxx</vendor> |
||||
<description><![CDATA[跳转Chrome]]></description> |
||||
<change-notes><![CDATA[ |
||||
[2021-10-29]【1.0】初始化插件。<br/> |
||||
[2021-11-04]【1.1】逻辑修改为解析token中用户的方式。<br/> |
||||
[2021-11-08]【1.2】增加获取token链接,直接比对数据库密码。<br/> |
||||
[2021-11-08]【1.3】增加sha256加密后比对数据库密码。<br/> |
||||
[2021-11-08]【1.4】增加写入cookie。<br/> |
||||
]]></change-notes> |
||||
<extra-decision> |
||||
<HttpHandlerProvider class="com.fr.plugin.xxxx.cqjg.jump.TokenRequestHandlerBridge"/> |
||||
<URLAliasProvider class="com.fr.plugin.xxxx.cqjg.jump.TokenRequestURLAliasBridge" /> |
||||
<GlobalRequestFilterProvider class="com.fr.plugin.xxxx.cqjg.jump.GlobalFilter"/> |
||||
</extra-decision> |
||||
<function-recorder class="com.fr.plugin.xxxx.cqjg.jump.GlobalFilter"/> |
||||
</plugin> |
@ -0,0 +1,9 @@
|
||||
package com.fr.plugin.xxxx.cqjg.jump; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @date 2020/5/14 |
||||
*/ |
||||
public class Constants { |
||||
public static final String PLUGIN_ID = "com.fr.plugin.xxxx.cqjg.jump"; |
||||
} |
@ -0,0 +1,109 @@
|
||||
package com.fr.plugin.xxxx.cqjg.jump; |
||||
|
||||
import com.fr.cert.token.Claims; |
||||
import com.fr.cert.token.Jwts; |
||||
import com.fr.decision.authority.data.User; |
||||
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; |
||||
import com.fr.decision.webservice.exception.user.UserNotExistException; |
||||
import com.fr.decision.webservice.utils.DecisionServiceConstants; |
||||
import com.fr.decision.webservice.v10.config.ConfigService; |
||||
import com.fr.decision.webservice.v10.login.LoginService; |
||||
import com.fr.decision.webservice.v10.user.UserService; |
||||
import com.fr.intelli.record.Focus; |
||||
import com.fr.intelli.record.Original; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.plugin.context.PluginContexts; |
||||
import com.fr.plugin.transform.FunctionRecorder; |
||||
import com.fr.record.analyzer.EnableMetrics; |
||||
import com.fr.security.KeySecretSeedConfig; |
||||
import com.fr.security.SecurityToolbox; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.fun.Authorize; |
||||
|
||||
import javax.servlet.FilterChain; |
||||
import javax.servlet.ServletException; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.io.IOException; |
||||
|
||||
/** |
||||
* @Author fr.open |
||||
* @Date 2021/10/29 |
||||
* @Description |
||||
**/ |
||||
@FunctionRecorder |
||||
@Authorize(callSignKey = Constants.PLUGIN_ID) |
||||
@EnableMetrics |
||||
public class GlobalFilter extends AbstractGlobalRequestFilterProvider { |
||||
|
||||
private static final String flag = "00000"; |
||||
|
||||
@Override |
||||
public String filterName() { |
||||
return "global"; |
||||
} |
||||
|
||||
@Override |
||||
@Focus(id = Constants.PLUGIN_ID, text = "重庆建工集团跳转", source = Original.PLUGIN) |
||||
public String[] urlPatterns() { |
||||
if (PluginContexts.currentContext().isAvailable()) { |
||||
String servletPathName = "decision"; |
||||
try { |
||||
servletPathName = ConfigService.getInstance().getBasicParam().getServletPathName(); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return new String[]{ |
||||
"/" + servletPathName, |
||||
"/" + servletPathName + "/view/report", |
||||
|
||||
}; |
||||
} else { |
||||
return new String[0]; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) { |
||||
String query = req.getQueryString(); |
||||
if (StringUtils.isNotBlank(query) && query.contains(flag)) { |
||||
int start = query.indexOf(flag) + 5; |
||||
int end = query.indexOf("&", start); |
||||
String token = query.substring(start, end == -1 ? query.length() : end); |
||||
FineLoggerFactory.getLogger().info("get token is {}", token); |
||||
try { |
||||
byte[] bytes = SecurityToolbox.base642Byte(KeySecretSeedConfig.getInstance().getTrustSeed()); |
||||
Claims claims = Jwts.parser().setSigningKey(bytes).parseClaimsJws(token).getBody(); |
||||
loginFromToken(req,res,claims.getSubject()); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
try { |
||||
filterChain.doFilter(req, res); |
||||
} catch (IOException e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage()); |
||||
} catch (ServletException e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage()); |
||||
} |
||||
} |
||||
|
||||
private boolean loginFromToken(HttpServletRequest req, HttpServletResponse res, String username) throws Exception { |
||||
try { |
||||
if (StringUtils.isNotEmpty(username)) { |
||||
User user = UserService.getInstance().getUserByUserName(username); |
||||
if (user == null) { |
||||
throw new UserNotExistException(); |
||||
} |
||||
String token = LoginService.getInstance().login(req, res, username); |
||||
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token); |
||||
return true; |
||||
} else { |
||||
return false; |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,18 @@
|
||||
package com.fr.plugin.xxxx.cqjg.jump; |
||||
|
||||
import com.fr.decision.fun.HttpHandler; |
||||
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; |
||||
import com.fr.plugin.holger.cqjg.jump.handle.TokenHandler; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @since 2021/07/28 |
||||
*/ |
||||
public class TokenRequestHandlerBridge extends AbstractHttpHandlerProvider { |
||||
@Override |
||||
public HttpHandler[] registerHandlers() { |
||||
return new HttpHandler[]{ |
||||
new TokenHandler() |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,18 @@
|
||||
package com.fr.plugin.xxxx.cqjg.jump; |
||||
|
||||
import com.fr.decision.fun.impl.AbstractURLAliasProvider; |
||||
import com.fr.decision.webservice.url.alias.URLAlias; |
||||
import com.fr.decision.webservice.url.alias.URLAliasFactory; |
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @since 2021/07/28 |
||||
*/ |
||||
public class TokenRequestURLAliasBridge extends AbstractURLAliasProvider { |
||||
@Override |
||||
public URLAlias[] registerAlias() { |
||||
return new URLAlias[]{ |
||||
URLAliasFactory.createPluginAlias("/token", "/token", true), |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,136 @@
|
||||
package com.fr.plugin.xxxx.cqjg.jump.handle; |
||||
|
||||
import com.fr.base.ServerConfig; |
||||
import com.fr.base.TemplateUtils; |
||||
import com.fr.data.NetworkHelper; |
||||
import com.fr.decision.authority.AuthorityContext; |
||||
import com.fr.decision.authority.data.User; |
||||
import com.fr.decision.config.FSConfig; |
||||
import com.fr.decision.fun.impl.BaseHttpHandler; |
||||
import com.fr.decision.mobile.terminal.TerminalHandler; |
||||
import com.fr.decision.webservice.CrossDomainResponse; |
||||
import com.fr.decision.webservice.bean.authentication.LoginClientBean; |
||||
import com.fr.decision.webservice.exception.user.UserNotExistException; |
||||
import com.fr.decision.webservice.utils.DecisionStatusService; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.security.JwtUtils; |
||||
import com.fr.stable.StringUtils; |
||||
import com.fr.stable.query.QueryFactory; |
||||
import com.fr.stable.query.restriction.RestrictionFactory; |
||||
import com.fr.stable.web.Device; |
||||
import com.fr.store.Converter; |
||||
import com.fr.third.com.lowagie.text.pdf.BadPasswordException; |
||||
import com.fr.third.org.apache.commons.codec.digest.DigestUtils; |
||||
import com.fr.third.springframework.web.bind.annotation.RequestMethod; |
||||
import com.fr.web.utils.WebUtils; |
||||
|
||||
import javax.servlet.http.Cookie; |
||||
import javax.servlet.http.HttpServletRequest; |
||||
import javax.servlet.http.HttpServletResponse; |
||||
import java.util.HashMap; |
||||
|
||||
|
||||
/** |
||||
* @author fr.open |
||||
* @Date 2021/08/17 |
||||
*/ |
||||
public class TokenHandler extends BaseHttpHandler { |
||||
|
||||
@Override |
||||
public RequestMethod getMethod() { |
||||
return RequestMethod.GET; |
||||
} |
||||
|
||||
@Override |
||||
public String getPath() { |
||||
return "/token"; |
||||
} |
||||
|
||||
@Override |
||||
public boolean isPublic() { |
||||
return true; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void handle(HttpServletRequest req, HttpServletResponse res) { |
||||
CrossDomainResponse domainResponse = null; |
||||
try { |
||||
String origin = NetworkHelper.getOriginalURL(req); |
||||
String uri = req.getRequestURI(); |
||||
String render = TemplateUtils.render(origin.replace(uri, "${fineServletURL}")); |
||||
String username = WebUtils.getHTTPRequestParameter(req, "fine_username"); |
||||
String password = WebUtils.getHTTPRequestParameter(req, "fine_password"); |
||||
String validity = WebUtils.getHTTPRequestParameter(req, "validity"); |
||||
User user = AuthorityContext.getInstance().getUserController().findOne(QueryFactory.create().addRestriction(RestrictionFactory.eq("userName", username))); |
||||
if (user == null) { |
||||
throw new UserNotExistException(); |
||||
} |
||||
if (!StringUtils.equals(DigestUtils.sha256Hex(password), user.getPassword())) { |
||||
throw new BadPasswordException(); |
||||
} |
||||
long timeout = getTokenTimeOutByValidity(Integer.parseInt(validity)); |
||||
String token = generateToken(user.getUserName(), user.getDisplayName(), user.getTenantId(),timeout ); |
||||
Device device = NetworkHelper.getDevice(req); |
||||
TerminalHandler handler = TerminalHandler.getTerminal(req, device); |
||||
LoginClientBean clientBean = new LoginClientBean(req, device, handler); |
||||
clientBean.setUsername(user.getUserName()); |
||||
clientBean.setToken(token); |
||||
clientBean.setValidity(Integer.parseInt(validity)); |
||||
clientBean.setUserId(user.getId()); |
||||
this.addLoginStatus(token, clientBean, timeout); |
||||
this.writeToken2Cookie(res, token, Integer.parseInt(validity)); |
||||
|
||||
domainResponse = CrossDomainResponse.create().callbackFuncName("callback").parameter("accessToken",token).parameter("url", render).parameter("status", "success"); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
domainResponse = CrossDomainResponse.error(e, "callback"); |
||||
} |
||||
try { |
||||
WebUtils.printAsString(res, domainResponse.createCrossDomainResponse()); |
||||
; |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
private void writeToken2Cookie(HttpServletResponse res, String token, int validity) { |
||||
try { |
||||
if (StringUtils.isNotEmpty(token)) { |
||||
Cookie tokenCookie = new Cookie("fine_auth_token", token); |
||||
long timeout = validity == -2 ? 1209600000L : (long)validity; |
||||
tokenCookie.setMaxAge((int)timeout); |
||||
tokenCookie.setPath(ServerConfig.getInstance().getCookiePath()); |
||||
res.addCookie(tokenCookie); |
||||
Cookie rememberLogin = new Cookie("fine_remember_login", String.valueOf(validity == -2 ? -2 : -1)); |
||||
rememberLogin.setMaxAge((int)timeout); |
||||
rememberLogin.setPath(ServerConfig.getInstance().getCookiePath()); |
||||
res.addCookie(rememberLogin); |
||||
} else { |
||||
FineLoggerFactory.getLogger().error("empty token cannot save."); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
|
||||
} |
||||
|
||||
private void addLoginStatus(String token, LoginClientBean bean, long timeout) throws Exception { |
||||
DecisionStatusService.loginStatusService().put(token, bean, new Converter<LoginClientBean>() { |
||||
@Override |
||||
public String[] createAlias(LoginClientBean bean) { |
||||
return new String[]{bean.getUsername()}; |
||||
} |
||||
}, timeout); |
||||
} |
||||
|
||||
private long getTokenTimeOutByValidity(int validity) { |
||||
return validity == -2 ? 1209600000L : FSConfig.getInstance().getLoginConfig().getLoginTimeout(); |
||||
} |
||||
|
||||
private String generateToken(String username, String displayName, String tenanId, long validity) { |
||||
HashMap map = new HashMap(); |
||||
map.put("description", displayName); |
||||
map.put("tenantId", tenanId); |
||||
return JwtUtils.createDefaultJWT(username, map, validity); |
||||
} |
||||
} |
Loading…
Reference in new issue