需求背景:
应甲方粑粑要求,公司系统的账号密码太多了,多次登陆很繁琐。需要从人事系统单点登陆到致远OA,实现一个账号一键登录到致远OA的功能。
简要陈述:
每个平台性的系统都有很强的扩展能力,致远OA也不例外,要做个单点登陆完全没有问题的。怎么才可以单点登陆到致远OA呢?我尽量讲的明白一些,从新建工程到部署测试都过一遍,有一丢丢java知识的同学,请往下看。(PS:底部有源码)
原理简述:
- 需要准备一个对称加密后的加密串,用以传递给OA(采取md5加密即可)
- 加密串包含三种信息(登录名,秘钥,时间戳)
- 解密后的登录名直接return即可,交由OA判断这个用户是否存在,存在即可单点登陆;
- 秘钥是双方约定的一个秘钥,也可以自行制定。加密解密用的是同一个即可;
- 时间戳有两个作用。一方面是保证每次传递加密串都不一样,不会被OA拦截;另一方是链接的有效时间的控制,超过约定的时间就不允许单点登陆进OA了。
原理看不太懂,没事没事,那我们从新建工程开始 ~
新建java工程
项目结构
引用jar说明:
关于jar包引用的问题,因为OA版本不同对应的jar也不同,案例中我只提供了最新版的jar。如果发现有版本差异,导致的编译失败问题,可以从实际服务器中拷贝。我在这里告诉你们如何从服务器上获取需要引用的jar包吧。单点登陆只需要两个jar包。
服务器位置:
ApacheJetspeed\webapps\seeyon\WEB-INF\lib\seeyon-cip-api.jar
ApacheJetspeed\webapps\seeyon\WEB-INF\lib\commons-lang.jar
需要的这个两个jar,作用只是完成代码的编译。这两个jar不需要部署到OA服务器上。
代码说明:
代码分为两个部分,一部分是组装带ticket的单点URL,另一个部分是实现OA单点类,我们先看看第一部分是如何操作的。直接上注释代码了
// 准备有效的OA登录名
String loginname = "seeyon1";
// 获取当前登录时间戳
String time = String.valueOf(System.currentTimeMillis());
// 使用同一个加密方法,将登录名,秘钥,时间戳都进行加密,得到签名
String sign = null;
sign = MD5(String.valueOf(loginname) + key + time);
// 使用分隔符_fgf_将登录名,签名,时间戳组装字符串
String ticket = String.valueOf(loginname) + "_fgf_" + sign + "_fgf_" + time;
// 根据具体OA访问ip,得到访问地址后直接用浏览器访问即可
System.out.println(String.format("http://127.0.0.1/seeyon/login/sso?from=OAsso&ticket=%1s",new Object[] { ticket }));
案例中有main方法可以直接生成带ticket的URL,同学们记得换为真实OA的地址。第一部分已经完成了含ticket的URL获取,但是致远OA不认识这个URL和ticket。下面继续代码的第二部分。
- 自定义的类需要继承SSOLoginHandshakeAbstract抽象类
public class OAsso extends SSOLoginHandshakeAbstract{
}
- 自定义的类需要注入到spring,xml配置如下
<bean id="oasso" class="com.seeyon.ctp.portal.sso.SSOLoginContext">
<!-- from 对应name属性 -->
<property name="name" value="OAsso"/>
<property name="forward" value="true"/>
<property name="handshake">
<!-- 使用自己的握手实现 -->
<bean class="com.seeyon.apps.OAsso.OAsso" />
</property>
</bean>
- 创建一个类之后,重写方法handshake
@Override
public String handshake(String ticket) {
}
// 细心的同学已经发现了,这个方法会将外部传进来的ticket,返回的是String类型的登录名
// 也就是说,我把传进来的ticket解析得出一个登录名,交由OA处理即可
- 下面看一下详细的重写handshake方法
@Override
public String handshake(String ticket) {
// ticket为空,返回null,不允许登陆
if (StringUtils.isBlank(ticket)) {
return null;
}
// _fgf_为切割符,ticket切割后没有等于3,返回null,不允许登陆
String[] params = ticket.split("\\s*\\_fgf_\\s*");
if (params.length != 3) {
return null;
}
// 判断时间是否超过半个钟,超过即不允许登陆
if (!isNumerStr(params[2]) && Long.valueOf(params[2]) > 1800000) {
return null;
}
// 使用同一个加密方法,将登录名,秘钥,时间戳都进行加密
String sign = null;
try {
sign = MD5(params[0] + key + params[2]);
} catch (Exception e) {
e.printStackTrace();
return null;
}
// 使用同一个加密方法得到的sign 和传进来的params[1] 对比,一致则返回登录名
// 返回登录名交由OA后台处理,存在这个用户登录名则允许登陆,否则不允许登陆
if (sign.equalsIgnoreCase(params[1])) {
System.out.println("potal----login--" + params[0]);
return params[0];
}
return null;
}
到这里,我想说,致远OA的单点登陆已经开发完成了
同学们就疑惑了,就这?
对,就这。因为我们的疑惑仅仅是对事物的未知。
但我还想说一下,如何部署进OA的,有兴趣的同学,请继续 ~
代码打包
我们需要用到xml打包脚本(仅限于eclipse工具,下面也告诉大家通用性的打包方式)
打包脚本有很多行,我们只关注需要改的第一行就行
我们可以直接右键,跑一下这个xml脚本
控制台出现一下输出,证明已经打包成功了
刷新一下lib目录,打包好的jar包就在lib下了
接下来我们将seeyon目录拷贝出来,覆盖到服务器的seeyon目录即可
服务器目录如下,直接覆盖即可(覆盖就已经部署成功了)
至于其他开发工具的打包,可以将编译后的java代码,直接覆盖到classes下即可。而seeyon目录和上面说的一样,覆盖服务器上的seeyon即可。(服务器上的classes目录如下图)
到这里我们就完成了单点登陆的开发和部署了
咦,还差点什么呢?不验证一下?
气氛都烘托到这里了,安排。
运行效果:
运行前的URL链接
http://127.0.0.1/seeyon/login/sso?from=OAsso&ticket=seeyon1_fgf_48cefd379324d3f1fabf34e460b1bcd3_fgf_1629548168538
// 注意,这个URL不是恒定不变的,是有半个小时有效期的。所以每次单点登陆前都要获取一个最新的
拷贝最新生成的链接到浏览器运行一下,漂亮,单点进去咯
最后补充:
到这里应该不差什么了吧
哦哦,还差资源共享。这里提供一下阿里云盘的链接(百度云盘的老是被和谐)
链接失效可以留言 ~
以上案例源码的阿里云盘,点击获取,获取码是rex7
如果想了解更多的致远OA二次开发的知识,可以看一下我整理的目前最新最详细的内部教程。
在这里说明一下:开发用的开发语言是java,需要的可以获取。
获取更多的内部教程,有兴趣请获取
技术无限,分享有限;如有疑惑,欢迎交流 ~