其他系统与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
expires:cookie到期时间
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
- 其他系统与domino系统单点登录的实现方式
- 单点登录系统实现
- 单点登录系统的设计与实现方案
- 单点登录系统的设计与实现方案
- 单点登录系统的设计与实现方案
- 单点登录系统的设计与实现方案
- 单点登录系统的设计与实现方案
- 跨域单点登录系统的设计与实现
- CAS实现的单点登录系统
- Java Web 系统单点登录的实现
- Java Web 系统单点登录的实现
- CAS实现的单点登录系统
- CAS实现的单点登录系统
- 单点登录系统简单实现
- 【SSO】单点登录系统实现
- redis实现单点登录系统
- BOE系统与BW系统间的单点登录
- Java 利用http协议与Domino实现sso单点登录
- java 分别利用synchronized和jdk1.5新特性实现多消费者-多生产者线程的等待唤醒机制
- CentOS5.x内核优化详细解析 (sysctl.conf)
- EBS根据表单、功能反查其职责、菜单路径
- 关于Integral channel features以及softcascade
- jqueryEasyUI:tabs扩展:给tabs组件绑定双击事件
- 其他系统与domino系统单点登录的实现方式
- jsp页面iframe高度自适应js
- win 开机 Microsoft corparation 滚动条
- 大学,梦想的起点
- Android调用原声分享相关的知识以及保存图片读取图片
- Introduction to tf
- 开发者应该了解的API技术清单!
- “iOS 推送通知”详解:从创建到设置到运行
- cocos2d-x 3.2开发 别点白块儿