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 verifyToken(String token, String unifySecred) throws Exception { JWTVerifier verifier = JWT.require(Algorithm.HMAC256(unifySecred)).build(); Map 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> 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 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 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; } } }