https://community.yonyou.com/article/detail/1274
https://community.yonyou.com/article/detail/207
https://community.yonyou.com/article/detail/165
1、单点登录的流程
2、单点登录的流程简化
客户端只需要发起单点登录的请求,省去获取token,封装单点登录url的过程,NCC服务器直接返回单点登录的url,按照这个思路实现单点登录。
3、NCC表中注册第三方系统信息
在NC Cloud的系统注册表sm_oauth_security注册第三方系统(插入一条数据)
表中各字段含义如下:
- CLIENT_ID :第三方系统编码,必需项
- CLIENT_NAME: 第三方系统名称,非必需
- CLIENT_SECURITY: 第三方系统和NC Cloud共同维护的秘钥对
- PK_OAUTH_SECURITY: 主键
- CLIENT_URL: 第三方系统的url (供NC Cloud集成访问第三方系统使用,本环节不需要)
- CLIENT_AUTHCLASS: 登录第三方系统授权类 (供NC Cloud集成访问第三方系统使用,本环节不需要)
- PK_GROUP:非本环节使用,设置为空
4、白名单设置
在home/ierp/sf/nccssoConfig.xml中配置白名单,如果无需单独处理权限,可以在第一个authenticator标签的listParam中配置ip白名单
如果需要单独定单点登录权限可以在第二个中处理。一般只需在第一个中配置即可。
<?xml version="1.0" encoding="UTF-8"?>
<NCCSSOConfigVO>
<authenticator id="default" classname="ncc.sso.bs.DefaultNCCSSOAuthenticator">
<regTimeOut>200</regTimeOut>
<listParam key="IPAddress">
<string>127.0.0.1</string>
<string>10.11.115.14</string>
</listParam>
</authenticator>
<authenticator id="type" classname="nc.sso.bs.AAA">
<regTimeOut>200</regTimeOut>
<listParam key="IPAddress">
<string>127.0.0.1</string>
</listParam>
</authenticator>
</NCCSSOConfigVO>
5、单点登录案例代码
单点登录使用的jar包

