其它系统与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
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");
// 单点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(/\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!=""){
// 创建单点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";
}
- 【实现效果】
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvR2F2aWQwMTI0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
其它系统与domino系统单点登录的实现方式的更多相关文章
- B/S系统间跨域单点登录设计思路
基于B/S系统间单点登录 此处说的单点登录的概念,即不同系统公用一个登录界面.一处系统通过登录验证,在接入的各系统均为登录状态.一般有两种情景: 1) 一级域名相同 例如:tieba.baidu.c ...
- 系统的讲解 - SSO单点登录
目录 概念 好处 技术实现 小结 扩展 概念 SSO 英文全称 Single Sign On,单点登录. 在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统. 比如:淘宝网(www.t ...
- 单点登录系统(SSO)的开发思路
单点登录并不是一个新鲜的玩意儿,比较官方的解释是企业业务整合的解决方案之一,通俗来讲SSO就是一个通用的用户中心,国内比较流行的UCenter就是一套单点登录解决方案.而近期以CSDN明文存储用户密码 ...
- 单点登录系统CAS筹建及取得更多用户信息的实现
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- 多系统实现单点登录方案:SSO 单点登录
一.什么是单点登录SSO(Single Sign-On) SSO是一种统一认证和授权机制,指访问同一服务器不同应用中的受保护资源的同一用户,只需要登录一次,即通过一个应用中的安全验证后,再访问其他应用 ...
- 单点登录系统实现基于SpringBoot
今天的干货有点湿,里面夹杂着我的泪水.可能也只有代码才能让我暂时的平静.通过本章内容你将学到单点登录系统和传统登录系统的区别,单点登录系统设计思路,Spring4 Java配置方式整合HttpClie ...
- 多平台的网站实现单点登录系统(SSO)的开发思路 让你的会员中心更加统一(参考资料)
单点登录并不是一个新鲜的玩意儿,比较官方的解释是企业业务整合的解决方案之一,通俗来讲SSO就是一个通用的用户中心,国内比较流行的UCenter就是一套单点登录解决方案.而近期以CSDN明文存储用户密码 ...
- 第04项目:淘淘商城(SpringMVC+Spring+Mybatis)【第十天】(单点登录系统实现)
https://pan.baidu.com/s/1bptYGAb#list/path=%2F&parentPath=%2Fsharelink389619878-229862621083040 ...
- SpringCloud微服务实战——搭建企业级开发框架(四十):使用Spring Security OAuth2实现单点登录(SSO)系统
一.单点登录SSO介绍 目前每家企业或者平台都存在不止一套系统,由于历史原因每套系统采购于不同厂商,所以系统间都是相互独立的,都有自己的用户鉴权认证体系,当用户进行登录系统时,不得不记住每套系统的 ...
随机推荐
- Google大脑科学家贾杨清(Caffe缔造者)-微信讲座
Google大脑科学家贾杨清(Caffe缔造者)-微信讲座 机器学习Caffe 贾扬清 caffe 一.讲座正文: 大家好!我是贾扬清178,目前在Google Brain69,今天有幸受雷鸣师兄 ...
- 【Android】5.2 图像按钮和图片格式
分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 1.ImageBtton ImageBtton的用法和Button相似,也有Click事件,用法也和Button一 ...
- 解决NSImage绘制的时候图像模糊
Mac下NSImage绘制模糊的原因之一是draw到了非整数像素上,框架在渲染的时候就会模糊. 针对这一原因写了以下工具: /** * @brief 一劳永逸的解决NSImage绘制的时候绘到浮点值像 ...
- LeetCode: Gray Code 解题报告
Gray CodeThe gray code is a binary numeral system where two successive values differ in only one bit ...
- tomcat Can't create cache file!
) at javax.imageio.ImageIO.write(ImageIO.java:1558) ... 119 more Caused by: java.io.IOException: 系统找 ...
- malloc和free函数详解
一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针 ...
- linux 基本配置tab键和显示行号 和中文输入法
一.仅设置当前用户的Tab键宽度 输入命令:vim ~/.vimrc 然后:set tabstop=4 //我这里将Tab键的宽度设置为4 保存:ctrl+z+z(或:wq!) OK! 二.设置所 ...
- java面试2
1.面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用部分细节.抽 ...
- wampserver 报错 Fatal error:Call to undefined function curl_init()
解决办法如下: 左键wampserver软件,找到PHP,然后找到扩展,点击php_curl开启这个扩展. 然后找到PHP的配置文件php.ini,路径为D:\wamp\bin\php\php5.3. ...
- 【Unity/C#】DateTime时间字符串,月份用英文显示
制作一个钟表,要求效果如下图: 由于每一部分的字体大小不同,我分别使用了不同的Text控件.(不懂dalao们有没有更科学的办法) 把这些Text控件包含在一个Object下,给该Object定义一个 ...