• 其它系统与domino系统单点登录的实现方式


    

    其它系统与domino系统单点登录的实现方式

    • 【背景】

    随着企业中业务不断增多,用户处理不同的业务则须要频繁的切换不同的系统进行操作。而用户则须要记住各个系统的username、password,频繁的登录。假设各个系统间可以进行单点登录。无疑会大大降低用户反复输入password的困扰。

    因为domino系统相对照较封闭。其它系统想相对安全的单点domino系统并不是易事。

    或许有些人会说通过这个方案。通过模拟用户登录的方式就能够实现:

    Names.nsf?login&username=xxx&password=xxx

    可是。这样实现显然不太安全。一个须要单独记录用户的明文password(domino httppassword是不可逆算法)。

     

    我知道两种实现方式相对安全:DSAPI和模拟LTPAToken

    本文介绍一种,通过dominoLTPAToken的生成方式实现单点登录的方法。

     

    • 【实现原理】

    输入參数

    1. username;

    2. 登录系统时间;

    3. 登录到期时间。

    4. Domino密钥

     

    输出參数

             加密后的LTPAToken加密串

     

    创建cookie

             document.cookie= "LtpaToken="+ token + ";expires=" + exp.toGMTString() +";path=/;domain=.xxx.com";

             token:加密token

             expirescookie到期时间

             domain:单点域名,与dominoSSO配置文档同样,格式:.xxx.com

     

    • 【參考代码】
    • java代码

       

      import java.io.PrintWriter;
      import java.util.Date;
      import java.util.HashMap;
      import java.util.Map;
      import java.util.Properties;
      
      import lotus.domino.*;
      
      public class JavaAgent extends AgentBase {
      
          public void NotesMain() {
          	Session session = null;
          	AgentContext agentContext = null;
          	Document doc = null;
          	PrintWriter pw = null;
          	String token = "";
          	String sReturn = "false";
          	String sJson = "";
            try {
          	  pw = getAgentOutput();
                session = getSession();
                agentContext = session.getAgentContext();
                doc = agentContext.getDocumentContext();
                String sPara = doc.getItemValueString("query_string_decoded");
                // 单点usernameloginName
                String canonicalUser = sPara.substring(sPara.indexOf("sPara=")+6);
      
                // 单点起始时间
                Date tokenCreation = new Date(new Date().getTime() - 60000 * 10);
      		  String timeLimit="720";
      		  // 单点到期时间
      		  Date tokenExpires = new Date(tokenCreation.getTime() + Long.parseLong(timeLimit) * 60000);
      		  // domino SSO 密钥(domino SSO配置文档的LTPA_DominoSecret域值)
      		  String dominoSecret = "9BY2oinn1FmI42i3oNEnL3nNVPQ=";
      		  token = LtpaToken.generate(canonicalUser, tokenCreation, tokenExpires, dominoSecret).getLtpaToken();
      		  //System.out.println("token==ssobak==="+token);
      		  sReturn = "true";          
      		  DominoTokenParser tokenParser = new DominoTokenParser();		   
      		  System.out.println("username:"+tokenParser.parse(token,dominoSecret));
      		  
            } catch(Exception e) {
                e.printStackTrace();
             }finally{
          	   pw.println("Content-type: text/plain;charset=GB2312");
          	   sJson = "{"oResult":""+sReturn+"","token":""+token+""}";
          	   System.out.println("sJson="+sJson);
          	   pw.println(sJson);
          	   
          	   //回收domino对象
          	   fnRecycle(doc);
          	   fnRecycle(agentContext);
          	   fnRecycle(session);
          	   
          	   if(pw!=null){
      				pw.close();
      			}
             }
         }  
          
          public void fnRecycle(Base object){
          	if(object != null){
       		   try {
       			  object.recycle();
      			} catch (NotesException e) {
      				// TODO 自己主动生成 catch 块
      				e.printStackTrace();
      			}
       	   }
          }
      } 
      import java.security.MessageDigest;
      import java.security.NoSuchAlgorithmException;
      import java.util.Calendar;
      import java.util.Date;
      import java.util.Properties;
      
       /** 
           * Lightweight Third Party Authentication. Generates and validates ltpa tokens used in Domino single sign on 
           * environments. Does not work with WebSphere SSO tokens. You need a properties file named LtpaToken.properties which 
           * holds two properties. 
           * 
           * <pre> 
           * ) domino.secret=The base64 encoded secret found in the field LTPA_DominoSecret in the SSO configuration document. 
           * ) cookie.domain=The domain you want generated cookies to be from. e.g. '.domain.com' (Note the leading dot) 
           *</pre> 
           * 
           * @author $Author: rkelly $ 
           * @version $Revision: 1.1 $ 
           * @created $Date: 2003/04/07 18:22:14 $ 
           */ 
      public final class LtpaToken { 
              private byte[] creation; 
              private Date creationDate; 
              private byte[] digest; 
              private byte[] expires; 
              private Date expiresDate; 
              private byte[] hash; 
              private byte[] header; 
              private String ltpaToken; 
              private Properties properties = null; 
              private byte[] rawToken; 
              private byte[] user; 
            
              
            
      
                  /** 
               * Constructor for the LtpaToken object 
               * 
               * @param token 
               *            Description of the Parameter 
               */ 
              public LtpaToken(String token) { 
                  init(); 
                  ltpaToken = token; 
                  rawToken = Base64.decode(token); 
                  user = new byte[(rawToken.length) - 40]; 
                  for (int i = 0; i < 4; i++) { 
                      header[i] = rawToken[i]; 
                  } 
                  for (int i = 4; i < 12; i++) { 
                      creation[i - 4] = rawToken[i]; 
                  } 
                  for (int i = 12; i < 20; i++) { 
                      expires[i - 12] = rawToken[i]; 
                  } 
                  for (int i = 20; i < (rawToken.length - 20); i++) { 
                      user[i - 20] = rawToken[i]; 
                  } 
                  for (int i = (rawToken.length - 20); i < rawToken.length; i++) { 
                      digest[i - (rawToken.length - 20)] = rawToken[i]; 
                  } 
                  creationDate = new Date(Long.parseLong(new String(creation), 16) * 1000); 
                  expiresDate = new Date(Long.parseLong(new String(expires), 16) * 1000); 
              } 
      
              /** 
               * Constructor for the LtpaToken object 
               */ 
              private LtpaToken() { 
                  init(); 
              } 
      
      
      
              /** 
               * Gets the creationDate attribute of the LtpaToken object 
               * 
               * @return The creationDate value 
               */ 
              public Date getCreationDate() { 
                  return creationDate; 
              } 
      
              /** 
               * Gets the expiresDate attribute of the LtpaToken object 
               * 
               * @return The expiresDate value 
               */ 
              public Date getExpiresDate() { 
                  return expiresDate; 
              } 
      
              /** 
               * Gets the user attribute of the LtpaToken object 
               * 
               * @return The user value 
               */ 
              public String getCanonicalUser() { 
                  return new String(user); 
              } 
              
              public String getUser(String prefix, String suffix) {
              	String userName = new String(user);
              	if (prefix !=null && !prefix.equals("")) {
          			userName = userName.substring(userName.indexOf(prefix) + prefix.length());
          		}
          		if (suffix ==null || suffix.equals("")) {
          			suffix = "/";
          		} 
              	return userName.substring(0, userName.indexOf("/"));
              }
              
              public String getUser() { 
                  return new String(user); 
              } 
      
      
              /** 
               * Validates the SHA-1 digest of the token with the Domino secret key. 
               * 
               * @return Returns true if valid. 
               */ 
              public  boolean isValid(LtpaTokenConfig config) { 
                  boolean validDigest = false; 
                  boolean validDateRange = false; 
                  byte[] newDigest; 
                  byte[] bytes = null; 
                  Date now = new Date(); 
      
                  MessageDigest md = getDigest(); 
      
                  bytes = concatenate(bytes, header); 
      
                  bytes = concatenate(bytes, creation); 
      
                  bytes = concatenate(bytes, expires); 
      
                  bytes = concatenate(bytes, user); 
      
                  bytes = concatenate(bytes, Base64.decode(config.getDominoSecret())); 
      
                  newDigest = md.digest(bytes); 
      
                  validDigest = MessageDigest.isEqual(digest, newDigest); 
                  
                  validDateRange = now.after(creationDate) && now.before(expiresDate); 
      
                  return validDigest & validDateRange; 
              } 
      
              /** 
               * String representation of LtpaToken object. 
               * 
               * @return Returns token String suitable for cookie value. 
               */ 
              public String toString() { 
                  return ltpaToken; 
              } 
      
              /** 
               * Creates a new SHA-1 <code>MessageDigest</code> instance. 
               * 
               * @return The instance. 
               */ 
              private MessageDigest getDigest() { 
                  try { 
                      return MessageDigest.getInstance("SHA-1");            
                  } catch (NoSuchAlgorithmException nsae) { 
                      nsae.printStackTrace(); 
                  } 
                  return null; 
              } 
      
              /** 
               * Description of the Method 
               */ 
              private void init() { 
      
                  creation = new byte[8]; 
                  digest = new byte[20]; 
                  expires = new byte[8]; 
                  hash = new byte[20]; 
                  header = new byte[4]; 
      
              } 
      
              /** 
               * Validates the SHA-1 digest of the token with the Domino secret key. 
               * 
               * @param ltpaToken 
               *            Description of the Parameter 
               * @return The valid value 
               */ 
              public static boolean isValid(String ltpaToken,LtpaTokenConfig config) { 
                  LtpaToken ltpa = new LtpaToken(ltpaToken); 
                  return ltpa.isValid(config); 
              } 
      
              /** 
               * Generates a new LtpaToken with given parameters. 
               * 
               * @param canonicalUser 
               *            User name in canonical form. e.g. 'CN=Robert Kelly/OU=MIS/O=EBIMED'. 
               * @param tokenCreation 
               *            Token creation date. 
               * @param tokenExpires 
               *            Token expiration date. 
               * @return The generated token. 
               */ 
              public static LtpaToken generate(String canonicalUser, Date tokenCreation, Date tokenExpires,String  secret) { 
                  LtpaToken ltpa = new LtpaToken(); 
                  System.out.println("Generating token for " + canonicalUser); 
                  Calendar calendar = Calendar.getInstance(); 
                  MessageDigest md = ltpa.getDigest(); 
                  ltpa.header = new byte[] { 0, 1, 2, 3 }; 
                  byte[] token = null; 
                  calendar.setTime(tokenCreation); 
                  ltpa.creation = Long.toHexString(calendar.getTimeInMillis() / 1000).toUpperCase().getBytes(); 
                  calendar.setTime(tokenExpires); 
                  ltpa.expires = Long.toHexString(calendar.getTimeInMillis() / 1000).toUpperCase().getBytes();  
                  //try {
      			//	canonicalUser = new String(canonicalUser.getBytes(), "GB2312");
      			//} catch (UnsupportedEncodingException e) {
      				// TODO 自己主动生成 catch 块
      			//	e.printStackTrace();
      			//}
                  ltpa.user = canonicalUser.getBytes(); 
                  //ltpa.user = canonicalUser.getBytes(Charset.forName("GB18030")); 
      
                  token = concatenate(token, ltpa.header); 
                  token = concatenate(token, ltpa.creation); 
                  token = concatenate(token, ltpa.expires); 
                  token = concatenate(token, ltpa.user); 
                  md.update(token); 
                  ltpa.digest = md.digest(Base64.decode(secret)); 
                  token = concatenate(token, ltpa.digest); 
      
                  return new LtpaToken(new String(Base64.encodeBytes(token,Base64.DONT_BREAK_LINES)));            
              } 
      
              /** 
               * Helper method to concatenate a byte array. 
               * 
               * @param a 
               *            Byte array a. 
               * @param b 
               *            Byte array b. 
               * @return a + b. 
               */ 
              private static byte[] concatenate(byte[] a, byte[] b) { 
                  if (a == null) { 
                      return b; 
                  } else { 
                      byte[] bytes = new byte[a.length + b.length]; 
      
                      System.arraycopy(a, 0, bytes, 0, a.length); 
                      System.arraycopy(b, 0, bytes, a.length, b.length); 
                      return bytes; 
                  } 
              } 
      
              public String getLtpaToken() { 
                  return ltpaToken; 
              } 
      
              public void setLtpaToken(String ltpaToken) { 
                  this.ltpaToken = ltpaToken; 
              } 
          }


    • js代码

       

      function fnSSO(){
      	if(document.getElementById("username").value==""){
      		alert("请输入登录名!");
      		document.getElementById("username").focus();
      		return false;
      	}
      	var objHTTP= new ActiveXObject("Microsoft.XMLHTTP");
      	var sDbPath = document.getElementById("DbFilePath").value;
      	var sPara = document.getElementById("username").value;
      	var vurl = "/"+sDbPath+"/"+"ajaxSSO" + "?

      openagent&sPara=" + sPara; objHTTP.open("GET", vurl, false, "", ""); objHTTP.setRequestHeader("If-Modified-Since","0"); objHTTP.send(false); var getOptions = objHTTP.responseText; getOptions = getOptions.replace(/ /ig,""); var oOptions = eval("(" + getOptions + ")"); var sReturn = ""; if(oOptions && oOptions.oResult=="true"){ var Days = 30; var exp = new Date(); exp.setTime(exp.getTime() + Days*24*60*60*1000); var token = oOptions.token; if(token!=""){ // 创建单点cookie document.cookie = "LtpaToken="+ token + ";expires=" + exp.toGMTString() + ";path=/;domain=.xxx.com"; } sReturn = sPara + ":单点登录成功!" }else{ sReturn = sPara + ":单点失败。" } document.getElementById("ssoinfo").innerHTML = "<font color='red'>" + sReturn + "</font>"; // 页面跳转 location.href = "http://xxx.com/xxx.nsf/xxx?

      openform"; }


    • 【实现效果】 

  • 相关阅读:
    Redis作者谈Redis应用场景(转)
    程序员必读书籍及导读指南(转)
    Python迭代器包itertools(转)
    Flash 0day漏洞(CVE-2018-4878)复现
    第二届“强网杯”全国网络安全挑战赛来袭——线上赛
    网站漏洞——文件判断函数的安全风险(实战篇)
    Android逆向进阶——让你自由自在脱壳的热身运动(dex篇)
    【python入门】之教你编写自动获取金币脚本
    Python大法之从火车余票查询到打造抢Supreme神器
    读DEDECMS找后台目录有感
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/6731703.html
Copyright © 2020-2023  润新知