持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情
1. SSO统一登录Oauth2.0简化模式对接
1.1 实现效果
用户访问ncc系统时,有两种登录方式,一是输入用户密码登录,二是通过统一身份认证系统登录时。若统一身份认证系统未登录,则跳转到统一身份认证系统进行登录后,单点登录到ncc系统;若已登录,直接单点登录到ncc系统。
1.2 业务流程
1.3 时序图
2. 单点登录到ncc
2.1 工作流程
a. 客户端向服务端发起登陆NCC请求;
b. 向NCC服务器注册校验用户登陆和上下文信息;
c. 如果校验成功NCC服务器响应给客户服务器token信息;
d. 客户服务器将token响应给客户端;
f. 客户端收到token后拼接请求ncc节点的url信息;
e. NCC收到请求并验证token是否合法,如果合法,则重定向到客户端请求的节点页面。
2.2 具体配置流程
2.2.1 NCC端设置
在NCC的系统注册表sm_oauth_security注册第三方系统
2.2.1.1 表中各字段含义
- CLIENT_ID:第三方系统编码,必需项
- CLIENT_NAME: 第三方系统名称,非必需
- CLIENT_SECURITY: 第三方系统和NCC共同维护的秘钥对
- PK_OAUTH_SECURITY: 主键
- CLIENT_URL: 第三方系统的url (供NCC集成访问第三方系统使用,本环节不需要)
- CLIENT_AUTHCLASS: 登录第三方系统授权类 (供NCC集成访问第三方系统使用,本环节不需要)
- PK_GROUP:非本环节使用,设置为空
2.2.1.2 注册sql
insert into sm_oauth_security (CLIENT_AUTHCLASS, CLIENT_ID, CLIENT_NAME, CLIENT_SECURITY, CLIENT_URL, DR, PK_GROUP, PK_OAUTH_SECURITY, TS)
values (null, 'scjcoa', 'oa', 'qfidufeiuvsvieaguaisfjfgaeu', null, null, '0001A210000000000YQ8', 'scjcoa', '2022-10-03 14:08:34');
2.2.2 第三方系统设置
2.2.2.1 通过秘钥对获取登录token,第三方服务访 http://ip:port/service/genThirdPartyAccessToken
同时访问参数为:
- type 获取方式,此方式为固定为 type_security且必需项;
- dsname 数据源名称,必需项;
- usercode NCC用户编码,必需项;
- langcode 多语语种,非必需项,为空默认中文语种;
- busicentercode 账套编码,非必需项,为空登录时会循环在数据源中查找用户;
- ts ,第三方系统加签的时间,用来生成校验秘钥对,必需项;
- client_id第三方系统id,即第一步在sm_oauth_security注册的系统编码,必需项;
- security第三方由共同维护的秘钥对根据给定的算法自己生成的秘钥值,必需项。 security是通过SHA256加签,其中是根据usercode,ts,client_security和当前系统时间动态拼接的字符串生成。
2.2.2.2 提供登录NCC系统URL,token是从第二步成功返回结果,该值默认保留1分钟,超时或使用过一次则失效
URL信息如下:
- http://ip:port/uap/rbac/thirdpartylogin/main/index.html?accesstoken=xxx &redirect_uri=http://ip:port/nccloud;
- ip和port是NCC的服务地址的ip和端口号;
- http://ip:port/uap/rbac/thirdpartylogin/main/index.html 为固定地址;
- accesstoken=xxx为(4)中获取的临时token;
- redirect_uri=http://ip:port/nccloud 为成功登录后要重定向的地址,如后面为空,默认跳到工作桌面(即首页)。如果是列表或卡片节点,需改为节点的url的地址。如果是审批详情页面,需要再次开发,因为审批详情页面的url不同其他页面,需要向NCC服务器请求获取。拼接完成访问url时,NCC服务器收到该请求,会验证token和用户登录ncc权限,验证通过则重定向到redirect_uri。
2.3 获取TOKEN 用于单点登陆
2.3.1 直接通过注册获取 access_token
private String registerSSOToken(UserVO securityUser) throws BusinessException {
InvocationInfoProxy.getInstance().setUserId(securityUser.getCuserid());
String access_token = RandomUtils.genRandomNumber(0, "");
NCCSSORegInfo ssoInfo = new NCCSSORegInfo();
ssoInfo.setUsercode(securityUser.getUser_code());
ssoInfo.setLangCode(Language);
ssoInfo.setBusiCenterCode(BizCenterCode==null?"NCC":BizCenterCode);
ssoInfo.setAccess_token(access_token);
INCCSSOService lookup =NCLocator.getInstance().lookup(INCCSSOService.class);
lookup.registerSSOInfo(ssoInfo);
return access_token;
}
2.3.2 直接通过请求获取 access_token
public class Test {
public static void main(String[] args) throws Exception {
// 在NC Cloud的系统注册表sm_oauth_security注册第三方系统
String dsname = "nccloud_01";//数据源名称
String usercode = "wst1";// ncc用户编码
String client_id = "wst";// 第三方系统id
String client_security = "qfidufeiuvsvieaguaisfjfgaeu";// 第三方秘钥
String nccUrl = "http://127.0.0.1:8088/";
URL preUrl = new URL(nccUrl + "service/genThirdPartyAccessToken");
URLConnection uc = preUrl.openConnection();
uc.setDoOutput(true);
uc.setUseCaches(false);
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
uc.setRequestProperty("Content-Length", "10000");
uc.setRequestProperty("userid", usercode);
HttpURLConnection hc = (HttpURLConnection) uc;
hc.setRequestMethod("POST");
OutputStream os = null;
DataOutputStream dos = null;
String returnFlag = "";
InputStream is = null;
try {
StringBuffer sb = new StringBuffer();
String ts = System.currentTimeMillis() + "";
String security = genKey(usercode, usercode + client_security + ts.substring(0, 6));
// 处理http请求参数+号变成空格问题
security = security.replaceAll("\\+", "%2B");
sb.append("type=type_security&ts=" + ts + "&dsname=" + dsname + "&usercode=" + usercode + "&client_id="
+ client_id + "&security=" + security);
os = hc.getOutputStream();
dos = new DataOutputStream(os);
dos.writeBytes(sb.toString());
dos.flush();
is = hc.getInputStream();
int ch;
while ((ch = is.read()) != -1) {
returnFlag += String.valueOf((char) ch);
}
System.out.println("ncc-token"+returnFlag);
String nccApiUrl = nccUrl;
StringBuffer sso_url = new StringBuffer();
//http://ip:port/uap/rbac/thirdpartylogin/main/index.html?accesstoken=xxx &redirect_uri=http://ip:port/nccloud
sso_url.append(nccApiUrl + "nccloud/sso/thirdPartyLogin.sso?accesstoken=" + returnFlag);
sso_url.append("&redirect_uri="+nccApiUrl+"nccloud");
System.out.print("sso_url:"+sso_url.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (Exception e2) {
}
}
if (os != null) {
try {
os.close();
} catch (Exception e2) {
}
}
if (is != null)
try {
is.close();
} catch (Exception e2) {
}
}
}
private static String genKey(String userid, String key) throws Exception {
return Base64Util.encryptBASE64((SignatureTookKit.digestSign(userid.getBytes(), key.getBytes())));
}
2.4 HttpServlet接口为例
public class ThirdPartyAccessTokenServlet extends HttpServlet implements IHttpServletAdaptor {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doAction(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doAction(req, resp);
}
public void doAction(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 初始化环境变量
// 获取access_token
// 执行跳转
}
}
2.5 初始化环境变量
2.5.1 baseinfo.properties配置
#数据源
UserDataSource=design
#集团
GroupId=0001X1100000000003VE
#接口用户ID
UserId=1001X11000000000000W
#接口用户编码
UserCode=cyz
#业务中心代码--单点登陆使用开发环境develop生产环境是账套编码
BizCenterCode=NCC
# 开发环境3006 生产环境以设定的端口号为准
NccWebAddress=http://127.0.0.1:3006
# 固定跳转地址 (开发环境3006 生产环境以设定的端口号为准)
localweburl=http://127.0.0.1:3006/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?
2.5.2 读取环境变量并进行设置
private void environmentProxy(HttpServletRequest request) throws Exception {
String UserDataSource = PropertiesUtils.getInstance().getStrValue("UserDataSource");
String GroupId = PropertiesUtils.getInstance().getStrValue("GroupId");
String BizCenterCode = PropertiesUtils.getInstance().getStrValue("BizCenterCode");
InvocationInfoProxy.getInstance().setGroupId(GroupId);
InvocationInfoProxy.getInstance().setUserDataSource(UserDataSource);
InvocationInfoProxy.getInstance().setBizCenterCode(BizCenterCode);
}
2.6 执行跳转到NCC桌面
String nccWebAddress = PropertiesUtils.getInstance().getStrValue("nccWebAddress");
String toUrl = localweburl + "accesstoken=" + access_token + "&redirect_uri=" + nccWebAddress+ "/nccloud";
response.sendRedirect(toUrl);
//http://ip:port/uap/rbac/thirdpartylogin/main/index.html?accesstoken=xxx&redirect_uri=http://ip:port/nccloud