package com.fr.plugin.xxx.gzjc.sso.filter; import com.fr.base.TemplateUtils; import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; import com.fr.decision.webservice.bean.authentication.OriginUrlResponseBean; import com.fr.decision.webservice.utils.DecisionStatusService; import com.fr.decision.webservice.utils.WebServiceUtils; import com.fr.general.PropertiesUtils; import com.fr.intelli.record.Focus; import com.fr.intelli.record.Original; import com.fr.json.JSONArray; import com.fr.json.JSONObject; import com.fr.locale.InterProviderFactory; import com.fr.log.FineLoggerFactory; import com.fr.plugin.context.PluginContexts; import com.fr.plugin.xxx.gzjc.sso.PluginConstants; import com.fr.plugin.xxx.gzjc.sso.utils.HttpUtil; import com.fr.plugin.xxx.gzjc.sso.utils.LogUtils; import com.fr.plugin.transform.FunctionRecorder; import com.fr.stable.StringUtils; import com.fr.stable.fun.Authorize; import com.fr.web.utils.WebUtils; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.UUID; import static com.fr.plugin.xxx.gzjc.sso.utils.CommonUtils.*; /** * @author xxx * @since 2021/12/04 */ @FunctionRecorder @Authorize(callSignKey = PluginConstants.PLUGIN_ID) public class SsoFilter extends AbstractGlobalRequestFilterProvider { private String apiClientId; private String apiClientSecret; private String apiAuthorize; private String apiGetToken; private String apiGetUser; private String errorUrl; private String appName; private void initParams() { Properties props = PropertiesUtils.getProperties("sso"); this.apiClientId = props.getProperty("api.client_id"); this.apiClientSecret = props.getProperty("api.client_secret"); this.apiAuthorize = props.getProperty("api.authorize"); this.apiGetToken = props.getProperty("api.get-token"); this.apiGetUser = props.getProperty("api.get-user"); this.appName = props.getProperty("api.app-name"); this.errorUrl = props.getProperty("api.error-url"); } @Override public void init(FilterConfig filterConfig) { super.init(filterConfig); } @Override public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) { if (isAccept(request) || isLogin(request)) { next(request, response, chain); return; } try { initParams(); //登录页面跳转地址拦截 String origin = WebUtils.getHTTPRequestParameter(request, "origin"); if (request.getRequestURI().endsWith("decision/login")) { try { if ("get".equalsIgnoreCase(request.getMethod()) && StringUtils.isNotBlank(origin)) { OriginUrlResponseBean path = DecisionStatusService.originUrlStatusService().get(origin); if (path != null) { String currentPath = String.format("%s://%s:%s%s",request.getScheme(),request.getServerName(),request.getServerPort(),path.getOriginUrl()); jumpAuthorize(request, response, currentPath); return; } } } catch (Exception e) { LogUtils.error(e.getMessage(), e); } next(request, response, chain); return; } String code = request.getParameter("code"); if (StringUtils.isBlank(code)) { jumpAuthorize(request, response, ""); return; } String username = getUsername(getToken(code)); if(!existUser(username)){ String address = String.format("%s?systemName=%s&reason=%s", errorUrl, URLEncoder.encode(appName,"UTF-8"), URLEncoder.encode("用户不存在","UTF-8")); response.sendRedirect(address); return; } login(username, request, response); String state = request.getParameter("state"); if (StringUtils.isNotBlank(state)) { String accessURL = getCachedParam(state, "accessURL"); if (StringUtils.isNotBlank(accessURL)) { response.sendRedirect(accessURL); return; } } next(request, response, chain); } catch (Exception e) { LogUtils.error("oauth2单点登陆处理失败, Cause by: ", e); setError(response, e.getMessage()); } } private String getUsername(String token) throws IOException { String address = String.format("%s?access_token=%s&client_id=%s", apiGetUser, token, apiClientId); HashMap params = new HashMap<>(); params.put("access_token", token); String res = HttpUtil.sendGet(address, null, null); LogUtils.debug4plugin("请求用户信息返回的内容 >>> [{}]", res); JSONObject body = new JSONObject(res); if(body.has("spRoleList")){ JSONArray array = body.getJSONArray("spRoleList"); if(array.length() != 0){ return array.getString(0); } } if (body.has("loginName")) { return body.getString("loginName"); } throw new RuntimeException("获取用户信息失败,Cause by: " + res); } private String getToken(String code) throws IOException { String address = String.format("%s?client_id=%s&grant_type=authorization_code&code=%s&client_secret=%s", apiGetToken, apiClientId, code, apiClientSecret); HashMap params = new HashMap<>(); params.put("client_id", apiClientId); params.put("client_secret", apiClientSecret); params.put("code", code); params.put("grant_type", "authorization_code"); String res = HttpUtil.sendPost(address, null, JSONObject.create()); LogUtils.debug4plugin("请求 Token 接口返回的内容 >>> [{}]", res); JSONObject body = new JSONObject(res); if (body.has("access_token")) { return body.getString("access_token"); } throw new RuntimeException("获取access_token失败,Cause by: " + res); } private void jumpAuthorize(HttpServletRequest request, HttpServletResponse response, String originUrl) throws Exception { String state = UUID.randomUUID().toString(); String accessURL = request.getRequestURL().toString(); Map params = new HashMap<>(); if (StringUtils.isNotBlank(originUrl)) { accessURL = String.format("%s://%s:%s%s",request.getScheme(),request.getServerName(),request.getServerPort(), TemplateUtils.render("${fineServletURL}"));; params.put("accessURL", originUrl); } else { if (StringUtils.isNotBlank(request.getQueryString())) { accessURL += "?" + request.getQueryString(); } params.put("accessURL", accessURL); } cacheParams(state, params); String address = String.format("%s?redirect_uri=%s&state=%s&client_id=%s&response_type=code", apiAuthorize, URLEncoder.encode(accessURL, "UTF-8"), state, apiClientId); LogUtils.debug4plugin("请求中不包含code值,跳转到登陆页面 >>> \"{}\"", address); response.sendRedirect(address); } @Override public String filterName() { return "sso"; } @Override @Focus(id = PluginConstants.PLUGIN_ID, text = "机场oauth2单点登陆", source = Original.PLUGIN) public String[] urlPatterns() { if (!PluginContexts.currentContext().isAvailable()) { return new String[]{"/neverbeused"}; } return new String[]{ "/decision/", "/decision/login", "/decision", "/decision/view/report", "/decision/view/form", }; } private boolean isAccept(HttpServletRequest request) { if (request.getRequestURI().endsWith("/view/form") || request.getRequestURI().endsWith("/view/report")) { if (StringUtils.isNotBlank(WebUtils.getHTTPRequestParameter(request, "code"))) { return false; } return true; } return false; } private void setError(HttpServletResponse res, String reason) { try { PrintWriter printWriter = WebUtils.createPrintWriter(res); Map map = new HashMap<>(); map.put("result", InterProviderFactory.getProvider().getLocText("Fine-Engine_Error_Page_Result")); map.put("reason", reason); map.put("solution", InterProviderFactory.getProvider().getLocText("Fine-Engine_Please_Contact_Platform_Admin")); String page = WebServiceUtils.parseWebPageResourceSafe("com/fr/web/controller/decision/entrance/resources/unavailable.html", map); printWriter.write(page); printWriter.flush(); printWriter.close(); } catch (Exception e) { FineLoggerFactory.getLogger().error(e.getMessage(), e); } } }