一、需求及实现
1、需求
一个现实中需求:某公司搭建了一套云平台,面向企业客户,不同的企业客户对此云平台理解和定位不一样,如某企业提出,请将平台名称配置为xxxx,并更改登录页,结合我们的企业文化。这就产生了单点登录cas接收特定参数应用不同的主题。这里接收的参数需要特别说明:按照预设需求,此参数应该是预先制定,可以和cas主题对应的。
2、实现
仍然利用serviceId来匹配不同主题,增加主题等可参照《参照移动端集成单点登录》
访问地址:http:域名/cas?service=http://bussiness1/login?area=2201
对应cas主题设置:
{
"@class": "org.apereo.cas.services.RegexRegisteredService",
"serviceId": "^(https|imaps|http)://.*bussiness1/login\\?area=.*$",
"name": "移动端",
"id": 999,
"description": "移动端登录页",
"evaluationOrder": 1,
"theme": "cloud2201",
"attributeReleasePolicy" : {
"@class" : "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
}
}
serviceId是正则表达式,匹配逻辑:
-
从访问地址中获取service的值:http://bussiness1/login?area=2201
-
二者匹配,如代码
Pattern pattern = RegexUtils.createPattern("^(https|imaps|http)://.*bussiness1/login\\?area=.*$");
boolean b = pattern.matcher("http://bussiness1/login?area=2201").matches();
3、操作流程
具体业务系统url是固定的,所以访问cas地址形式是确定的:如http:域名/cas?service=http://bussiness1/login?area=变量
- 按需求确定area的值
- 定制主题,注意serviceId的值
- 研发界面
即可实现不同企业在使用同一套云平台时,拥有不同主题的登录页面。
二、相关代码
InitialFlowSetupAction.class
private void configureWebflowContextForService(final RequestContext context) {
Service service = WebUtils.getService(this.argumentExtractors, context);
if (service != null) {
LOGGER.debug("Placing service in context scope: [{}]", service.getId());
Service selectedService = this.authenticationRequestServiceSelectionStrategies.resolveService(service);
RegisteredService registeredService = this.servicesManager.findServiceBy(selectedService);
if (registeredService != null && registeredService.getAccessStrategy().isServiceAccessAllowed()) {
LOGGER.debug("Placing registered service [{}] with id [{}] in context scope", registeredService.getServiceId(), registeredService.getId());
WebUtils.putRegisteredService(context, registeredService);
RegisteredServiceAccessStrategy accessStrategy = registeredService.getAccessStrategy();
if (accessStrategy.getUnauthorizedRedirectUrl() != null) {
LOGGER.debug("Placing registered service's unauthorized redirect url [{}] with id [{}] in context scope", accessStrategy.getUnauthorizedRedirectUrl(), registeredService.getServiceId());
WebUtils.putUnauthorizedRedirectUrl(context, accessStrategy.getUnauthorizedRedirectUrl());
}
}
} else if (!this.casProperties.getSso().isAllowMissingServiceParameter()) {
LOGGER.warn("No service authentication request is available at [{}]. CAS is configured to disable the flow.", WebUtils.getHttpServletRequestFromExternalWebflowContext(context).getRequestURL());
throw new NoSuchFlowExecutionException(context.getFlowExecutionContext().getKey(), new UnauthorizedServiceException("screen.service.required.message", "Service is required"));
}
WebUtils.putService(context, service);
}
RegisteredService registeredService = this.servicesManager.findServiceBy(selectedService);
通过此行代码调用下方流程
AbstractServicesManager.class
findServiceBy(final String serviceId)
调用: RegexRegisteredService this.servicePattern.matcher(serviceId).matches()
扩展:
相关代码原理深入分析,待续