关键词:sso、华为云云商店、联营SaaS商品、登录
一、需求
(1)什么是联营saas商品:
联营SaaS通常针对特定的合作伙伴或市场细分,提供高度定制化的服务,两个或多个品牌共同参与产品的开发和市场推广。
(2)需求细节:
saas应用登录时统一跳转到华为云商店的认证中心进行登录。
二、思路与方案
1、关于接口开发调测
在伙伴(针对华为云商店的伙伴)系统中开发联营saas接口,包括5个基础接口描述和5个联营Kit接口描述,买家在云商店上购买saas商品,处理saas商品绑定企业、新增部门等业务处理时,云商店调用isv开发的接口,把买家的相关信息同步到isv的saas应用系统中。
接口文档:https://support.huaweicloud.com/accessg-marketplace/zh-cn_topic_0070649102.html
2、关于单点登录功能开发
(1)携带appid重定向到统一的登录页面,用户输入账号密码登录
(2) 登录成功后,由浏览器根据redirect_uri跳转回商家SaaS应用主页https://example.com?code= {code}
&tenant={tenant},并将code通过redirect_uri返回给商家;
(3) 根据返回的code获取access_token与refresh_token,具体请参考联营能力开放接口的/api/v1/oauth2/token接口定义。
(4) 根据/api/v1/oauth2/userinfo接口获取用户信息(第一步同步下来的用户信息),完成用户登录。
三、实现过程
【添加生产地址】-【开发调测联营saas接口】-【凭证与测试账号申请】-【开发单点登录功能】
1、在卖家中心添加生产地址
2、开发接口与调测
(1)基础接口开发
五个基础接口使用同一个url,根据云商店请求的数据,根据参数activity识别请求的是五个基础接口中的哪个,然后分别存储到数据库中,并返回信息给云商店。
(这里是做登录案例,所以就接口直接返回了成功的信息给云商店)
@Controller public class HuaweiSaaSCloudController { protected Logger logger = LoggerFactory.getLogger(getClass()); @Autowired HuaweiSaaSCloudService huaweiCloudService; private static String accessKey="生产地址管理中的key值"; @ResponseBody @GetMapping("api/saasSync") public void produceAPI(HttpServletRequest req,HttpServletResponse res) { //Map<String, String[]> paramsMap = request.getParameterMap(); // if(HuaweiUtils.verificateRequestParams(request, accessKey, 256)) { // HWResponseResult hwResponseResult=new HWResponseResult(); // hwResponseResult.setResultCode("000002"); // hwResponseResult.setResultMsg("请求参数不合法!!"); // return hwResponseResult; // } //if("newInstance".equals(paramsMap.get("activity")[0])) { //表示新购商品 HWResponseResult s=new HWResponseResult(); try { s = huaweiCloudService.sassProduceAPI(req); } catch (ParseException e1) { e1.printStackTrace(); } String json=JSONObject.toJSONString(s); String ss=""; try { ss=HuaweiUtils.generateResponseBodySignature(accessKey, json); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } String dd="sign_type=\"HMAC-SHA256\", signature=\""+ss+"\""; res.addHeader("Body-Sign", dd); JSONObject.toJSONString(s); try { res.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); res.getWriter().write(JSONObject.toJSONString(s)); } catch (IOException e) { e.printStackTrace(); } } }
//响应结果,直接返回true public HWResponseResult sassProduceAPI(HttpServletRequest request) throws ParseException { HWResponseResult hwResponseResult=new HWResponseResult(); hwResponseResult.setResultCode("000000"); hwResponseResult.setResultMsg("success接口成功了"); return hwResponseResult; }
//根据key值加密响应体 public static String generateResponseBodySignature(String key, String body) throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException { return base_64(hmacSHA256(key, body)); }
key值查看路径:https://console.huaweicloud.com/marketplace/isv/?region=cn-north-4#/console/productionAddressMGT
基础接口开发完成之后,部署到isv的服务器,然后就可以在华为云商店调用接口测试
(2)联营kit接口开发
在基础接口(/api/saasSync)的基础上拼接上+固定地址,以下五个固定地址是约定好的,不能更改。这5个接口由isv方系统的服务提供给华为云商店调用,用于同步租户信息、domainName(生产环境登录时获取用户token时用到的域名地址)等到isv的数据库中。
(这里是做登录案例,所以接口直接返回了成功的信息给云商店,处理代码和基础接口一样)
/api/saasSync+/produceAPI/tenantSync /api/saasSync+/produceAPI/applicationSync /api/saasSync+/produceAPI/authSync /api/saasSync+/produceAPI/singleOrgSync /api/saasSync+/produceAPI/allOrgSync
开发完成kit接口之后,就可以调测。注意这里调测时填入的生产接口地址和前面新购商品等5个接口调测时填入的地址一样,实际上云商店会自动在后台填充了联营kit接口中的五个固定地址。
3、凭证与测试账号申请
(1)凭证申请
生产地址:前面接口调测成功的地址,下拉列表可以选择到
公钥(密钥长度>=3072bit,填充方式OAEP):RSA密钥对在线生成工具,RSA密钥对在线生成工具2
(2)申请测试账号
4、单点登录功能开发
(1)登录地址重定向
苍穹平台的单点登录插件,实现接口
重定向到测试账号的统一认证登录地址
@Override public void callTrdSSOLogin(HttpServletRequest request, HttpServletResponse response, String backUrl) { // 退出处理 if (request.getRequestURI().contains("logout.do")) { logout(request); SSOUtil.sendRedirect(response, "http://localhost:8080/ierp"); return; } //判断是否成功登录 金蝶云通过code进行判断 String c = request.getParameter("code"); String s = request.getParameter("tenant"); if (StringUtils.isNotEmpty(c) && StringUtils.isNotEmpty(s)) { return; } //sso插件重定向处理 if (request.getQueryString() != null && request.getQueryString().contains("flag=1")) { return; } //正常登录访问苍穹,构造缓存数据 MultiMap<String> queryParameters = ((Request) request).getQueryParameters(); TargetInfo targetInfo = SSOUtil.buildTargetInfo(queryParameters); targetInfo.getParam().put("queryParam", request.getQueryString()); //如果请求的url中有 logout表示是从退出的接口过来的。需要 到首页 或者登录页面页面 request.getRequestURI() ,同时最好清除相关token缓存 //退出处理,默认到首页 //缓存数据,因为tenant参数可以保持同步返回,所以用来进行模拟线程安全处理,10分钟过期 String tenant = ID.genStringId(); targetInfo.setState(tenant); DistributeSessionlessCache cache = CacheFactory.getCommonCacheFactory().getDistributeSessionlessCache("ssoLogin"); cache.put(tenant, JSONObject.toJSONString(targetInfo), 60); //根据sso地址构造,登录地址 重定向到云平台 SSOUtil.sendRedirect(response, SSOUtil.buildLoginUrl(targetInfo, request)); }
(2)获取用户token
getTrdSSOAuth方法中根据云商店返回的code信息去获取用户token,具体请参考联营能力开放接口的/api/v1/oauth2/token接口定义
(3)获取用户信息
根据/api/v1/oauth2/userinfo接口及第(2)步获取到的token去获取用户信息,完成用户登录。
由于在前面的接口中,并没有实际把云商店同步过来的用户信息,更新到我的saas应用系统中,因此这里获取到的用户信息,并不存在我的saas应用中,所以这里直接setuser指定了我saas应用中存在的账号作为登录账号。
四、效果图
五、开发环境版本
V6.0.1
六、参考资料
https://support.huaweicloud.com/accessg-marketplace/zh-cn_topic_0070649102.html
sso.rar(8.71KB)
推荐阅读