You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

232 lines
9.3 KiB

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<String, Object> 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<String, Object> 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<String, String> 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<String, Object> 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);
}
}
}