в процессе перевода приложения на xPages возникает законный вопрос - как оставить временно живущим "классический" код?
схема следующая (на примере агента): Агент->обертка вызова по http->профит
пример агента
обертка
увидим знакомы (по моим постам) вызовы классов TrustAllCertificates.install(); LtpaToken ltpaToken...
класс токена расширил получением домена из дока сайта
можно былобы и из LS2J, если бы не необходимость Session или придется мудрить с промежуточным xPage и шифрованием как уже описывал в Унификации
агент, скорее-всего, нужно будет запускать с правами подписывающего или того кто имеет доступ к Ltpa...
Чтобы код хэпаги исполнялся от имени к-л пользователя - можно предусмотреть вызов агента с контекстным документом (где и брать юзера) и передавать доп. параметр в обертку
схема следующая (на примере агента): Агент->обертка вызова по http->профит
пример агента
Java:
import lotus.domino.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session ses = getSession();
AgentContext agentContext = ses.getAgentContext();
// (Your code goes here)
com.setralubs.XAgent.run(ses, agentContext, "test", "");//".castrolcis.com");
} catch(Exception e) {
e.printStackTrace();
}
}
}
Java:
import lotus.domino.Session;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import lotus.domino.AgentContext;
import lotus.domino.Database;
import lotus.domino.Name;
public class XAgent {
public static void run(Session ses, AgentContext agentContext, String xpageName, String domain) {
String url = null;
try {
TrustAllCertificates.install();
LtpaToken ltpaToken=new LtpaToken();
ltpaToken.initByConfiguration(ses);
String token=ltpaToken.generateLtpaToken(ses.getEffectiveUserName());
Database db=agentContext.getCurrentDatabase();
String dbPath = agentContext.getCurrentDatabase().getFilePath();
String server=db.getServer();
//dbPath=db.getHttpURL();
//System.out.println("path->"+dbPath);
if (domain.isEmpty())domain=ltpaToken.getDomain();
Name name=ses.createName(server);
server=name.getCommon();
url = "https://"+server+domain+"/" + dbPath + "/" + xpageName + ".xsp";
System.out.println("Starting " + xpageName + " in database " + dbPath);
System.out.println("URL->"+url);
String cookies="LtpaToken=" + token;// + "; domain=" + domain.substring(1) + "; path=/";
System.out.println("Cookies->"+cookies);
URL xPageURL = new URL(url);
HttpURLConnection conn = (HttpURLConnection) xPageURL.openConnection();
conn.setRequestProperty("Cookie", cookies);
//conn.connect();
switch (conn.getResponseCode()) {
case HttpURLConnection.HTTP_OK:
// read from the urlconnection via the bufferedreader
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println("Response: " + line);
}
bufferedReader.close();
break;
case HttpURLConnection.HTTP_INTERNAL_ERROR:
System.out.println("Interal server error while running");
break;
default:
System.out.println("An error occurred: " + conn.getResponseCode());
System.out.println("Error message: " + conn.getResponseMessage());
break;
}
conn.disconnect();
System.out.println("Finished " + xpageName + " in database " + dbPath);
} catch (Exception e) {
System.out.println("URL->"+url);
e.printStackTrace();
}
}
}
класс токена расширил получением домена из дока сайта
Java:
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
//import java.util.Calendar;
//import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.bind.DatatypeConverter;
import lotus.domino.Database;
import lotus.domino.Document;
import lotus.domino.NotesException;
import lotus.domino.Session;
import lotus.domino.View;
/*
* @author Serdar Basegmez, Developi (http://lotusnotus.com/en)
*/
public class LtpaToken{
public static final String NAMESDB="names.nsf";
public static final String SSOVIEW="($WebSSOConfigs)";
public static final String SSO_DOMINO_SECRETFIELD="LTPA_DominoSecret";
public static final String SSO_DOMINO_DURATIONFIELD="LTPA_TokenExpiration";
public static final String SSO_DOMINO_DOMAIN="LTPA_TokenDomain";
private String WebSSOSite="CRUINTERNET:CISsite";
private boolean ready=false;
private int duration=300;
private String ltpaSecret="";
private String classID;
private String domain="";
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public LtpaToken(){
classID="::"+this.getClass().getName()+"::";
System.out.println("constructor:" + this.getClass().getName());
}
public LtpaToken(String ltpaSecret) {
this();
setLtpaSecret(ltpaSecret);
}
public LtpaToken(String ltpaSecret, int duration) {
this();
setLtpaSecret(ltpaSecret);
setDuration(duration);
}
public void initByConfiguration(Session session) throws Exception{
initByConfiguration(session, WebSSOSite);
}
public void initByConfiguration(Session session, String configName) throws Exception {
Database dbNames=null;
View ssoView=null;
Document ssoDoc=null;
String memberID=classID+"initByConfiguration::";
String status="try...";
try {
if (session==null)throw new Exception("session is null");
Database db=session.getCurrentDatabase();
if (db==null)throw new Exception("current db is null");
String currentServer=db.getServer();//session.getServerName();
db.recycle();
status="get server name";
status="get NAB from:"+currentServer;
dbNames=session.getDatabase(currentServer, NAMESDB, false);
status="get view"+SSOVIEW;
ssoView=dbNames.getView(SSOVIEW);
status=currentServer+"->get config doc:"+configName;
ssoDoc=ssoView.getDocumentByKey(configName, true);
if(ssoDoc==null) {
status="Unable to find SSO configuration with the given configName.";
throw new IllegalArgumentException(status);
}
setLtpaSecret(ssoDoc.getItemValueString(SSO_DOMINO_SECRETFIELD));
setDuration(ssoDoc.getItemValueInteger(SSO_DOMINO_DURATIONFIELD));
setDomain(ssoDoc.getItemValueString(SSO_DOMINO_DOMAIN));
status="success";
} catch (NotesException ex) {
status = "Notes exception:"+ex.text;
throw new Exception("Notes Error: "+ex);
} finally {
try {
if(dbNames!=null) dbNames.recycle();
if(ssoView!=null) ssoView.recycle();
if(ssoDoc!=null) ssoDoc.recycle();
System.out.println(memberID+status);
} catch(NotesException exc) {
System.out.println(memberID+"finally catch:"+status);
//ignore
}
}
}
public String generateLtpaToken(String userName) {
String memberID=classID+"generateLtpaToken";
if(!isReady()) {
throw new IllegalStateException("LtpaGenerator is not ready.");
}
MessageDigest sha1 = null;
//Calendar ci=Calendar.getInstance();
GregorianCalendar creationDate=new GregorianCalendar();
GregorianCalendar expiringDate=new GregorianCalendar();
byte[] userNameArray=userName.getBytes();
expiringDate.add(GregorianCalendar.MINUTE, duration);
System.out.println(memberID+"Ltpa creation:"+creationDate.getTime().toString());
System.out.println(memberID+"Ltpa expiring:"+expiringDate.getTime().toString());
try {
sha1 = MessageDigest.getInstance( "SHA-1" );
} catch (NoSuchAlgorithmException e) {
e.printStackTrace(System.err);
}
byte[] secretDecoded=DatatypeConverter.parseBase64Binary(ltpaSecret);
// Look at important notes above...
try {
if(Charset.isSupported("LMBCS")) {
userNameArray=userName.getBytes("LMBCS");
}
} catch (UnsupportedEncodingException e) {
// Not supposed to fall here.
}
byte[] tokenBase=concatBytes(("\000\001\002\003"+getHexRep(creationDate)+getHexRep(expiringDate)).getBytes(), userNameArray);
byte[] digest=sha1.digest(concatBytes(tokenBase, secretDecoded));
return DatatypeConverter.printBase64Binary(concatBytes(tokenBase, digest));
}
public static byte[] concatBytes(byte[] arr1, byte[] arr2) {
byte[] result=Arrays.copyOf(arr1, arr1.length+arr2.length);
System.arraycopy(arr2, 0, result, arr1.length, arr2.length);
return result;
}
public static String getHexRep(GregorianCalendar date) {
int timeVal=(int)(date.getTimeInMillis()/1000);
String hex=Integer.toHexString(timeVal).toUpperCase();
if(hex.length()>=8) {
return hex;
} else {
return String.format("%0"+(8-hex.length())+"d", new Integer[]{new Integer(0)})+hex;
}
}
public void setDuration(int duration) {
this.duration = duration;
}
public void setLtpaSecret(String ltpaSecret) {
this.ltpaSecret = ltpaSecret;
this.ready=true;
}
public boolean isReady() {
return ready;
}
public String test(String param){
return "test:" + param;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
агент, скорее-всего, нужно будет запускать с правами подписывающего или того кто имеет доступ к Ltpa...
Чтобы код хэпаги исполнялся от имени к-л пользователя - можно предусмотреть вызов агента с контекстным документом (где и брать юзера) и передавать доп. параметр в обертку
Последнее редактирование: