根据AD账号直接单点登录到第三方系统
上周在做一个单点登录的任务,今天有时间就整理一下,当时遇到的问题很多,我会慢慢的回忆记录下来。
首先这个单点登录我们要构思一下:
之前的版本是,跳转的链接url是个固定值,它保存到了数据库,我们点击后输入账号密码登录,它是直接从数据库中获取。而现在我们想要实现的功能是,在A系统通过AD账号登录,直接在A系统内点击B系统图标或文字直接跳转到B系统,无需通过账号密码的其他操作直接进入。同时我们也要保障我们传过去的AD账号一定是安全的(不能明文输出),这时需要我们做个加密和解密的过程。
这是我做的一个流程图,仅供参考:
接下来我们就开始进行代码部分
1、在前端相应跳转位置进行传参。
jumpUrl(item) {
//B系统单点
if(item.title == "B系统"){
const params = new FormData();
params.append("userAd", sessionStorage.getItem("userAd"));
this.$post("/getbsystemkey.json", params)
.then(res => {
if (res.data){
if(res.status == "true"){
window.open(this.$bsystemUrl+"account="+res.data);
}
}
})
.catch(err => {
console.log(err);
});
}else{
window.open(item.url);
this.Linklist(item.linkId);
}
这里遇到了一个问题:
这是我的问题及解决办法
接口遇到的坑(一)
2、A系统后台进行加密
在加密之前我们需要准备一个密钥key,同时确保A系统和B系统的密钥是同一个,之后才能进行后面的工作。
2.1 在我们的secretkey.porperties加密钥
这里我们就在网上找工具生成密钥,我一直在用的是这个在线密码生成器
bsystemkey=eAcZD5AtD7f5aN5lC5ALz5d3QM5l0ASS
之后在commonVar中引用这个key
public final static String BSYSTEMKEY= propertieKey.getProperty("bsystemkey");
2.2 A系统中进行加密
/**
* 在A系统中进行加密处理
*/
@RequestMapping(value = "/getbsystemkey")
//将你需要的参数传过去
public ResponseEntity<String> getbsystemkey(Model model, HttpServletRequest request,String userAd) throws Exception{
//yyyy-MM-dd hh:mm:ss为12时制
//yyyy-MM-dd HH:mm:ss为24时制
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// 获取服务器当前时间
String serversDate = sdf.format(Calendar.getInstance().getTime());
// 获取配置的密钥
String bsystemKey=CommonVar.BSYSTEMKEY;
String bsystemContent = userAd+"&"+serversDate;
try{
// 创建ASE工具对象
SymmetricASEEncoder sae = new SymmetricASEEncoder();
String token=sae.AESEncode(bsystemKey, bsystemContent);
/**
* 3.return
*/
return renderData(true, "Success!", token);
}catch (Exception e){
return renderData(false, "Failure!", null);
}
}
此时的token中就带有我们的AD和时间,只不过传过去的时候是加密形式的。
2.3 B系统中解密
if("asystem".equals(appId)){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
boolean flag = false;
// 获取服务器当前时间
String serversDate = sdf.format(Calendar.getInstance().getTime());
// 解密token
AESUtil sae = new AESUtil();
//这里的key一定要和上面定义的保持一致
//将AD和时间进行分割
String[] str = sae.AESDncode("eAcZD5AtD7f5aN5lC5ALz5d3QM5l0ASS",account).split("&");
String userAd = str[0];
String currentTime = str[1];
System.out.println("userAd="+userAd+"currentTime"+currentTime);
//时间对比
flag=compare(serversDate,currentTime);
if(flag){
account=userAd;
}else{
mv.addObject("msg", "单点key已失效,请重新登录!");
}
}
解密中也会重新获取一次本地时间,因为我们想要判断在单点跳转过程中,超过你限制的时间(比如1分钟)它会无法跳转,token失效,需要重新点击在跳转。
/**
* S时间对比工具
* @param time1
* @param time2
* @return
* @throws ParseException
*/
public static boolean compare(String time1, String time2) throws ParseException {
// 如果想比较日期则写成"yyyy-MM-dd"就可以了
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar nowTime = Calendar.getInstance();//得到当前时间
// 将字符串形式的时间转化为Date类型的时间
Date a = sdf.parse(time1);
Date b = sdf.parse(time2);
// 设置当前时间
nowTime.setTime(b);
// 增加1分钟
nowTime.add(Calendar.MINUTE, 1);
b = nowTime.getTime();
System.out.println(b);
// Date类的一个方法,如果a早于b返回true,否则返回false
if (a.before(b))
return true;
else
return false;
}
我的这部分是写到了我之前写好的一个接口里,因为我发现在我新写的接口时,无论怎么加都无法跳转到我写的接口内,而是直接跳转到登录页,(因为我是后接手这个代码具体它的结构和用法还不是很清楚),所以放弃了新写的接口,直接利用之前写好的,你们在写的时候可以自行考虑哈。我的这个仅供参考哈。
3.测试
接下来我们就先校验,我们穿过来的token是否解析成功
因为他是两个项目,所以正常情况下是同时启动2个项目来做测试,但是我的eclipse和电脑有点low,所以只能启动一个哈。
所以我们就在A系统中写一个main方法做测试,然后启动B系统,最后将这个链接放到postman中测试,看是否通过。
3.1 A系统测试main方法,生成加密后的token
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 获取服务器当前时间
String serversDate = sdf.format(Calendar.getInstance().getTime());
// 获取配置的密钥
String bsystemKey=CommonVar.BSYSTEMKEY;
//此test为AD账号
String bsystemContent = "test"+"&"+serversDate;
try{
// 创建ASE工具对象
SymmetricASEEncoder sae = new SymmetricASEEncoder();
String token=sae.AESEncode(bsystemKey, bsystemContent);
System.out.println(token);
/**
* 3.return
*/
return;
}catch (Exception e){
return;
}
}
这里会生成一个token
//样例
LcGQ6tr8r0xLNz7ZjgUxK8Fx8B1Mxt8nylCeT5Q1GIs=
我们用postman测试,将这个token携带过去
如果postman测试通了证明你的加密解密没有问题,如果失败了,你要检查下,解密是否正确,或者解析工具是否解析成功。
我使用的加密和解密是根据这篇文章java使用AES对称加密和解密
中间也遇到了一些其他小问题,只不过时间长了,我忘记了,先把我想到的记录下来。以上仅供参考。如有疑问,不对的地方,或者是有更好的办法可以解决,请各位亲多多留言,我会虚心请教学习的!!!!
本文地址:https://blog.csdn.net/FannyIf123/article/details/107604776
上一篇: java中通过行为参数化传递代码方案
下一篇: HDU 1400 插头DP,状压DP