关于单点登录第一天接触之我见
前几天老大要搭好了项目框架,然后没要我继续跟进,而是做单点登录。我操,跨系统。有点紧张,礼拜天看了看单点登录。
理论梳理:
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
当用户第一次访问应用系统的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--ticket;用户再访问别的应用的时候,就会将这个ticket带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行校验,检查ticket的合法性。如果通过校验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。
目前相对来讲,实在原来项目的基础上加了一个加密层,就是把当前用户名以一种加密的方式传输给另一个系统,另一个系统接收到加密串对他进行解析,
解析后如果匹配正确,直接登录(因为当时非常纠结为什么加密传输过程中不把密码一起加密传输过去,让对方解密后取匹配?而是只给了用户名,我尝试过传输非用户的假名字,
会报错:解析失败),如果用户名匹配失败则无法登陆。
在这里主要将机密过程做一展示:
package com.zx.ps.aes; import java.net.URLEncoder; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Base64; /** * @author : ckx * @date : 2016-12-5 下午9:32:52 */ public class AESUtil { // 加密 public static String Encrypt(String sSrc, String sKey) throws Exception { if (sKey == null) { System.out.print("Key为空null"); return null; } // 判断Key是否为16位 if (sKey.length() != 16) { System.out.print("Key长度不是16位"); return null; } byte[] raw = sKey.getBytes("utf-8"); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式" cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); return new Base64().encodeToString(encrypted);//此处使用BASE64做转码功能,同时能起到2次加密的作用。 } // 解密 public static String Decrypt(String sSrc, String sKey) throws Exception { try { // 判断Key是否正确 if (sKey == null) { System.out.print("Key为空null"); return null; } // 判断Key是否为16位 if (sKey.length() != 16) { System.out.print("Key长度不是16位"); return null; } byte[] raw = sKey.getBytes("utf-8"); SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, skeySpec); byte[] encrypted1 = new Base64().decode(sSrc);//先用base64解密 try { byte[] original = cipher.doFinal(encrypted1); String originalString = new String(original,"utf-8"); return originalString; } catch (Exception e) { System.out.println(e.toString()); return null; } } catch (Exception ex) { System.out.println(ex.toString()); return null; } } public static void main(String[] args) throws Exception { /* * 此处使用AES-128-ECB加密模式,key需要为16位。 */ // String cKey = "abcdefg123456789"; // 需要加密的字串 // String cSrc = "www.FDSA.soEEEEE"; String cKey = "1234567891234567"; String cSrc = "20161201121212szzx"; String url=URLEncoder.encode("DTB90z5MWjtt7ojCU+zvJbqnuke2KPAmffGPW2q8kFA=","UTF-8"); System.out.println(url); System.out.println(cSrc); // 加密 String enString = AESUtil.Encrypt(cSrc, cKey); System.out.println("加密后的字串是:" + enString); // 解密 String DeString = AESUtil.Decrypt(enString, cKey); System.out.println("解密后的字串是:" + DeString);
enString=URLEncoder.encode(enString);
System.out.println("URL加密:"+enString);
}
}
在页面中本系统对另一系统的跳转超链接:
对用户进行加密,并把加密串放入超链接中:
String cKey = "1234567891234567"; String cSrc = "20161205193612zhongjunhua"; String ticket=AESUtil.Encrypt(cSrc, cKey);//调用加密方法对用户加密 System.err.println("###########"+ticket);
ticket=URLEncoder.encode(ticket);
System.err.println("ticket1"+ticket);
dmp.put("zxssoticket", ticket);
如此便可以实现简单的单点登录。