Browse Source

增加统一认证登陆;

dev
luyan 2 years ago
parent
commit
07e59070e0
  1. 9
      epmet-auth/src/main/java/com/epmet/constant/SsoConstant.java
  2. 20
      epmet-auth/src/main/java/com/epmet/controller/SsoController.java
  3. 30
      epmet-auth/src/main/java/com/epmet/dto/form/SsoCheckTicketFormDTO.java
  4. 15
      epmet-auth/src/main/java/com/epmet/service/SsoService.java
  5. 167
      epmet-auth/src/main/java/com/epmet/service/impl/SsoServiceImpl.java
  6. 10
      epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/constant/AppClientConstant.java

9
epmet-auth/src/main/java/com/epmet/constant/SsoConstant.java

@ -17,5 +17,12 @@ public interface SsoConstant {
String USER_ID_IS_NULL = "userId为空,生成token失败......";
String CUSTOMER_ID_IS_NULL = "customerId为空,缓存放置token失败......";
/**
* 日照 Ticket 校验接口地址SSO调用
*/
String TICKET_TOKEN_URL = "https://sso.shuzirizhao.cn/sso/checkTicket";
/**
* 日照 获取登陆身份信息
*/
String USER_INFO_URL = "https://sso.shuzirizhao.cn/sso/userinfo";
}

20
epmet-auth/src/main/java/com/epmet/controller/SsoController.java

