Commit 241430e0 by wqc

单点登录调整333

parent fd5e68ec
......@@ -30,7 +30,7 @@ public interface SysFeign {
ResultVo modifyPasswd(@RequestBody Map<String, Object> paramsMap);
@PostMapping("/sso/verifyToken")
ResultVo getVerifyToken(@RequestBody Map<String, Object> paramsMap);
ResultVo getVerifyToken(@RequestBody Map<Object, Object> paramsMap);
@GetMapping("/api/version/getAppVersion")
ResultVo getAppVersion(@RequestParam String appName);
......
package com.zq.api.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.zq.api.dao.ApiLogDao;
import com.zq.api.entity.ApiLog;
import com.zq.api.entity.ApiUser;
import com.zq.api.feign.SysFeign;
import com.zq.api.form.ApiForm;
import com.zq.api.form.ApiResp;
import com.zq.api.utils.ApiUtils;
import com.zq.api.utils.ReflectionUtils;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.vo.ApiTokenVo;
import com.zq.common.vo.ResultVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author wilmiam
* @since 2021-09-28 15:44
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiLogDao apiLogDao;
private final SysFeign sysFeign;
private final RedisUtils redisUtils;
/**
* 允许用户未登录状态下执行的方法名
*/
private final String[] allowMethod = {"sendCode", "resetPassword", "phoneLogin", "passwdLogin", "getAppVersion","cremationSearch","marriageSearch","naturalPersonSearch"};
private static final List<String> METHOD_LIST;
static {
METHOD_LIST = methodList();
}
public IApiLogic getApiLogic(ApiForm form) {
IApiLogic apiLogic = ApiUtils.getApiLogic(form);
return apiLogic;
}
public static List<String> methodList() {
List<String> methodList = new ArrayList<>();
Method[] methods = IApiLogic.class.getMethods();
for (Method method : methods) {
Class<?>[] params = method.getParameterTypes();
if (params.length == 1 && (params[0] == ApiForm.class)) {
methodList.add(method.getName());
}
}
return methodList;
}
public ApiResp action(ApiForm form) throws Exception {
if (!METHOD_LIST.contains(form.getMethod())) {
return ApiUtils.getMethodError(form);
}
// 调用接口方法,利用反射更简洁
IApiLogic apiLogic = getApiLogic(form);
return (ApiResp) ReflectionUtils.invokeMethod(apiLogic, form.getMethod(), new Class<?>[]{ApiForm.class}, new Object[]{form});
}
/**
* 身份验证
*
* @param form
* @param appId
* @param appSecret
* @return
*/
public ApiResp auth(ApiForm form, String appId, String appSecret, String token) {
boolean contains = Arrays.asList(allowMethod).contains(form.getMethod());
if (contains) {
return ApiUtils.getSuccessResp(form);
} else if (StrUtil.isBlank(token)) {
return ApiUtils.getLoginValidError(form);
}
ResultVo resultVo = sysFeign.getApiUserByAppId(appId, appSecret);
if (!resultVo.isSuccess() || resultVo.getData() == null) {
return ApiUtils.getAppIdValidError(form);
}
// 认证签名
String key = redisUtils.getStr("civil.apiKey." + token);
String sign = ApiUtils.getSign(form.getSignStr(key == null ? "" : key));
if (!sign.equals(form.getSign())) {
return ApiUtils.getCheckSignValidError(form);
}
ApiUser apiUser = BeanUtil.copyProperties(resultVo.getData(), ApiUser.class);
ApiTokenVo apiTokenVo = ApiTokenVo.builder()
.userId(apiUser.getId())
.name(apiUser.getName())
.roleLevel(apiUser.getRoleLevel())
.build();
form.setUserId(apiUser.getId() == null ? null : apiUser.getId().toString());
form.setAppId(apiUser.getAppId());
form.setApiTokenVo(apiTokenVo);
return ApiUtils.getSuccessResp(form);
}
@Async
public void addLog(ApiForm form, String ip, String logType, String respMsg, String errorInfo, Long timeCost) {
apiLogDao.insert(ApiLog.builder()
.appId(form.getAppId())
.userId(form.getUserId())
.method(form.getMethod())
.version(form.getVersion())
.bizContent(form.getBizContent())
.ip(ip)
.logType(logType)
.respMsg(respMsg)
.stackTrace(errorInfo)
.timeCost(timeCost)
.createTime(DateUtil.date().toJdkDate())
.build());
}
}
package com.zq.api.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.zq.api.dao.ApiLogDao;
import com.zq.api.entity.ApiLog;
import com.zq.api.entity.ApiUser;
import com.zq.api.feign.SysFeign;
import com.zq.api.form.ApiForm;
import com.zq.api.form.ApiResp;
import com.zq.api.utils.ApiUtils;
import com.zq.api.utils.ReflectionUtils;
import com.zq.common.config.redis.RedisUtils;
import com.zq.common.vo.ApiTokenVo;
import com.zq.common.vo.ResultVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author wilmiam
* @since 2021-09-28 15:44
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ApiService {
private final ApiLogDao apiLogDao;
private final SysFeign sysFeign;
private final RedisUtils redisUtils;
/**
* 允许用户未登录状态下执行的方法名
*/
private final String[] allowMethod = {"sendCode", "resetPassword", "phoneLogin", "passwdLogin", "getAppVersion","cremationSearch","marriageSearch","naturalPersonSearch"};
private static final List<String> METHOD_LIST;
static {
METHOD_LIST = methodList();
}
public IApiLogic getApiLogic(ApiForm form) {
IApiLogic apiLogic = ApiUtils.getApiLogic(form);
return apiLogic;
}
public static List<String> methodList() {
List<String> methodList = new ArrayList<>();
Method[] methods = IApiLogic.class.getMethods();
for (Method method : methods) {
Class<?>[] params = method.getParameterTypes();
if (params.length == 1 && (params[0] == ApiForm.class)) {
methodList.add(method.getName());
}
}
return methodList;
}
public ApiResp action(ApiForm form) throws Exception {
if (!METHOD_LIST.contains(form.getMethod())) {
return ApiUtils.getMethodError(form);
}
// 调用接口方法,利用反射更简洁
IApiLogic apiLogic = getApiLogic(form);
return (ApiResp) ReflectionUtils.invokeMethod(apiLogic, form.getMethod(), new Class<?>[]{ApiForm.class}, new Object[]{form});
}
/**
* 身份验证
*
* @param form
* @param appId
* @param appSecret
* @return
*/
public ApiResp auth(ApiForm form, String appId, String appSecret, String token) {
boolean contains = Arrays.asList(allowMethod).contains(form.getMethod());
if (contains) {
return ApiUtils.getSuccessResp(form);
} else if (StrUtil.isBlank(token)) {
return ApiUtils.getLoginValidError(form);
}
ResultVo resultVo = sysFeign.getApiUserByAppId(appId, appSecret);
if (!resultVo.isSuccess() || resultVo.getData() == null) {
return ApiUtils.getAppIdValidError(form);
}
// 认证签名
String key = redisUtils.getStr("civil.apiKey." + token);
String sign = ApiUtils.getSign(form.getSignStr(key == null ? "" : key));
if (!sign.equals(form.getSign())) {
return ApiUtils.getCheckSignValidError(form);
}
ApiUser apiUser = BeanUtil.copyProperties(resultVo.getData(), ApiUser.class);
ApiTokenVo apiTokenVo = ApiTokenVo.builder()
.userId(apiUser.getId())
.name(apiUser.getName())
.roleLevel(apiUser.getRoleLevel())
.token(token)
.sessionKey(key)
.build();
form.setUserId(apiUser.getId() == null ? null : apiUser.getId().toString());
form.setAppId(apiUser.getAppId());
form.setApiTokenVo(apiTokenVo);
return ApiUtils.getSuccessResp(form);
}
@Async
public void addLog(ApiForm form, String ip, String logType, String respMsg, String errorInfo, Long timeCost) {
apiLogDao.insert(ApiLog.builder()
.appId(form.getAppId())
.userId(form.getUserId())
.method(form.getMethod())
.version(form.getVersion())
.bizContent(form.getBizContent())
.ip(ip)
.logType(logType)
.respMsg(respMsg)
.stackTrace(errorInfo)
.timeCost(timeCost)
.createTime(DateUtil.date().toJdkDate())
.build());
}
}
package com.zq.api.service.impl;
import cn.hutool.core.map.MapUtil;
import com.zq.api.feign.OpenFeign;
import com.zq.api.feign.PortalFeign;
import com.zq.api.feign.SysFeign;
......@@ -13,6 +14,7 @@ import com.zq.common.vo.ResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
......@@ -52,7 +54,10 @@ public class ApiV100Logic extends BaseApiLogic implements IApiLogic {
@Override
public ApiResp getVerifyToken(ApiForm form) {
return ApiUtils.toApiResp(form, sysFeign.getVerifyToken(form.getParamsMap()));
Map<Object, Object> params = MapUtil.builder()
.put("appId",form.getAppId())
.build();
return ApiUtils.toApiResp(form, sysFeign.getVerifyToken(params));
}
@Override
......
......@@ -19,9 +19,9 @@ public class SsoLoginVo {
private String uuid = "";
private String loginToken;
private String token;
private String loginKey;
private String key;
private String appId;
......
......@@ -42,12 +42,6 @@ public class SysInfo {
@ApiModelProperty("状态 0-禁用 1-启用")
private Integer state;
@ApiModelProperty("生成的token")
private String loginToken;
@ApiModelProperty("生成的key")
private String loginKey;
@ApiModelProperty("创建时间")
private Date createTime;
......
......@@ -102,10 +102,9 @@ public class SsoController {
@ApiOperation("验证token和key")
@PostMapping(value = "/verifyToken")
public ResultVo verifyToken(@RequestParam String loginToken,String loginKey ,HttpServletRequest request, HttpServletResponse response) {
AssertUtils.notNull(loginToken,"token不为空");
AssertUtils.notNull(loginKey,"key不为空");
return ResultVo.success(ssoService.verifyToken(loginToken,loginKey,request,response));
public ResultVo verifyToken(@RequestBody SsoLoginVo vo ,HttpServletRequest request, HttpServletResponse response) {
AssertUtils.notNull(vo.getAppId(),"APPID不为空");
return ResultVo.success(ssoService.verifyToken(vo,request,response));
}
......
package com.zq.system.modules.system.rest.api;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.zq.system.modules.mnt.rest.AppController;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class testAPI {
public static void main(String[] args) {
String appId = "a5cbfc5ac3704f848e12f464a8289bfc";
String apiNo = IdUtil.simpleUUID();
String method = "getVerifyToken";
String timestamp = System.currentTimeMillis() + "";
String version = "1.0.0";
String bizContent = "";//JSON字符串
bizContent = StrUtil.isBlank(bizContent) ? "" : URLUtil.encode(Base64.encode(bizContent), StandardCharsets.UTF_8);
Map<String, String> params = new HashMap<>();
params.put("appId", appId);
params.put("apiNo", apiNo);
params.put("method", method);
params.put("timestamp", timestamp);
params.put("bizContent", bizContent);
params.put("version", version);
// 签名参数排序
TreeMap<String, String> signTreeMap = new TreeMap<>();
signTreeMap.put("appId", appId);
signTreeMap.put("apiNo", apiNo);
signTreeMap.put("timestamp", timestamp);
signTreeMap.put("method", method);
signTreeMap.put("version", version);
signTreeMap.put("bizContent", bizContent);
// 拼接签名参数
StringBuilder src = new StringBuilder();
for (Map.Entry<String, String> entry : signTreeMap.entrySet()) {
src.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
}
//key,单点登录后由我方返回
src.append("key=").append("99edda8498cd465c84b08a41bcfe1c7b");
params.put("sign", MD5.create().digestHex(src.toString()).toUpperCase());
String sign=MD5.create().digestHex(src.toString()).toUpperCase();
//请求头中Authorization既为token,单点登录后由我方返回
HttpRequest request = HttpRequest.post("http://127.0.0.1:9888/api/action")
.header("appId", appId)
.header("appSecret", "5ba197db5cbb4863a829d7deabf9d238")
.header("key","99edda8498cd465c84b08a41bcfe1c7b")
.header("Authorization", "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MTIyNyIsImF1dGgiOiIiLCJqdGkiOiI2ZDU5YzIxNGY5NTA0OTc4YjFiNDYwYjdiZGU5YmY0ZCJ9.mQ0HmX4k6JelSObgzwasIlZk6Dx7fmmkso7TL0aEFivJO_1x92KOHy6FmHyX7ttyb7AMNv7bjWZ5x20zufbTOw")
.contentType("application/x-www-form-urlencoded")
.formStr(params);
HttpResponse execute = request.execute();
String body = execute.body();
System.out.println("响应 => " + body);
// 失败 => {"apiNo":"09c1ad82ec0f4b2d80cae0cfb1d7059b","code":"103","msg":"调用方法异常","timestamp":1638176339560,"data":null,"success":false}
// 成功 => {"apiNo":"bc070a7c31ac4b8eb1180b2d82a2096b","code":"200","msg":"成功","timestamp":1638176552353,"data":{"userId":"123","username":"admin@gxfy.com"},"success":true}
int status = execute.getStatus();
if (status == 200) {
JSONObject obj = JSONUtil.parseObj(body);
Integer code = obj.getInt("code");
if (code == 200) {
JSONObject data = obj.getJSONObject("data");
System.out.println("成功拿到数据 => " + data);
}
}
}
}
......@@ -86,7 +86,7 @@ public class SsoService {
verificationCode(vo.getPhone(), vo.getPhoneVerificationCode());
User resources=new User();
User resources = new User();
resources.setPassword(passwordEncoder.encode(passwd));
resources.setDept(vo.getDept());
resources.setEnabled(vo.getEnabled());
......@@ -210,7 +210,7 @@ public class SsoService {
}
public Object tokenLogin(SsoLoginVo vo,HttpServletRequest request, HttpServletResponse response) {
public Object tokenLogin(SsoLoginVo vo, HttpServletRequest request, HttpServletResponse response) {
String toUrl = request.getParameter("service");
AssertUtils.hasText(toUrl, "跳转地址为空");
......@@ -225,19 +225,17 @@ public class SsoService {
data.put("toUrl", toUrl + "?" + properties.getHeader() + "=" + token + "&key=" + key);
data.put(properties.getHeader(), properties.getTokenStartWith() + token);
// if () {
SysInfo sysInfo = sysInfoDao.selectOne(Wrappers.lambdaQuery(SysInfo.builder().appId(vo.getAppId()).build()));
AssertUtils.hasText(sysInfo.getAppId(), "APPID不存在");
AssertUtils.hasText(sysInfo.getHomeUrl(), "业务系统主页地址未配置");
SysInfo build = SysInfo.builder()
.appId(sysInfo.getAppId())
.loginKey(key)
.loginToken(token)
.systemName(vo.getSystemName())
.systemTag(vo.getSystemTag())
.state(1)
.createTime(DateUtil.date())
.build();
sysInfoDao.updateByappId(build);
SysInfo sysInfo = sysInfoDao.selectOne(Wrappers.lambdaQuery(SysInfo.builder().appId(vo.getAppId()).build()));
AssertUtils.hasText(sysInfo.getAppId(), "APPID不存在");
AssertUtils.hasText(sysInfo.getHomeUrl(), "业务系统主页地址未配置");
SysInfo build = SysInfo.builder()
.appId(sysInfo.getAppId())
.systemName(vo.getSystemName())
.systemTag(vo.getSystemTag())
.state(1)
.createTime(DateUtil.date())
.build();
sysInfoDao.updateByappId(build);
// }
return data;
// response.sendRedirect(sysInfo.getHomeUrl() + "?" + properties.getHeader() + "=" + token + "&key=" + key);
......@@ -293,11 +291,13 @@ public class SsoService {
redisUtils.deleteStr(CacheKeys.authCodeKey(phone));
}
public ResultVo verifyToken(String loginToken,String loginKey, HttpServletRequest request, HttpServletResponse response) {
SysInfo sysInfo = sysInfoDao.selectOne(Wrappers.lambdaQuery(SysInfo.builder().loginToken(loginToken).loginKey(loginKey).build()));
if (sysInfo==null){
return ResultVo.success(sysInfo.getAppId());
}else{
public ResultVo verifyToken(SsoLoginVo vo, HttpServletRequest request, HttpServletResponse response) {
OnlineUserDto adminContext = ContextUtils.getAdminContext();
SysInfo sysInfo = sysInfoDao.selectOne(Wrappers.lambdaQuery(SysInfo.class).eq(SysInfo::getAppId, vo.getAppId()));
BindUserInfo bindUserInfo = blindUserInfoDao.selectOne(Wrappers.lambdaQuery(BindUserInfo.builder().sysId(sysInfo.getId()).userId(adminContext.getUserId()).build()));
if (sysInfo != null) {
return ResultVo.success(bindUserInfo.getSystemUserId());
} else {
return ResultVo.fail("校验失败");
}
}
......
......@@ -11,13 +11,11 @@
<result property="homeUrl" column="home_url" jdbcType="OTHER"/>
<result property="loginUrl" column="login_url" jdbcType="OTHER"/>
<result property="state" column="state" jdbcType="OTHER"/>
<result property="loginToken" column="login_token" jdbcType="OTHER"/>
<result property="loginKey" column="login_key" jdbcType="OTHER"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
</resultMap>
<update id="updateByappId">
update sys_info
UPDATE sys_info
<set>
<if test="appId != null">
app_id = #{appId, jdbcType=OTHER},
......@@ -28,12 +26,6 @@
<if test="systemTag != null">
system_tag = #{systemTag, jdbcType=OTHER},
</if>
<if test="loginToken != null">
login_token = #{loginToken, jdbcType=OTHER},
</if>
<if test="loginKey != null">
login_key = #{loginKey, jdbcType=OTHER},
</if>
<if test="createTime != null">
create_time = #{createTime, jdbcType=TIMESTAMP},
</if>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment