# 景安统一认证-安全访问控制接入

# 前言

安全访问控制设计主要用于A8用户和第三方应用用户可以实现安全的免密跳转,适用以下场景: 【场景1】 第三方系统作为企业统一门户,用户登录第三方后单点登录V5系统应用。 【场景2】 第三方系统作为企业统一信息平台,集成V5待办/消息。用户登录第三方后,直接打开并处理V5待办。

因此设计接安全访问控制接口ctp-auth-api,由A8系统接入该接口,允许通过该接口认证的请求自动登入A8。 ctp-auth-api的实现者仅需要关注接口的实现即可。

# 接入说明设计图

1659419639794.png

# 接入说明

分别设计[SP模式]和[IDP模式]解决以上两种场景问题,[SP模式]API分为server和client两端,分别用于识别认证token和颁发token 。server端集成到A8系统中,client端集成到第三方系统中 ;   [IDP模式]API分为server和client两端,分别用于识别认证token和颁发token。 server端集成到A8系统中,client端集成到第三方系统. server端充当认证中心,A8和第三服务分别调用server SDK和client SDK获取、校验token.

[SP模式] [SP模式]模式在A8端均是通过注册TokenAuthenticator的实现类到spring容器中,注册的bean name和TokenAuthenticator.authenticatorName(server端) ClientTokenProvider.authenticatorName(client端)相同。

当从第三方跳转到A8时,调用ClientTokenProvider获取认证名称和认证token, 然后使用ClientTokenProvider.REQUEST_AUTH_AUTHENTICATOR和ClientTokenProvider.REQUEST_AUTH_TOKEN 组装URL并重定向到A8系统中, A8系统根据REQUEST_AUTH_AUTHENTICATOR获取对应的TokenAuthenticator实现类,根据REQUEST_AUTH_TOKEN 获取token, 然后使用TokenAuthenticator对token认证,并返回认证成功后的用户ID信息,然后使用用户ID做自动登录。

[SP模式]仅支持从第三方跳转到A8系统。 ctp-auth-api的实现者需要对token的时效性,有效性,安全性等做保证 TokenAuthenticator.authenticatorName(server端) = ClientTokenProvider.authenticatorName(client端) = request.getParameter(TOKEN_AUTH_AUTHENTICATOR) [IDP模式] [IDP模式]和[SP模式]雷同,不同的是[IDP模式]不仅支持从第三方免密跳转到A8系统,还支持A8系统免密跳转到第三方应用.并且client SDK接管第三方应用的认证。 送第三方跳转到A8系统是和[sp模式相同],当从A8系统第三方系统时,需要第三方系统做一定改造,即通过A8系统跳转token的认证后实现自动登录。

从A8系统跳转到第三方的过程为:1. 从服务器端获取Token认证器接口IdpTokenAuthenticator的实现(获取方式和[SP模式]相同),并调用接口IdpTokenAuthenticator.createToken 获取token,然后通过连接返回到第三方系统。 2. 第三方系统接收到请求后,在客户端使用接口 IdpClientAuthenticator.checkAndGetThirdUserId校验并获取第三方系统用户ID。

[IDP模式]既支持SP模式的跳转(接入相同)也支持从A8系统跳转到第三方系统 客户端:IdpClientAuthenticator extends ClientTokenProvider 服务端:IdpTokenAuthenticator extends TokenAuthenticator

# 致远提供能力说明

为SDK实现者提供一定的能力,帮助SDK融入A8中,SDK开发者的所有依赖应该先使用A8相同版本依赖。致远的能力提供在cip-api中,仅依赖该jar即可。

# 1. 数据库存储能力

/**
 * @param sql    要执行的SQL脚本,参数使用?代替
 * @param params 封装到List中的参数列表。添加参数的顺序需要和SQL脚本中的'?'出现的顺序一致。
 *               支持数据类型:
 *               1. 时间{@code java.util.Date}
 *               2. 基础类型或包装类,String
 * @return 返回受影响数据条数(仅update、delete、insert)
 */
public static int execute(final String sql, final List<?> params) {
}

/
 * @param sql      要执行的SQL脚本,参数使用?代替
 * @param params   封装到List中的参数列表。添加参数的顺序需要和SQL脚本中的'?'出现的顺序一致。
 *                 支持数据类型:
 *                 1. 时间{@code java.util.Date}
 *                 2. 基础类型或包装类,String
 * @param pageInfo 分页参数
 * @param sortList 排序参数
 * @return
 */
public ExposePagingResult<List<Map<String, Object>>> queryByPaging(final String sql, final List params, final ExposePageInfo pageInfo, final List<ExposeSort> sortList) {
}

# 2. 缓存能力

参考类:com.seeyon.apps.cip.thirdpartyinterface.expose.ExposeCacheFactory

该缓存主要包装了A8缓存的实现,单机和集群方式也会跟追A8配置改变自动改变,使用者无需关注。

# 2. App绑定/解绑通知

参考类 com.seeyon.apps.cip.thirdpartyinterface.AppExtender

/**
 * App扩展器信息
 *
 * @return
 */
AppExtendInfo extenderInfo();

/**
 * 新增绑定第三方App
 *
 * @param appBindInfo
 */
void bindThirdApp(AppBindInfo appBindInfo);

/**
 * 更新绑定第三方App
 *
 * @param appBindInfo
 */
void updateThirdApp(AppBindInfo appBindInfo);

/**
 * 解绑第三方App
 *
 * @param appBindInfo
 */
void unbindThirdApp(AppBindInfo appBindInfo);

/**
 * 收集第三APP信息,实现动态配置使用
 * <p>
 * AppBindInfo.metaInfoList说明
 * 递归获取属性,如:国家、省、市
 * 传入空参,则返回第一层级列表国家
 * 选择国家则返回已选值和下一个可选择,
 * 如传入中国,返回中国,省的列表,
 * 再传入中国、四川返回中国,四川,市的列表
 *
 * @param appBindInfo
 * @return
 */
List<MetaInfo> configAppInfo(AppBindInfo appBindInfo);

/**
 * 查询App配置信息
 *
 * @param appBindInfo
 * @return
 */
List<MetaInfo> queryAppInfo(AppBindInfo appBindInfo);

/**
 * 为{@code appInfo} 第三方生成客户端使用的配置文件
 *
 * @param appInfo
 * @return
 */
default InputStream generateConfigFileFor(AppBindInfo appInfo) {
 throw new UnsupportedOperationException("current extender do not support.");
}

# 3. 用户绑定/解绑通知

参考类:com.seeyon.apps.cip.thirdpartyinterface.BindingUserListener

/**
 * 新增A8和第三方用户绑定关系
 *
 * @param userBindInfo
 */
void bindUser(UserBindInfo userBindInfo);

/**
 * A8解除和第三方用户的绑定关系
 *
 * @param userBindInfo
 */
void unbindUser(UserBindInfo userBindInfo);

# 案例说明:

# SP模式客户端举例:

//第一步 创建获取认证器实现
IdpClientAuthenticator authClientApp =new XXXIdpClientAuthenticator();
//第二步 创建客户端启动配置,该配置可自定义开发。 如当前配置为传入配置文件的路径
XXXAnAuthAppConfig config = new XXXAuthAppConfig();
config.setConfigFilePath("配置文件路径");
//第三步 注册并激活客户端
authClientApp.register(config);

//第四步 创建TOKEN
AuthUserInfo authUserInfo = new AuthUserInfo();
authUserInfo.setThirdUserId(null);
String token = jinAnAuthClientApp.createToken(authUserInfo);

//第五步 重定向到A8
String url = "http://172.31.15.101:30102";
String redirectUrl ="/seeyon/vreport/vReport.do?method=vReportView&portalId=-8361284883926662329&_resourceCode=F08_report_view";
String url=WebUtil.jumpToOaLoginUrl(host,authClientApp.authenticatorName(),token,redirectUrl)
response.sendRedirect(url);

# SP模式服务端举例:

//第一步 获取认证器名称和token
String token = request.getParameter(TOKEN_AUTH_TOKEN);
String authenticatorName = request.getParameter(TOKEN_AUTH_AUTHENTICATOR);

//第二步 根据token认证器名称获取token认证器
TokenAuthenticator tokenAuthenticator = (TokenAuthenticator) AppContext.getBean(authenticatorName);

//第三部 校验token有效性,并返回token认证结果
AuthResult authResult = tokenAuthenticator.checkAndGetUserIds(token);
if (authResult.getStatus() == AuthStatus.AUTH_FAILED) {
    throw new LoginAuthenticationException(LoginResult.ERROR_UNKNOWN_USER);
} 
//第四步 自动登录
login(authResult.getUserIds().get(0));

# IDP模式A8跳第三方服务端举例:

//第一步 根据token认证器名称获取token认证器
IdpTokenAuthenticator tokenAuthenticator = (TokenAuthenticator) AppContext.getBean(authenticatorName);

//第二步 创建TOKEN
AuthInfo authUserInfo = new AuthInfo();
authUserInfo.setAppId("123").setUserId("1").setThirdUserId("312");
String token = tokenAuthenticator.createToken(authUserInfo);

//第三步 重定向到第三方系统
String url = "http://172.31.15.101:30102/main.do";
String redirectUrl="www.baidu.com";
String sendUrl=WebUtil.jumpToUrl(url,authenticatorName,token,redirectUrl);
response.sendRedirect(url);

# IDP模式A8跳第三方客户端端举例: //第一步 根据token认证器名称获取token认证器 IdpTokenAuthenticator tokenAuthenticator = (TokenAuthenticator) AppContext.getBean(authenticatorName);

//第一步 创建获取认证器实现
IdpClientAuthenticator authClientApp =new XXXIdpClientAuthenticator();
//第二步 创建客户端启动配置,该配置可自定义开发。 如当前配置为传入配置文件的路径
XXXAnAuthAppConfig config = new XXXAuthAppConfig();
config.setConfigFilePath("配置文件路径");
//第三步 注册并激活客户端
authClientApp.register(config);

//第四步 获取并校验TOKEN
String token = request.getParameter(TOKEN_AUTH_TOKEN);//TOKEN_AUTH_TOKEN可自定义
String userId=jinAnAuthClientApp.checkAndGetThirdUserId(token);
创建人:wangxuncd
修改人:suyj