当前位置: 移动技术网 > IT编程>开发语言>.net > 根据AD账号直接单点登录到第三方系统

根据AD账号直接单点登录到第三方系统

2020年07月29日  | 移动技术网IT编程  | 我要评论
上周在做一个单点登录的任务,今天有时间就整理一下,当时遇到的问题很多,我会慢慢的回忆记录下来。首先这个单点登录我们要构思一下:之前的版本是,跳转的链接url是个固定值,它保存到了数据库,我们点击后输入账号密码登录,它是直接从数据库中获取。而现在我们想要实现的功能是,在A系统通过AD账号登录,直接在A系统内点击B系统图标或文字直接跳转到B系统,无需通过账号密码的其他操作直接进入。同时我们也要保障我们传过去的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

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网