【已解决】单点登录,不启用token的场景下实现单点登录的技术思路

项目名称:机构运营-机构门户
KOCA版本 :5.0.1
KOCA模块 :admin-basic等
模块版本 :5.0.1
场景 :
机构门户是一个面向互联网的web应用,功能上要把另外一个业务子系统(后面简称F系统,也是双基石的产品)嵌入到门户的页面中去,要解决单点登录的问题,即门户登录后能够在门户中直接打开F系统的首页(已经登录进去到首页工作台),门户除了集成F系统外后面还会集成其他业务子系统,其中F系统是基于koca开发的,版本也很新,但是F系统因客户安全方面的需求,koca-auth安全认证体系使用是session模式,后台auth-strategy > strategy-name:remote走自定义的auth-url 后台没有配置jwt,前端代码工程也关闭了token(JWT_TOKEN_ENABLE=false)。这种技术条件下,机构门户如何实现整合F系统实现单点登录。
问题 :
报错细节 :
因为F系统使用的是session模式,loginType=sso&token=${token} 无效,只能跳转到F系统的登录页。
尝试解决方案:
参考在线文档
http://koca.szkingdom.com:18888/frame/frame/http/sso

我验证了 方式一 通过 loginType=sso 路由参数实现单点登录,集成另外一个业务系统系统(S系统),是支持的,能够实现单点登录,用的是iframe。
但是F系统的session模式,机构门户就不知道怎么实现,寻求一个技术实现思路~~

这是后端层面的解决方案:
机构门户网站集成单点登录功能吗?
可以参考这篇文章:
https://koca.szkingdom.com/koca-base_v5.0.1/Development_Boot/Security_Certification/Security_Develop_Guide.html#十二、koca安全认证单点登录
门户网站是基于koca开发,则参考第十二点
门户网站是外部第三方的,则参考第十三点通过Controller对接SSO

基于admin-basic模块,把默认的token模式改为session模式。后台登录看到成功,前端报会话或认证过期。

auth.yml

koca:
  security:
    strategy: session
    enable: true
    auth-strategy:
      strategy-name: kpbs
    session-storage:
      strategy-name: memory    
    
    auth:      
      randomCodeSwitch: true
      login-page-url: /#/login
      ignored-url:
        - /management/** # 默认全部需要认证
        - /*/v2/api-docs
        - /*/v3/api-docs
        - /*/swagger-resources
        - /bex/api-docs
        - /unity-socket/**
        - /api/gateway/routes   

参照在线文档和论坛帖子写了3个java类:
KpbsLoginServiceImpl.java

@Service
public class KpbsLoginServiceImpl implements LoginService<Principal> {

	private static final Logger logger = LoggerFactory.getLogger(KpbsLoginServiceImpl.class);

	private SpringSecurityProperties springSecurityProperties;

	private RemoteAuthUtilService remoteAuthUtilService;

	public void setRemoteAuthUtilService(RemoteAuthUtilService remoteAuthUtilService) {
		this.remoteAuthUtilService = remoteAuthUtilService;
	}

	public void setSpringSecurityProperties(SpringSecurityProperties springSecurityProperties) {
		this.springSecurityProperties = springSecurityProperties;
	}

	@Override
	public TrustedPrincipal authenticate(Principal principal) throws LoginException {
		
		String loginName = principal.getLoginName();
		String password = principal.getPassword();
		Map othersMap = principal.getOthers();
		logger.info("调试信息 authenticate: " + othersMap);
		
		List dataList = new ArrayList();
		Map userData = new HashMap();
		userData.put("USER_ID", loginName);
		dataList.add(userData);
		
		TrustedPrincipal trustedPrincipal = new TrustedPrincipal();
		
		Map<String, Object> map = new HashMap<>();
		map.put("others", dataList);
		trustedPrincipal.setOthers(map);
		trustedPrincipal.setUserNo(loginName);
		
		return trustedPrincipal;
	}

	@Override
	public String getAuthStrategy() {
		return "kpbs";
	}
	
}

KpbsLoginSuccessSecurityImpl.java

@Service
public class KpbsLoginSuccessSecurityImpl implements LoginSuccess<HttpServletRequest, HttpServletResponse> {
	private static final Logger logger = LoggerFactory.getLogger(LoginSuccessSpringSecurityImpl.class);

	private SpringSecurityProperties springSecurityProperties;

	@Override
	public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
			TrustedPrincipal trustedPrincipal) {
		logger.info("调试信息 LoginSuccessSpringSecurityImpl onLoginSuccess");

		Map<String, Object> map = new HashMap<>(16);
		map.put("loginName", trustedPrincipal.getUserNo());
		map.put("userNo", trustedPrincipal.getUserNo());
		map.put("userName", trustedPrincipal.getUserNo());
		map.put("userCode", trustedPrincipal.getUserNo());		
		map.put(SecurityConstants.OHTERS_NAME, trustedPrincipal.getOthers());

		SecurityResponseUtil.setResponseApplicationUtf8Content(response);
		try {
			String sessionId = request.getSession().getId();
			List otherList = (List)(trustedPrincipal.getOthers().get("others"));
			logger.info("调试信息 onLoginSuccess: " + otherList);
			Map others = (Map)otherList.get(0);
			others.put("SESSION_ID", sessionId);
			
			request.getSession().setAttribute(sessionId, others);
			
			Result<Map<?, ?>> data = new Result<>();
			data.setBody(map);
			SecurityResponseUtil.jsonOut(response, data);
		} catch (IOException e) {
			logger.error(e.getMessage(), e.getCause());
		}
	}

	public void setSpringSecurityProperties(SpringSecurityProperties springSecurityProperties) {
		this.springSecurityProperties = springSecurityProperties;
	}
}

KpbsLoginFailureSecurityImpl.java

前端登录后,后台日志:
[2024-03-19 17:36:36.461] INFO [admin,cffa34e46a87dde3,7461acc7a8f6473b,] 17140 — [http-nio-8081-exec-3] c.s.k.a.s.a.d.KpbsLoginServiceImpl 42: 调试信息 authenticate: {remoteIp=127.0.0.1, sessionid=fc9e7cb7-2850-4c93-9b43-b816e3b3b1c7, others=}
[2024-03-19 17:36:36.461] INFO [admin,cffa34e46a87dde3,7461acc7a8f6473b,] 17140 — [http-nio-8081-exec-3] s.k.a.s.a.d.KpbsLoginSuccessSecurityImpl 33: 调试信息 LoginSuccessSpringSecurityImpl onLoginSuccess
[2024-03-19 17:36:36.462] INFO [admin,cffa34e46a87dde3,7461acc7a8f6473b,] 17140 — [http-nio-8081-exec-3] s.k.a.s.a.d.KpbsLoginSuccessSecurityImpl 46: 调试信息 onLoginSuccess: [{USER_ID=admin}]

前端碰到的问题:



前端工程 config.json, JWT_TOKEN_ENABLE 默认true,改为false问题一样。
请koca老师抽空解答一下~

把token变成session模式的问题已经解决。
总结有以下几点:
1.要把网关改为认证服务者,涉及到pom的修改和auth.yml文件的修改
2.admin-basic要去掉认证服务
3.添加redis,仅网关
4.nginx配置要修改

1 个赞