适配版本
4.7.8
之前的版本
概述
在企业内部,对于已有一套完整的登录系统(SSO)的情况下,通常会要求把所有的系统都对接到SSO中;本文主要讲解用Oinone开发的项目对接SSO的具体实现。
对接步骤
1、项目自定义实现UserCookieLogin,可参考默认是的示例说明:
pro.shushi.pamirs.user.api.login.UserCookieLoginFree
2、具体的对接示例
package pro.shushi.pamirs.demo.core.sso;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import pro.shushi.pamirs.demo.core.sso.constant.HttpConstant;
import pro.shushi.pamirs.demo.core.sso.constant.SSOConstant;
import pro.shushi.pamirs.demo.core.sso.constant.SessionUserTypeEnum;
import pro.shushi.pamirs.demo.core.sso.model.ApiCommonTransient;
import pro.shushi.pamirs.demo.core.sso.utils.AuthenticateUtils;
import pro.shushi.pamirs.demo.core.sso.model.PermissionInfoResp;
import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j;
import pro.shushi.pamirs.meta.api.dto.model.PamirsUserDTO;
import pro.shushi.pamirs.meta.api.dto.protocol.PamirsRequestVariables;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.meta.common.exception.PamirsException;
import pro.shushi.pamirs.meta.common.spring.BeanDefinitionUtils;
import pro.shushi.pamirs.meta.common.util.UUIDUtil;
import pro.shushi.pamirs.resource.api.enmu.UserSignUpType;
import pro.shushi.pamirs.user.api.cache.UserCache;
import pro.shushi.pamirs.user.api.constants.UserConstant;
import pro.shushi.pamirs.user.api.enmu.UserExpEnumerate;
import pro.shushi.pamirs.user.api.enmu.UserLoginTypeEnum;
import pro.shushi.pamirs.user.api.login.IUserLoginChecker;
import pro.shushi.pamirs.user.api.login.UserCookieLogin;
import pro.shushi.pamirs.user.api.login.UserCookieLoginSimple;
import pro.shushi.pamirs.user.api.model.PamirsUser;
import pro.shushi.pamirs.user.api.model.tmodel.PamirsUserTransient;
import pro.shushi.pamirs.user.api.service.UserService;
import pro.shushi.pamirs.user.api.utils.CookieUtil;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;
/**
*
* @author wangxian
*
* 完全自定义login的过程
* 需要实现登陆部分login 以及拦截部分fetchUserIdByReq
* 如果fetchUserIdByReq返回值为null的时候 将会被拦截
*/
@Slf4j
@Order(0)
@Component
public class DemoUserSSOCookieLogin extends UserCookieLogin<PamirsUser> {
//刷新令牌
private static String REFRESH_TOKEN = "refreshToken";
//系统id
private static String CLIENT_ID = "client-id";
//访问令牌
private static String AUTHORIZATION = "Authorization";
private IUserLoginChecker checker;
@Autowired
private UserService userService;
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Override
public String createSessionId(HttpServletRequest request, PamirsUser idModel) {
return UUIDUtil.getUUIDNumberString();
}
@Override
public String type() {
return UserLoginTypeEnum.COOKIE.value();
}
@Override
public PamirsUser resolveAndVerification(PamirsUserTransient user) {
if (checker == null) {
checker = BeanDefinitionUtils.getBean(IUserLoginChecker.class);
}
return checker.check4login(user);
}
/**
* 重写登录拦截功能
* 该函数主要作用,通过三方权限校验.
* @param request
* @return
*/
@Override
public PamirsUserDTO fetchUserIdByReq(HttpServletRequest request) {
PamirsRequestVariables pamirsRequestVariables = PamirsSession.getRequestVariables();
log.debug("==cookie== {}", JSON.toJSONString(request.getCookies()));
log.debug("==headNames== {}", JSON.toJSONString(request.getHeaderNames()));
log.debug("==params=={}",JSON.toJSONString(request.getContextPath()));
String sessionId = CookieUtil.getValue(request, "pamirs_uc_session_id");
PamirsUserDTO pamirsUserDTO = UserCache.get(sessionId);
if (pamirsUserDTO ==null) {
//H5-企业微信登录,其他SSO登录。获取标识。根据实际情况修改和适配
String accessToken = request.getParameter("accessToken");
ApiCommonTransient permissionInfo = AuthenticateUtils.getPermissionInfo(accessToken);
// *******登录成功的条件判断,各SSO根据情况自行修改********
if(HttpConstant.SUCCESS.equals(permissionInfo.getCode())) {
// SSO用户换 Oinone 的用户
PamirsUser pamirsUser = setUserInfoToCookiesAndSetUserIdToCache(permissionInfo,accessToken);
return new PamirsUserDTO().setUserId(pamirsUser.getId()).setPhone(pamirsUser.getPhone()).setUserCode(
pamirsUser.getCode()).setLogin(pamirsUser.getLogin()).setEmail(pamirsUser.getEmail()).setUserName(pamirsUser.getName());
} else {
//用户未登录,并且token未获取到用户null(根据实际情况修改)
return null;
}
} else {
return fetchUserIdByReq4Pamirs(request);
}
}
/**
* 开放一个用户登录setCookies函数 供登录和跳转校验
* @param permissionInfo
* @param accessToken
* @return
*/
public PamirsUser setUserInfoToCookiesAndSetUserIdToCache(ApiCommonTransient permissionInfo, String accessToken) {
String sessionId;
PermissionInfoResp ssoResponseTransient = JSON.parseObject(permissionInfo.getData().toString(), PermissionInfoResp.class);
// *********示例:SSO跟业务系统中用户ID关联;其他关联条件请根据数据情况处理*******
PamirsUser pamirsUser = userService.queryById(ssoResponseTransient.getUserInfo().getId());
if (pamirsUser == null) {
// ********SSO中有用户数据,Oinone的系统中没有需要怎么处理************/
// ********这里仅仅是一个示例,在上述情况下创建用户,请根据实际情况处理,请根据实际情况处理*****/
pamirsUser = createOrUpdatePamirsUser(ssoResponseTransient);
}
HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
HttpServletResponse httpServletResponse = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
UserCookieLoginSimple userCookieLoginSimple = new UserCookieLoginSimple();
sessionId = userCookieLoginSimple.createSessionId(httpServletRequest, null);
String cacheKey = userCookieLoginSimple.parseSessionId(sessionId);
UserCache.putCache(cacheKey, userCookieLoginSimple.coverToUserDTO(pamirsUser));
try {
CookieUtil.set(httpServletResponse, UserConstant.USER_SESSION_ID, sessionId);
} catch (Exception e) {
log.error("SSO Login Cookie Set Err", e);
}
//set accessToken to cookies
String userCodeCacheKey = SSOConstant.USER_REDIS_CACHE + pamirsUser.getId();
redisTemplate.opsForValue().set(userCodeCacheKey,accessToken,3600, TimeUnit.SECONDS);
return pamirsUser;
}
// ********这里仅仅是一个示例,在上述情况下创建用户,请根据实际情况处理,请根据实际情况处理*****/
private PamirsUser createOrUpdatePamirsUser(PermissionInfoResp ssoResponseTransient) {
PamirsUser pamirsUser;
pamirsUser = new PamirsUser();
pamirsUser.unsetEmail();
pamirsUser.unsetPhone() ;
pamirsUser.setId(ssoResponseTransient.getUserInfo().getId());
pamirsUser.setUserType(SessionUserTypeEnum.COMPANY_ADMIN.displayName());
pamirsUser.setSignUpType(UserSignUpType.BACKSTAGE);
pamirsUser.setName(ssoResponseTransient.getUserInfo().getUsername());
pamirsUser.setLogin(ssoResponseTransient.getUserInfo().getUsername());
pamirsUser.setNickname(ssoResponseTransient.getUserInfo().getNickname());
pamirsUser.setRealname(ssoResponseTransient.getUserInfo().getNickname());
pamirsUser.setId(ssoResponseTransient.getUserInfo().getId());
userService.createOrUpdate(pamirsUser);
return pamirsUser;
}
/**
* 原始用户登陆后函数调用
* @param request
* @return
*/
private PamirsUserDTO fetchUserIdByReq4Pamirs(HttpServletRequest request) {
PamirsUserDTO pamirsUserDTO = super.fetchUserIdByReq(request);
if (pamirsUserDTO == null || pamirsUserDTO.getUserId() == null) {
return pamirsUserDTO;
}
PamirsUser user = new PamirsUser().setId(pamirsUserDTO.getUserId()).queryById();
if (user != null && !Boolean.TRUE.equals(user.getActive())) {
//清理下登录的cookie
String sessionId = CookieUtil.getValue(request, UserConstant.USER_SESSION_ID);
if (!StringUtils.isBlank(sessionId)) {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
UserCache.logout(request, response, sessionId);
}
log.error("{}当前用户是{},{}", UserExpEnumerate.USER_CAN_NOT_ACTIVE_ERROR, pamirsUserDTO.getUserId(), pamirsUserDTO.getLogin());
throw PamirsException.construct(UserExpEnumerate.USER_CAN_NOT_ACTIVE_ERROR).errThrow();
}
return pamirsUserDTO;
}
}
3、通常自定义登录的时候需要获取HttpRequest和HttpResponse,从HttpRequest获取请求头或者请求参数,获取方式如下:
// HttpServletRequest获取
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// HttpServletResponse获取
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
对接SSO示例代码包
示例代码包点击可以进行下载:
SS0对接Demo示例
Oinone社区 作者:望闲原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/4747.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验