###查看client_id和client_security
>>>>>select * from sm_oauth_security
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLConnection;
import nccloud.security.impl.SignatureTookKit;
import org.apache.commons.codec.binary.Base64;
public class PostThirdPartyAccessTokenTest {
public static String BaseUrl = "http://ip:port";
public static void main(String[] args) throws Exception{
String dsname = "nccdb";//数据源的编码,本地开发为design
String usercode = "100134";//用户的编码,需要用户可以正常登陆
String client_id = "nccapi";//第三方系统id,
String client_security = "*****c02be45fffe2***********";//第三方秘钥
String busicentercode = "001";//账套编码,本地开发时为develop
String url=BaseUrl+"/service/genThirdPartyAccessToken";
String security = genKey(usercode,usercode + client_security + (System.currentTimeMillis() + "").substring(0, 6));
String write="type=type_security&dsname="+dsname+"&usercode="+usercode+"&client_id="+client_id+"&security="+security+"&busicentercode="+busicentercode;
write=write.replaceAll("\\+","%2B");//避免出现特殊符号问题。
//获取token
String token = getToken(url,write);
if("".equals(token)) {
System.out.println("获取token失败");
return;
}
System.out.println("获取的token为:"+token);
System.out.println("单点登陆路径为:"+getBaseRedirectUrl(token));
// System.out.println("审批详情单点登陆路径为:"+getMsgCenterRedirectUrl(token));
// System.out.println("单点登陆到单据详情:"+getBillDetailRedirectUrl(token));
}
/**
* 单点登录到首页:http://127.0.0.1:8080/nccloud
* @param token 单点登录获取到的token
* */
private static String getBaseRedirectUrl(String token) {
//单点成功后的跳转路径
String redirect_uri = BaseUrl+"/nccloud";
//单点登陆时的全路径,可以直接粘贴到浏览器进行访问。
String fullUrl=BaseUrl+"/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?accesstoken="+token+"&redirect_uri="+redirect_uri;
return fullUrl;
}
/**
* 单点登陆到单据详情,单据节点打开对应的单据
* 这里只是拼了单点登陆的url,前端节点需要this.props.getUrlParam('id')获取单据id
* 将id查询出来后对单据进行展示
* @param token 单点登陆获取到的token
* */
private static String getBillDetailRedirectUrl(String token) throws UnsupportedEncodingException {
String billId="1001A1100000018BIE2E";//单据id--例如本例子的采购订单 select pk_order from po_order where 1=1 and vbillcode='CD2025020800003436'
String appcode="400400800";//单据应用编码
String pagecode="400400800_card";//单据页面编码
StringBuffer redirectUrl = new StringBuffer();
redirectUrl.append(BaseUrl+"/nccloud/resources/workbench/public/common/main/index.html#/ifr?ifr=");
redirectUrl.append( URLEncoder.encode(URLEncoder.encode("/nccloud/resources/pu/pu/poorder/main/index.html#/card?id="+billId+"&status=browse&scene=linksce","UTF-8"),"UTF-8"));//这里拼的路径是节点打开后iframe 标签src的路径。
redirectUrl.append("&b1="+URLEncoder.encode(URLEncoder.encode("供应链","UTF-8"),"UTF-8"));//b1,面包屑导航,首页后第一级
redirectUrl.append("&b2="+URLEncoder.encode(URLEncoder.encode("采购管理","UTF-8"),"UTF-8"));//b2,面包屑导航,第二级
redirectUrl.append("&b3="+URLEncoder.encode(URLEncoder.encode("采购订单","UTF-8"),"UTF-8"));//b3,面包屑导航,第三级
redirectUrl.append("&n="+URLEncoder.encode(URLEncoder.encode("采购订单维护","UTF-8"),"UTF-8"));//n,菜单名字
redirectUrl.append("&c="+appcode);//应用编码
redirectUrl.append("&p="+pagecode);//页面编码
redirectUrl.append("&ar=0001Z81000000002UHUZ");//应用注册对应的小应用主键,这里示例代码用的客户申请单
String fullUrl =BaseUrl+"/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?accesstoken="+token+"&redirect_uri="+redirectUrl.toString();
return fullUrl;
}
/**调用接口获取token
*
* @param url 要调用的接口
* @param write 需要写出的数据
* @return token值
* */
private static String getToken(String url,String write) {
OutputStream outStream=null;
DataOutputStream dataOutput=null;
InputStream inStream = null;
String ret="";
try {
URL preUrl = new URL(url);
URLConnection con = preUrl.openConnection();
//设置为true,后面可以调用getOutputStream并传输数据
con.setDoOutput(true);
//不使用http缓存
con.setUseCaches(false);
//设置http请求头
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Content-Length", "10000" );
HttpURLConnection httpCon = (HttpURLConnection) con;
//这里使用post方式调用接口
httpCon.setRequestMethod("POST");
//获取输出流
outStream = httpCon.getOutputStream();
dataOutput = new DataOutputStream(outStream);
//接口需要的参数作为字节序列写入输出流
dataOutput.writeBytes(write);
dataOutput.flush();
//获取输入流
inStream = httpCon.getInputStream();
//读取服务返回的数据
int ch;
while ((ch = inStream.read()) != -1) {
ret += String.valueOf((char) ch);
}
} catch (Exception e) {
System.out.println(e);
} finally {
//关闭服务输入流和输出流
if (dataOutput != null) {
try {
dataOutput.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
if (outStream != null) {
try {
outStream.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
if (inStream != null) {
try {
inStream.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
}
//返回读取的token
return ret;
}
private static String genKey(String userid,String key) throws Exception{
return new Base64().encodeToString(SignatureTookKit.digestSign(userid.getBytes(), key.getBytes()));
}
}
在单点登录跳转到单据详情页面的时候,应该赋什么值到对应的b1、b2、b3、n、c、p等参数呢?


**记得两次解码,因为跳转拼接的时候是两次urlencode**