华为云云商店联营SaaS单点登录案例原创
金蝶云社区-陈来珍
陈来珍
0人赞赏了该文章 251次浏览 未经作者许可,禁止转载编辑于2024年02月02日 17:20:35

关键词: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

image.png

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接口获取用户信息(第一步同步下来的用户信息),完成用户登录。

image.png

三、实现过程

【添加生产地址】-【开发调测联营saas接口】-【凭证与测试账号申请】-【开发单点登录功能】

1、在卖家中心添加生产地址image.png

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

image.png

基础接口开发完成之后,部署到isv的服务器,然后就可以在华为云商店调用接口测试

image.png

image.png

(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接口中的五个固定地址。

image.png

3、凭证与测试账号申请

(1)凭证申请

生产地址:前面接口调测成功的地址,下拉列表可以选择到

公钥(密钥长度>=3072bit,填充方式OAEP):RSA密钥对在线生成工具RSA密钥对在线生成工具2image.png

(2)申请测试账号image.pngimage.png

4、单点登录功能开发

(1)登录地址重定向

苍穹平台的单点登录插件,实现接口

public class SSODemo implements ThirdSSOAuthHandler

重定向到测试账号的统一认证登录地址

@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));
}

image.png

(2)获取用户token

    getTrdSSOAuth方法中根据云商店返回的code信息去获取用户token,具体请参考联营能力开放接口的/api/v1/oauth2/token接口定义

image.png

(3)获取用户信息

      根据/api/v1/oauth2/userinfo接口及第(2)步获取到的token去获取用户信息,完成用户登录。       

      由于在前面的接口中,并没有实际把云商店同步过来的用户信息,更新到我的saas应用系统中,因此这里获取到的用户信息,并不存在我的saas应用中,所以这里直接setuser指定了我saas应用中存在的账号作为登录账号。

image.png

四、效果图

image.png

五、开发环境版本

V6.0.1

六、参考资料

https://support.huaweicloud.com/accessg-marketplace/zh-cn_topic_0070649102.html



sso.rar(8.71KB)

赞 0