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

来源:互联网 发布:淘宝直播怎么添加宝贝 编辑:程序博客网 时间:2024/04/29 06:23


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

  • 【背景】

随着企业中业务不断增多,用户处理不同的业务则需要频繁的切换不同的系统进行操作,而用户则需要记住各个系统的用户名、密码,频繁的登录。如果各个系统间能够进行单点登录,无疑会大大减少用户重复输入密码的困扰。

由于domino系统相对比较封闭,其他系统想相对安全的单点domino系统并非易事。

也许有些人会说通过这样的方法,通过模拟用户登录的方式就可以实现:

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

但是,这样实现显然不太安全,一个需要单独记录用户的明文密码(domino http密码是不可逆算法)。

 

我知道两种实现方式相对安全:DSAPI和模拟LTPAToken。本文介绍一种,通过dominoLTPAToken的生成方式实现单点登录的方法。

 

  • 【实现原理】

输入参数

1.用户名;

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");          // 单点用户名loginName          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("用户名:"+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(/\n/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!=""){// 创建单点cookiedocument.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";}


  • 【实现效果】 

3 0