@ -4,20 +4,20 @@ import com.epmet.commons.thirdplat.apiservice.jcet.JcetApiService;
import com.epmet.commons.thirdplat.bean.ThirdPlatUserInfo;
import com.epmet.commons.tools.utils.Result;
import com.epmet.commons.tools.validator.ValidatorUtils;
import com.epmet.dto.form.SsoEnteOrgFormDTO;
import com.epmet.dto.form.SsoLoginFormDTO;
import com.epmet.dto.form.SsoLoginOperFormDTO;
import com.epmet.dto.form.SsoWorkLoginFormDTO;
import com.epmet.dto.form.*;
import com.epmet.dto.result.SsoLoginResultDTO;
import com.epmet.dto.result.UserTokenResultDTO;
import com.epmet.service.SsoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
* @Author zxc
* @DateTime 2021/1/18 下午4:33
@ -40,7 +40,7 @@ public class SsoController {
* @date 2021/1/18 下午4:59
*/
@PostMapping("resi/login")
public Result<SsoLoginResultDTO> ssoResiLogin(@RequestBody SsoLoginFormDTO formDTO){
public Result<SsoLoginResultDTO> ssoResiLogin(@RequestBody SsoLoginFormDTO formDTO) {
ValidatorUtils.validateEntity(formDTO, SsoLoginFormDTO.SsoLoginForm.class);
return new Result<SsoLoginResultDTO>().ok(ssoService.ssoResiLogin(formDTO));
}
@ -74,7 +74,7 @@ public class SsoController {
* @Description 1ticket自动登录获取内部token
**/
@PostMapping("work/login")
public Result<UserTokenResultDTO> ssoWorkLogin(@RequestBody SsoWorkLoginFormDTO formDTO){
public Result<UserTokenResultDTO> ssoWorkLogin(@RequestBody SsoWorkLoginFormDTO formDTO) {
ValidatorUtils.validateEntity(formDTO, SsoWorkLoginFormDTO.SsoLoginForm.class);
return new Result<UserTokenResultDTO>().ok(ssoService.ssoWorkLogin(formDTO));
}
@ -91,4 +91,12 @@ public class SsoController {
return new Result<UserTokenResultDTO>().ok(userTokenResultDTO);
}
@PostMapping("checkTicket")
public Result ssoCheckTicket(@RequestBody SsoCheckTicketFormDTO form) throws IOException {
if (StringUtils.isEmpty(form.getTicket())) {
return new Result().ok(ssoService.checkTicket(form));
}
return new Result().error(-1,"登陆失败,请联系管理员!");
}
}

30
epmet-auth/src/main/java/com/epmet/dto/form/SsoCheckTicketFormDTO.java

@ -0,0 +1,30 @@
package com.epmet.dto.form;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author yan Lu
* @description 日照SSO统一认证接口参数
* @create 2023/7/27 16:10
*/
@Data
public class SsoCheckTicketFormDTO {
/**
* 授权重定向时的 ticket 参数
*/
@NotBlank(message = "ticket不能为空")
private String ticket;
/**
* 单点注销时的回调通知地址只在SSO模式三单点注销时需要携带此参数非必填
*/
private String ssoLogoutCall;
/**
* client 标识用于锁定 ticket非必填
*/
private String client;
}

15
epmet-auth/src/main/java/com/epmet/service/SsoService.java

@ -1,12 +1,11 @@
package com.epmet.service;
import com.epmet.dto.form.SsoEnteOrgFormDTO;
import com.epmet.dto.form.SsoLoginFormDTO;
import com.epmet.dto.form.SsoLoginOperFormDTO;
import com.epmet.dto.form.SsoWorkLoginFormDTO;
import com.epmet.dto.form.*;
import com.epmet.dto.result.SsoLoginResultDTO;
import com.epmet.dto.result.UserTokenResultDTO;
import java.io.IOException;
/**
* @Author zxc
* @DateTime 2021/1/18 下午4:34
@ -44,4 +43,12 @@ public interface SsoService {
* @date 2021/2/24 1:28 下午
*/
UserTokenResultDTO thirdLoginOperWork(SsoLoginOperFormDTO formDTO);
/**
* SSO 登陆信息检查
*
* @param form
* @return
*/
UserTokenResultDTO checkTicket(SsoCheckTicketFormDTO form) throws IOException;
}

167
epmet-auth/src/main/java/com/epmet/service/impl/SsoServiceImpl.java

@ -2,16 +2,21 @@ package com.epmet.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.epmet.auth.constants.AuthOperationConstants;
import com.epmet.common.token.constant.LoginConstant;
import com.epmet.commons.thirdplat.apiservice.AbstractApiService;
import com.epmet.commons.thirdplat.bean.ThirdPlatUserInfo;
import com.epmet.commons.thirdplat.constants.PyldConstants;
import com.epmet.commons.tools.constant.AppClientConstant;
import com.epmet.commons.tools.exception.EpmetErrorCode;
import com.epmet.commons.tools.exception.EpmetException;
import com.epmet.commons.tools.exception.ExceptionUtils;
import com.epmet.commons.tools.exception.RenException;
import com.epmet.commons.tools.security.dto.GovTokenDto;
import com.epmet.commons.tools.security.dto.TokenDto;
import com.epmet.commons.tools.security.password.PasswordUtils;
import com.epmet.commons.tools.utils.*;
import com.epmet.constant.SsoConstant;
import com.epmet.dto.*;
import com.epmet.dto.form.*;
import com.epmet.dto.result.*;
@ -24,16 +29,24 @@ import com.epmet.jwt.JwtTokenProperties;
import com.epmet.jwt.JwtTokenUtils;
import com.epmet.redis.SsoRedis;
import com.epmet.service.SsoService;
import com.epmet.service.ThirdLoginService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
@ -49,8 +62,6 @@ import java.util.stream.Collectors;
@Slf4j
public class SsoServiceImpl implements SsoService {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private SsoRedis ssoRedis;
@ -107,7 +118,7 @@ public class SsoServiceImpl implements SsoService {
throw new RenException(e.getMessage());
}
if (null == userInfo){
if (null == userInfo) {
throw new RenException(EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getCode(),
"【SSO登录】调用第三方平台查询用户信息失败,用户信息为空");
}
@ -119,12 +130,12 @@ public class SsoServiceImpl implements SsoService {
userInfoFormDTO.setCustomerId(customerId);
Result<UserDTO> userDTOResult = epmetUserOpenFeignClient.saveUserInfo(userInfoFormDTO);
if (!userDTOResult.success()){
if (!userDTOResult.success()) {
throw new RenException("【SSO登录】新增或更新user_weChat失败");
}
userId = userDTOResult.getData().getId();
if (StringUtils.isBlank(userId)){
if (StringUtils.isBlank(userId)) {
throw new RenException("【SSO登录】userId为空,生成token失败");
}
//生成业务token
@ -167,7 +178,7 @@ public class SsoServiceImpl implements SsoService {
//test end
if (!result.success() || null == result.getData() || null == result.getData().getUserId()) {
logger.warn("根据手机号查询PC工作端登陆人员信息失败,返回10003账号不存在,param:{}", JSON.toJSONString(form));
log.warn("根据手机号查询PC工作端登陆人员信息失败,返回10003账号不存在,param:{}", JSON.toJSONString(form));
throw new RenException(EpmetErrorCode.ERR10003.getCode());
}
@ -186,6 +197,111 @@ public class SsoServiceImpl implements SsoService {
return userTokenResultDTO;
}
@Override
public UserTokenResultDTO checkTicket(SsoCheckTicketFormDTO form) throws IOException {
CloseableHttpClient httpclient = null;
CloseableHttpResponse response = null;
UserTokenResultDTO userTokenResultDTO = null;
try {
httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(SsoConstant.TICKET_TOKEN_URL);
JSONObject infoJson = new JSONObject();
infoJson.put("ticket", form.getTicket());
StringEntity stringEntity = new StringEntity(infoJson.toString(), "UTF-8");
stringEntity.setContentEncoding("UTF-8");
stringEntity.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpPost.setEntity(stringEntity);
response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (entity != null) {
EntityUtils.toString(entity, "UTF-8");
}
JSONObject result = JSONObject.parseObject(EntityUtils.toString(entity));
if (result.getString("code").equals("200")) {
String ticket = result.getString("data");
String timestamp = String.valueOf(System.currentTimeMillis());
httpPost = new HttpPost(SsoConstant.USER_INFO_URL);
infoJson = new JSONObject();
infoJson.put("loginId", ticket);
infoJson.put("timestamp", timestamp);
infoJson.put("nonce", "");
infoJson.put("sign", "");
stringEntity = new StringEntity(infoJson.toString(), "UTF-8");
stringEntity.setContentEncoding("UTF-8");
stringEntity.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpPost.setEntity(stringEntity);
response = httpclient.execute(httpPost);
entity = response.getEntity();
if (entity != null) {
EntityUtils.toString(entity, "UTF-8");
}
result = JSONObject.parseObject(EntityUtils.toString(entity));
if (result.getString("code").equals("200")) {
JSONObject data = JSONObject.parseObject(result.getString("data"));
String mobile = data.getString("phone");
String password = data.getString("password");
//1、根据手机号查询政府端工作人员基本信息,校验用户是否存在
Result<List<CustomerStaffDTO>> staffData = epmetUserFeignClient.checkCustomerStaff(mobile);
String customerId = "";
String userId = "";
if (null != staffData && staffData.getData().size() > 0) {
//2、根据客户Id和手机号查询登陆用户信息(代码逻辑来源于web端登陆接口)
CustomerStaffDTO staffDTO = staffData.getData().get(0);
customerId = staffDTO.getCustomerId();
userId = staffDTO.getUserId();
GovWebOperLoginFormDTO checkDto = new GovWebOperLoginFormDTO();
checkDto.setCustomerId(staffDTO.getCustomerId());
checkDto.setMobile(staffDTO.getMobile());
GovWebOperLoginResultDTO resData = epmetUserFeignClient.getStaffIdAndPwd(checkDto).getData();
if (null == resData || null == resData.getUserId()) {
log.warn("根据手机号查询PC工作端登陆人员信息失败,返回10003账号不存在");
throw new EpmetException(EpmetErrorCode.ERR10003.getCode());
}
//3、未禁用enable,已禁用disabled
if ("disabled".equals(resData.getEnableFlag())) {
throw new EpmetException(EpmetErrorCode.GOV_STAFF_DISABLED.getCode(),
String.format("当前账号已被禁用staffId:%s", resData.getUserId()),
EpmetErrorCode.GOV_STAFF_DISABLED.getMsg());
}
GovWebOperLoginResultDTO resultDTO = resData;
//4.密码是否正确
if (!PasswordUtils.matches(password, resultDTO.getPassWord())) {
log.warn("登陆密码错误");
throw new EpmetException(EpmetErrorCode.ERR10004.getCode(), "登陆密码错误!");
}
}
//5.生成token存到redis并返回
userTokenResultDTO = new UserTokenResultDTO();
userTokenResultDTO.setCustomerId(customerId);
String token = generateToken(AppClientConstant.APP_GOV, AppClientConstant.CLIENT_SSO, userId);
userTokenResultDTO.setToken(token);
disposeTokenDto(AppClientConstant.APP_GOV, AppClientConstant.CLIENT_SSO, userId, token, customerId);
// 6.发送登录事件
try {
SpringContextUtils.getBean(ThirdLoginService.class).sendLoginEvent(userId, "数字社区登录",
AppClientConstant.APP_GOV,
AppClientConstant.CLIENT_SSO,
AuthOperationConstants.LOGIN);
} catch (Exception e) {
log.error("【数字社区web端登录】发送登录事件失败,程序继续执行。错误信息");
}
}
} else {
log.error("校验失败,没有查询到Ticket为:'" + form.getTicket() + "'的人员信息", result.getString("msg"));
throw new EpmetException(EpmetErrorCode.ERR10008.getCode(), "校验失败,没有查询到Ticket为:'" + form.getTicket() + "'的人员信息");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != httpclient) {
httpclient.close();
response.close();
}
}
return userTokenResultDTO;
}
/**
* @Description token放缓存
* @Param formDTO
@ -233,7 +349,7 @@ public class SsoServiceImpl implements SsoService {
* @author zxc
* @date 2021/1/19 下午1:47
*/
public String getCustomerId(String appId){
public String getCustomerId(String appId) {
JSONObject jsonObject = new JSONObject();
String customerMsgUrl = epmetThirdUrlPrefix + "/api/third/customermp/getcustomermsg/";
String data = HttpClientManager.getInstance().sendPostByJSON(customerMsgUrl + appId, JSON.toJSONString(jsonObject)).getData();
@ -282,7 +398,7 @@ public class SsoServiceImpl implements SsoService {
} catch (Exception e) {
throw new RenException(e.getMessage());
}
if (null == userInfo){
if (null == userInfo) {
throw new RenException(EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getCode(),
"【SSO登录】调用第三方平台查询用户信息失败,用户信息为空");
}
@ -290,7 +406,7 @@ public class SsoServiceImpl implements SsoService {
//3.根据华为openId查询用户是否存在历史登陆信息
Result<StaffLatestAgencyResultDTO> latestStaffWechat = epmetUserOpenFeignClient.getLatestStaffWechatLoginRecord(userInfo.getOpenId());
if (!latestStaffWechat.success() || null == latestStaffWechat.getData()) {
logger.warn(String.format("没有获取到用户最近一次登录账户信息,code[%s],msg[%s]", EpmetErrorCode.PLEASE_LOGIN.getCode(), EpmetErrorCode.PLEASE_LOGIN.getMsg()));
log.warn(String.format("没有获取到用户最近一次登录账户信息,code[%s],msg[%s]", EpmetErrorCode.PLEASE_LOGIN.getCode(), EpmetErrorCode.PLEASE_LOGIN.getMsg()));
throw new RenException(EpmetErrorCode.PLEASE_LOGIN.getCode());
}
StaffLatestAgencyResultDTO staffLatestAgencyResultDTO = latestStaffWechat.getData();
@ -324,6 +440,7 @@ public class SsoServiceImpl implements SsoService {
staffWechatFormDTO.setWxOpenId(openid);
return epmetUserOpenFeignClient.saveStaffWechat(staffWechatFormDTO);
}
/**
* @param latestStaffWechatLoginDTO
* @Author sun
@ -339,6 +456,7 @@ public class SsoServiceImpl implements SsoService {
Result staffLoginRecordResult = epmetUserOpenFeignClient.saveStaffLoginRecord(staffLoginAgencyRecordFormDTO);
return staffLoginRecordResult;
}
/**
* @Description 生成政府端小程序业务token Key
* @Author sun
@ -349,9 +467,10 @@ public class SsoServiceImpl implements SsoService {
map.put("client", client);
map.put("userId", staffId);
String token = jwtTokenUtils.createToken(map);
logger.info("app:" + app + ";client:" + client + ";userId:" + staffId + ";生成token[" + token + "]");
log.info("app:" + app + ";client:" + client + ";userId:" + staffId + ";生成token[" + token + "]");
return token;
}
/**
* @Description 保存tokenDto到redis
* @Author sun
@ -382,8 +501,9 @@ public class SsoServiceImpl implements SsoService {
govTokenDto.setOrgIdPath(getOrgIdPath(staffLatestAgency.getStaffId()));
cpUserDetailRedis.set(govTokenDto, expire);
logger.info("截止时间:" + DateUtils.format(jwtTokenUtils.getExpiration(token), "yyyy-MM-dd HH:mm:ss"));
log.info("截止时间:" + DateUtils.format(jwtTokenUtils.getExpiration(token), "yyyy-MM-dd HH:mm:ss"));
}
public Set<String> getDeptartmentIdList(String staffId) {
try {
Result<List<DepartmentListResultDTO>> deptListResult = govOrgOpenFeignClient.getDepartmentListByStaffId(staffId);
@ -393,28 +513,31 @@ public class SsoServiceImpl implements SsoService {
return deptIdLists;
}
} else {
logger.error("登录:查询部门列表,远程调用返回错误:{}", deptListResult.getMsg());
log.error("登录:查询部门列表,远程调用返回错误:{}", deptListResult.getMsg());
}
} catch (Exception e) {
String errorStackTrace = ExceptionUtils.getErrorStackTrace(e);
logger.error("登录:查询部门列表异常:{}", errorStackTrace);
log.error("登录:查询部门列表异常:{}", errorStackTrace);
}
return null;
}
/**
* 根据工作人员ID查询网格ID列表
*
* @param staffId
*/
public Set<String> getGridIdList(String staffId) {
Result<List<GridByStaffResultDTO>> result = govOrgOpenFeignClient.listGridsbystaffid(staffId);
if (!result.success()) {
logger.error("登录:查询网格列表,远程调用返回错误:{}", result.getMsg());
log.error("登录:查询网格列表,远程调用返回错误:{}", result.getMsg());
return null;
} else {
List<GridByStaffResultDTO> grids = result.getData();
return grids.stream().map(grid -> grid.getGridId()).collect(Collectors.toSet());
}
}
/**
* 根据staffId查询所属的组织机构
*
@ -423,13 +546,15 @@ public class SsoServiceImpl implements SsoService {
public CustomerAgencyDTO getAgencyByStaffId(String staffId) {
Result<CustomerAgencyDTO> result = govOrgOpenFeignClient.getAgencyByStaff(staffId);
if (!result.success()) {
logger.error("登录:查询登录人所属的机关OrgIdPath失败:{}", result.getMsg());
log.error("登录:查询登录人所属的机关OrgIdPath失败:{}", result.getMsg());
return null;
}
return result.getData();
}
/**
* 查询人员在某机关单位下的角色列表
*
* @param staffId orgId
*/
public List<GovTokenDto.Role> queryGovStaffRoles(String staffId, String orgId) {
@ -443,14 +568,16 @@ public class SsoServiceImpl implements SsoService {
}
return null;
}
/**
* 查询工作人员的OrgIdPath
*
* @param staffId
*/
public String getOrgIdPath(String staffId) {
Result<CustomerAgencyDTO> result = govOrgOpenFeignClient.getAgencyByStaff(staffId);
if (!result.success()) {
logger.error("登录:查询登录人所属的机关OrgIdPath失败:{}", result.getMsg());
log.error("登录:查询登录人所属的机关OrgIdPath失败:{}", result.getMsg());
return null;
}
CustomerAgencyDTO agency = result.getData();
@ -478,7 +605,7 @@ public class SsoServiceImpl implements SsoService {
customerStaffFormDTO.setMobile(formDTO.getMobile());
Result<CustomerStaffDTO> customerStaffDTOResult = epmetUserOpenFeignClient.getCustomerStaffInfo(customerStaffFormDTO);
if (!customerStaffDTOResult.success() || null == customerStaffDTOResult.getData()) {
logger.warn(String.format("获取工作人员信息失败,手机号[%s],客户id:[%s],code[%s],msg[%s]", formDTO.getMobile(), formDTO.getCustomerId(), customerStaffDTOResult.getCode(), customerStaffDTOResult.getMsg()));
log.warn(String.format("获取工作人员信息失败,手机号[%s],客户id:[%s],code[%s],msg[%s]", formDTO.getMobile(), formDTO.getCustomerId(), customerStaffDTOResult.getCode(), customerStaffDTOResult.getMsg()));
throw new RenException(customerStaffDTOResult.getCode());
}
CustomerStaffDTO customerStaff = customerStaffDTOResult.getData();
@ -498,7 +625,7 @@ public class SsoServiceImpl implements SsoService {
} catch (Exception e) {
throw new RenException(e.getMessage());
}
if (null == userInfo){
if (null == userInfo) {
throw new RenException(EpmetErrorCode.THIRD_PLAT_REQUEST_ERROR.getCode(),
"【SSO enterOrg】调用第三方平台查询用户信息失败,用户信息为空");
}

10
epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/constant/AppClientConstant.java

@ -27,6 +27,10 @@ public interface AppClientConstant {
* PC端:web
*/
String CLIENT_WEB = "web";
/**
* 第三方统一认证登陆
*/
String CLIENT_SSO = "sso_web";
/**
* 微信小程序:wxmp
*/
@ -39,17 +43,17 @@ public interface AppClientConstant {
/**
* 客户来源App
* */
*/
String APP = "app";
/**
* 用户Id
* */
*/
String USER_ID = "userId";
/**
* 客户端
* */
*/
String CLIENT = "client";
/**

Loading…
Cancel
Save