平台第三方应用集成单点登录解决方案

                                                                   平台第三方应用集成单点登录解决方案

 

  1. 使用场景

基于统一用户平台实现多应用集成单点登录,统一入口登录后用户实现共享,实现多系统认证登录,权限由各业务系统内部实现。

  1. 实现原理

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。一个JWT实际上就是一个字符串,它由三部分组成,头部(header)、载荷(playload)与签名(signature)。

1)目标应用获取到token后需要对其进行解密,得到JWT头、有效负荷,按照约定算法进行编码加密形成验签,再同签名进行对比以判断数据的完整性和一致性。

2)验证通过后解码有效载荷内容,获取有效期属性判断该token是否超期失效。

3)验证token在有效期内,获取到统一用户的登录ID,并进行自己系统内的用户验证和权限判断实现登录或者跳转到业务界面。

  1. 单点登录使用方式

单点登录的目标应用访问地址:

http://www.xxx.gov.cn/xxx/single.do?token= ZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKTlJEVklaWGdpZlE9PS5leUpsZUhBaU9pSXlNREl3TFRBeExURTJJREV6T2pNNE9qTTFJaXdpZFhObGNtbGtJam9pYkc5bmFXNXVZVzFsSWl3aWRYTmxjbTVoYldVaU9pTHBxNWptaUpEcGxJc2lmUT09Ljc0QkIyNkFGQjVBNjZBNzI2NENERUM4MDVFMDA5RDUy

JAVA

方法一:需要导入commons-lang-2.5.0.jar  jackson-all-1.9.11.jar  sso-decoder-1.0.0.jar

如果应用中已经存在对应jar包或者更高版本则可以不用导入。

代码示例:

import com.boshan.sso.validation.TokenDecoder;

TokenDecoder tokenDecoder = new TokenDecoder();

String result = tokenDecoder.checkUserToken(token);

result参数说明

{“issuccess”:”true”, ”userid”:”admin”, “message”:””}

参数名称

参数值

说明

issuccess

true/false

验证通过则为true

userid

用户登录ID

验证失败值为空

message

单点登录验证消息

验证通过值为空

 

方法二:对token进行Base64解码,解码后的字符串由三部分组成.

如:头部header.载荷playload.签名signature

eyJ0eXAiOiJKV1QiLCJhbGciOiJNRDVIZXgifQ==.eyJleHAiOiIyMDIwLTAxLTE2IDEzOjM4OjM1IiwidXNlcmlkIjoibG9naW5uYW1lIiwidXNlcm5hbWUiOiLpq5jmiJDplIsifQ==.74BB26AFB5A66A7264CDEC805E009D52

对头部header进行Base64解码后获得字符串 {“typ”:”jwt”, ” alg”:” MD5Hex” } 得到算法MD5Hex。

联系方案提供方获取截长数值SPLIT秘钥SECRETKEY ①。

根据SPLIT大小对头部header截取字符串前几位作为一个字符串值②。

根据SPLIT大小对载荷playload截取字符串后几位作为一个字符串值③。

将①,②,③ 按照对应算法进行加密,将加密后的字符串与签名signature进行比对以便验证数据的完整性和一致性。

一致性验证通过后,对载荷playload字符串再进行Base64解码获取一个json字符串。

如:{“username”:”张三”, ”userid”:”admin”, “exp”:”2020-01-16 16:22:39”}

请根据exp字段与系统当前时间进行验证该token是否已经失效。

有效性验证通过后,可以直接获取userid字段值,然后在自己系统内验证用户有效性以及权限进行系统登录或者界面跳转。

public String getSign(String header, String paload){

         String prifix = header.substring(0, Constants.SPLIT);

         String suffix = paload.substring(paload.length() - Constants.SPLIT, paload.length());

         String sign = "";

         try {

                  String[] str = {prifix, Constants.SECRETKEY, suffix};

                  List<Byte> list = new ArrayList<Byte>();

                  for (String string : str) {

                           for(byte b : string.getBytes("UTF-8")) {

                                   list.add(b);

                          }

                  }

                  Collections.sort(list);

                  sign = StringUtils.join(list.toArray(), ",");

                  sign = MD5Hex (sign, 32);

         } catch (Exception e) {

                  System.out.println(e.getMessage());

         }

         return sign;

}

private static String MD5Hex (String contentText,int length) {

         try {   

                  MessageDigest messageDigest = MessageDigest.getInstance("MD5");

                  messageDigest.update(contentText.getBytes());

                  byte bytes[] = messageDigest.digest();

                  int index;

                  StringBuffer data = new StringBuffer("");

                  for (int offset = 0; offset < bytes.length; offset++) {

                          index = bytes[offset];

                          if (index < 0) {

                                   index += 256;

                          }

                          if (index < 16) {

                                   data.append("0");

                          }

                          data.append(Integer.toHexString(index));

        }   

                  if (length == 32) {//32位加密

                          return data.toString().toUpperCase();

                  }else if (length == 16) {// 16位的加密

                          return data.toString().substring(8, 24).toUpperCase();

                  }else {

                          return null;

                  }

         } catch (Exception e) {

                  e.printStackTrace();

                  return null;

         }

}

C#、PHP等其他编程语言请参看以上方法二的实现原理进行处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值