चूंकि हमारे पास डोमिनोज 9.0.1 पर सफलतापूर्वक कार्यान्वित एसएलओ प्राप्त करने के लिए कई कदम उठाने के लिए, मैंने कोड लिखने का फैसला किया जो हमारे डोमिनोज सर्वर के साथ चलाने के लिए किसी भी (भविष्य) आईडीपी कॉन्फ़िगरेशन का उपयोग करने की अनुमति देगा। मैं निम्नलिखित रणनीति को लागू किया:
- उपयोग जानकारी के जितना संभव हो सके
- एक इनकमिंग SAML लॉगआउट अनुरोध से उपलब्ध IdP SLO प्रतिक्रिया के बारे में जानकारी प्राप्त करने के लिए इसी होने की idpcat.nsf में IdP विन्यास को पहचानें आईडीपी सेवा प्रदाता (SAML सर्वर)
- SAML कॉन्फ़िगरेशन में परिवर्तन होने पर नई आवश्यकताओं को गतिशील अनुकूलन की अनुमति देने के लिए idpcat.nsf में संबंधित आईडीपी कॉन्फ़िगरेशन में SAML लॉगआउट प्रतिक्रिया को परिभाषित करें।
नतीजतन, कोड में एक पैरामीटर मानचित्र भेजे SAML लॉगआउट अनुरोध के सभी क्षेत्रों को पढ़ता है और डीकोड और क्वेरी स्ट्रिंग में पैरामीटर मानचित्र अनुरोध की एक्सएमएल पैरामीटर्स को निकालने के लिए अनावश्यक रूप से बढ़ा। चूंकि डोमिनोज सर्वर पर विभिन्न वेबसाइटों को एसएसओ कनेक्शन की अनुमति देने के लिए अलग-अलग आईडीपी सेवा प्रदाताओं के लिए कॉन्फ़िगर किया जा सकता है, इसलिए मैं संबंधित "होस्ट नाम" के साथ आईडीपी कॉन्फ़िगरेशन की पहचान करता हूं और उसी पैरामीटर मानचित्र में अपने सभी फ़ील्ड को पढ़ता हूं। एक लागू एक्सएमएल प्रतिक्रिया को परिभाषित करने के लिए मैंने सभी आवश्यक परिभाषाओं को आईडीपी कॉन्फ़िगरेशन की टिप्पणी में लिखने का निर्णय लिया, जो अलग-अलग आईडीपी प्रदाताओं के लिए एक ही कोड का उपयोग करने के लिए एकल आईडीपी कॉन्फ़िगरेशन को अनुकूलित करने की अनुमति देता है भले ही विभिन्न SAML संस्करणों का उपयोग करें। Idpcat.nsf में आईडीपी कॉन्फ़िगरेशन के टिप्पणी क्षेत्र में परिभाषाएं इस तरह दिखती हैं:
एसएलओ प्रतिक्रिया:/idp/एसएलओ।SAML2;
SLO प्रतिक्रिया एक्सएमएल: "<" कलश: LogoutResponse आईडी = "@ UUID" संस्करण = "# संस्करण" IssueInstant = "@ ACTUAL_TIME" गंतव्य = "SLO_Response" InResponseTo = "# आईडी" xmlns: कलश = "# xmlns : कलश ">" "<" urn1: जारीकर्ता xmlns: urn1 = "XML_Parameter1" ">" HTTP_HSP_LISTENERURI "<"/urn1: जारीकर्ता ">" "<" कलश: स्थिति ">" "<" कलश: StatusCode मूल्य = "XML_Parameter2"/">" "<"/कलश: स्थिति ">" "<"/कलश: LogoutResponse ">";
एक्सएमएल मान: #xmlns: कलश = प्रोटोकॉल -> अभिकथन & #xmlns: urn = प्रोटोकॉल -> स्थिति: सफलता;
प्रतिक्रिया पैरामीटर: रिलेस्टेट & सिगएल्ग और हस्ताक्षर;
हस्ताक्षर प्रकार: SHA256withRSA;
कीस्टोर प्रकार: पीकेसीएस 12;
कीस्टोर फ़ाइल: डी: \ saml_cert.pfx;
कीस्टोर पासवर्ड: **********;
प्रमाणपत्र: {} xxxxxxxxxx
इस परिभाषा में कुंजी के साथ मूल्यों से अलग होती है ":" और मूल्यों के अंत के साथ निर्दिष्ट किया जाता है "," (नई लाइन नहीं) यह एसएसओ कनेक्शन के लिए उपयोग किए गए संबंधित आईडीपी कॉन्फ़िगरेशन में आईडीपी सेवा प्रदाता से आवश्यक एसएएमएल प्रतिक्रिया का पूर्ण पैरामीटरकरण सेट करने की अनुमति देता है।
• SLO प्रतिक्रिया:: यह रिश्तेदार का पता है, जहां SLO रिस्पांस संबंधित IdP सर्वर पर करने के लिए भेजा जाना है इस प्रकार है परिभाषाएँ निर्दिष्ट हैं।
• एसएलओ प्रतिक्रिया एक्सएमएल: यह एक्सएमएल प्रारूप में संरचित एसएलओ प्रतिक्रिया को परिभाषित करने वाली टेक्स्ट स्ट्रिंग है ("<" और ">" बिना ") का उपयोग करें। पैरामीटर मानचित्र में पाए गए पैरामीटर की पहचान करने वाले स्ट्रिंग्स को उनके संबंधित मान में बदल दिया जाता है। सुनिश्चित करें कि समान पैरामीटर सही ढंग से पहचान कुकी पैरामीटर। इसके अतिरिक्त 2 सूत्रों प्रदान की जाती हैं एक अग्रणी "$" और अनुरोध क्वेरी एक अग्रणी "#" के एक्सएमएल मानकों है, जहां "@UUID" के साथ एक यादृच्छिक UUID की गणना करेगा कर रहे हैं बनाने के लिए XML प्रतिक्रिया के आईडी पैरामीटर के लिए सही प्रारूप और "@ACTUAL_TIME" XML प्रतिक्रिया के IssueInstant पैरामीटर के लिए तत्काल प्रारूप में सही टाइम स्टाम्प की गणना करेगा।
• XML मान: यह टेक्स्ट स्ट्रिंग अतिरिक्त पैरामीटर की पहचान करती है, जहां मूल रूप से एक ज्ञात पैरामीटर का उपयोग किया जाता है, लेकिन आवश्यक पाठ से मेल खाने के लिए पैरामीटर मान का एक हिस्सा आदान-प्रदान की आवश्यकता होती है। मापदंडों स्ट्रिंग "XML_Paramater" स्ट्रिंग SLO प्रतिक्रिया एक्सएमएल टेक्स्ट में "&" के साथ प्रत्येक मूल्य को अलग करने में स्थिति के बाद से पहचाने जाते हैं। एक्सएमएल वैल्यूज के लिए पाठ पैरामीटर पहचान के बाद "=" और टेक्स्ट को प्रतिस्थापित करने के बाद "->" और नया टेक्स्ट द्वारा संरचित किया जाता है।
• प्रतिक्रिया पैरामीटर: प्रतिक्रिया पैरामीटर "&" से अलग किए गए हैं और परिभाषित किए गए एसएलओ प्रतिक्रिया में जोड़े जाएंगे। एक हस्ताक्षर मानकों की आवश्यकता है तो SigAlg और हस्ताक्षर इस स्ट्रिंग में की जरूरत है और अंत में रखा जाना चाहिए।
• हस्ताक्षर प्रकार: तो हस्ताक्षर की आवश्यकता है एल्गोरिथ्म के प्रकार के हस्ताक्षर गणना के लिए इस्तेमाल यहाँ निर्दिष्ट किया जाता है।
• कीस्टोर प्रकार: यह प्रमाणपत्र के लिए उपयोग की जाने वाली कीस्टोर का प्रकार है।
• कीस्टोर फ़ाइल: यह वह फ़ाइल है जहां लोटस नोट्स सर्वर पर ड्राइव और पथ सहित कीस्टोर सहेजा गया है। हमने टेस्ट सर्वर पर डी: \ saml_cert.pfx का उपयोग किया।
• कीस्टोर पासवर्ड: यह कुंजीस्टोर फ़ाइल और उसमें संग्रहीत प्रमाणपत्र खोलने के लिए आवश्यक पासवर्ड है।
• प्रमाणपत्र: यह कुंजीस्टोर फ़ाइल में प्रमाणपत्र की पहचान प्रमाणपत्र का उपनाम है। यदि किसी स्थान पर कई प्रमाणपत्रों को गठबंधन करने के लिए किसी नई कुंजीस्टोर फ़ाइल में प्रमाणपत्र संग्रहीत किया जाता है, तो उपनाम हमेशा एक नए मान में बदल जाता है, जिसे यहां अनुकूलित किया जाना है।
कोड लागू किया गया कोड domcfg.nsf में "लॉगआउट" नाम के साथ एक जावा एजेंट है, लेकिन इसे मूल रूप से एसएसओ उपयोगकर्ताओं के लिए उपलब्ध किसी भी डेटाबेस में कार्यान्वित किया जा सकता है और यह आईडी के संरक्षण की अनुमति देने के लिए सर्वर के रूप में चलाता है उच्चतम सुरक्षा के साथ idpcat.nsf में विन्यास। आईडीपी सेवा प्रदाता पर आपको एसएमएल अनुरोध के बाद क्रमशः संबंधित वेबसाइट "https://WEBSITE/domcfg.nsf/Logout?Open&" के रूप में डोमिनोज सर्वर के लिए एसएलओ अनुरोध को कॉन्फ़िगर करना होगा। यदि आईडीपी सेवा प्रदाता द्वारा हस्ताक्षर का अनुरोध किया जाता है, तो आपको हस्ताक्षर करने के लिए आवश्यक निजीकी सहित सर्टिफिकेट के साथ एक कीस्टोर फ़ाइल को स्टोर करना होगा। कीस्टोर फ़ाइल को एमएमसी स्नैप-इन फ़ंक्शन का उपयोग करके प्रबंधित किया जा सकता है (https://msdn.microsoft.com/en-us/library/ms788967(v=vs.110).aspx देखें)। निर्यात फ़ंक्शन द्वारा एक फ़ाइल में कई प्रमाणपत्रों को गठबंधन करना संभव है, लेकिन आपको यह सुनिश्चित करना होगा कि आप निर्यात विज़ार्ड में संबंधित सेटिंग द्वारा फ़ाइल में निजी कुंजी निर्यात करें।
import lotus.domino.*;
import java.io.*;
import java.util.*;
import java.text.*;
import com.ibm.xml.crypto.util.Base64;
import java.util.zip.*;
import java.net.URLEncoder;
import java.security.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session ASession = getSession();
AgentContext AContext = ASession.getAgentContext();
DateTime date = ASession.createDateTime("Today 06:00");
int timezone = date.getTimeZone();
Database DB = AContext.getCurrentDatabase();
String DBName = DB.getFileName();
DBName = DBName.replace("\\", "/").replace(" ", "+");
//Load PrintWriter to printout values for checking (only to debug)
//PrintWriter pwdebug = getAgentOutput();
//pwdebug.flush();
//Load Data from Logout Request
Document Doc = AContext.getDocumentContext();
Vector<?> items = Doc.getItems();
Map<String, String> Params = new LinkedHashMap<String, String>();
for (int j=0; j<items.size(); j++) {
Item item = (Item)items.elementAt(j);
if (!item.getValueString().isEmpty()) Params.put(item.getName(), item.getValueString());
}
String ServerName = Params.get("HTTP_HSP_HTTPS_HOST");
int pos = ServerName.indexOf(":");
ServerName = pos > 0 ? ServerName.substring(0, ServerName.indexOf(":")) : ServerName;
Params.put("ServerName", ServerName);
Doc.recycle();
DB.recycle();
//Load Cookie Variables
Params = map(Params, Params.get("HTTP_COOKIE"), "$", "; ", "=", false, false);
//Load Query Variables
Params = map(Params, Params.get("QUERY_STRING_DECODED"), "", "&", "=", false, false);
//Decode and Infalte SAML Request
String RequestUnziped = decode_inflate(Params.get("SAMLRequest"), true);
//pwdebug.println("Request unziped: " + RequestUnziped);
//System.out.println("Request unziped: " + RequestUnziped);
String RequestXMLParams = RequestUnziped.substring(19, RequestUnziped.indexOf("\">"));
//Load XML Parameters from Request
Params = map(Params, RequestXMLParams, "#", "\" ", "=\"", false, false);
//for (Map.Entry<String, String> entry : Params.entrySet()) pwdebug.println(entry.getKey() + " value: " + entry.getValue());
//for (Map.Entry<String, String> entry : Params.entrySet()) System.out.println(entry.getKey() + " value: " + entry.getValue());
String Issuer = RequestUnziped.substring(RequestUnziped.indexOf(":Issuer"), RequestUnziped.indexOf("Issuer>"));
Issuer = Issuer.substring(Issuer.indexOf(">") + 1, Issuer.indexOf("<"));
Params.put("SLO_Issuer", Issuer);
//Load Parameters for the Response
DbDirectory Dir = ASession.getDbDirectory(null);
Database idpcat = Dir.openDatabase("idpcat.nsf");
View idpView = idpcat.getView("($IdPConfigs)");
Document idpDoc = idpView.getDocumentByKey(ServerName, false);
items = idpDoc.getItems();
for (int j=0; j<items.size(); j++) {
Item item = (Item)items.elementAt(j);
if (!item.getValueString().isEmpty()) Params.put(item.getName(), item.getValueString());
}
Params = map(Params, idpDoc.getItemValueString("Comments"), "", ";", ": ", false, false);
Params.put("SLO_Response", Issuer + Params.get("SLO Response"));
Params.put("@UUID", "_" + UUID.randomUUID().toString());
Params.put("@ACTUAL_TIME", actualTime(Params.get("#IssueInstant"), Params.get("#NotOnOrAfter"), timezone));
//for (Map.Entry<String, String> entry : Params.entrySet()) pwdebug.println(entry.getKey() + " value: " + entry.getValue());
//for (Map.Entry<String, String> entry : Params.entrySet()) System.out.println(entry.getKey() + " value: " + entry.getValue());
idpDoc.recycle();
idpView.recycle();
idpcat.recycle();
Dir.recycle();
//Setup XML Response as defined
String ResponseString = Params.get("SLO Response XML");
for (Iterator<String> itRq = Params.keySet().iterator(); itRq.hasNext();) {
String Key = (String) itRq.next();
ResponseString = ResponseString.replace(Key, Params.get(Key));
}
//pwdebug.println("Response String replaced: " + ResponseString);
//System.out.println("Response String replaced: " + ResponseString);
//Load Values to be exchanged in the defined Response
Map<String, String> RsXMLValues = map(new LinkedHashMap<String, String>(), Params.get("XML Values"), "", "&", "=", true, false);
//for (Map.Entry<String, String> entry : RsXMLValues.entrySet()) pwdebug.println(entry.getKey() + " value: " + entry.getValue());
//for (Map.Entry<String, String> entry : RsXMLValues.entrySet()) System.out.println(entry.getKey() + " value: " + entry.getValue());
//Exchange defined Strings with Values from the Request
int itc = 0;
for (Iterator<String> itRXV = RsXMLValues.keySet().iterator(); itRXV.hasNext();) {
itc = itc + 1;
String Key = (String) itRXV.next();
int lock = Key.indexOf(" -> ");
String KeyRq = lock > 0 ? Key.substring(0, lock) : Key;
int lockRq = KeyRq.indexOf(" ");
KeyRq = lockRq > 0 ? KeyRq.substring(0, lockRq) : KeyRq;
String Parameter = Params.get(KeyRq);
String Value = RsXMLValues.get(Key);
if (!Value.isEmpty()) {
int locv = Value.indexOf(" -> ");
String ValueS = locv > 0 ? Value.substring(0, locv) : Value;
String ValueR = locv > 0 && Value.length() > locv + 4 ? Value.substring(locv + 4) : ValueS;
Parameter = Parameter.replace(ValueS, ValueR);
}
ResponseString = ResponseString.replace(("XML_Parameter" + itc), Parameter);
}
//pwdebug.println("Final XML Response String: " + ResponseString);
//System.out.println("Final XML Response String: " + ResponseString);
//Deflate and Encode the XML Response
String ResponseZiped = deflate_encode(ResponseString, Deflater.DEFAULT_COMPRESSION, true);
//pwdebug.println("Response Ziped: " + ResponseZiped);
//System.out.println("Response Ziped: " + ResponseZiped);
//Setup Response URLQuery as defined
String ResponseEncoded = "SAMLResponse=" + URLEncoder.encode(ResponseZiped, "UTF-8");
//pwdebug.println("Response to Sign: " + ResponseEncoded);
//System.out.println("Response to Sign: " + ResponseEncoded);
//Load Parameters to be added to the Response
Map<String, String> ResponseParams = map(new LinkedHashMap<String, String>(), Params.get("Response Parameters"), "", "&", "=", false, true);
//for (Map.Entry<String, String> entry : ResponseParams.entrySet()) pwdebug.println(entry.getKey() + " value: " + entry.getValue());
//for (Map.Entry<String, String> entry : ResponseParams.entrySet()) System.out.println(entry.getKey() + " value: " + entry.getValue());
//Add defined Parameters with Values from the Request
for (Iterator<String> itRP = ResponseParams.keySet().iterator(); itRP.hasNext();) {
String Key = (String) itRP.next();
if (Key.contains("Signature")) {
//pwdebug.println("Response to Sign: " + ResponseEncoded);
//System.out.println("Response to Sign: " + ResponseEncoded);
Signature signature = Signature.getInstance(Params.get("Signature Type"));
//pwdebug.println("Signature: Initiated");
//System.out.println("Signature: Initiated");
KeyStore keyStore = KeyStore.getInstance(Params.get("KeyStore Type"));
//pwdebug.println("Key Store: Initiated");
//System.out.println("Key Store: Initiated");
keyStore.load(new FileInputStream(Params.get("KeyStore File")), Params.get("KeyStore Password").toCharArray());
//pwdebug.println("Key Store: Loaded");
//System.out.println("Key Store: Loaded");
PrivateKey key = (PrivateKey) keyStore.getKey (Params.get("Certificate"), Params.get("KeyStore Password").toCharArray());
//pwdebug.println("Key Store: Private Key Loaded");
//System.out.println("Key Store: Private Key Loaded");
signature.initSign(key);
//pwdebug.println("Signature: Private Key Initiated");
//System.out.println("Signature: Private Key Initiated");
signature.update(ResponseEncoded.getBytes("UTF-8"));
//pwdebug.println("Signature: Signed");
//System.out.println("Signature: Signed");
String ResponseSignature = URLEncoder.encode(Base64.encode(signature.sign()), "UTF-8");
//pwdebug.println("Signature: Signed");
//System.out.println("Signature: Signed");
ResponseEncoded = ResponseEncoded.concat("&").concat(Key).concat("=").concat(ResponseSignature);
}
else ResponseEncoded = ResponseEncoded.concat("&").concat(Key).concat("=").concat(URLEncoder.encode(Params.get(Key), "UTF-8"));
}
String ResponseURL = Params.get("SLO_Response").concat("?").concat(ResponseEncoded);
//pwdebug.println("Final Response URL: " + ResponseURL);
//pwdebug.close();
//System.out.println("Final Response URL: " + ResponseURL);
//Send Logout to Server and redirect to Response to defined Destination
PrintWriter pwsaml = getAgentOutput();
pwsaml.flush();
pwsaml.println("[" + Params.get("HTTP_HSP_LISTENERURI") + "/" + DBName + "?logout&redirectto=" + URLEncoder.encode(ResponseURL, "UTF-8") + "]");
pwsaml.close();
//Recycle Agent and Session
AContext.recycle();
ASession.recycle();
} catch(Exception e) {
PrintWriter pwerror = getAgentOutput();
pwerror.flush();
pwerror.println(e);
System.out.println(e);
pwerror.close();
}
}
//Load Maps from Strings to identify Paramteres and Values
private static Map<String, String> map(Map<String, String> map, String input, String keys, String spliting, String pairing, Boolean keycount, Boolean empty) {
Map<String, String> output = map.isEmpty() ? new LinkedHashMap<String, String>() : map;
String[] Pairs = input.split(spliting);
int kc = 0;
for (String Pair : Pairs) {
kc = kc + 1;
int pos = Pair.indexOf(pairing);
String Key = pos > 0 ? Pair.substring(0, pos) : Pair;
if (keycount) Key = Key + " " + kc;
String Value = pos > 0 && Pair.length() > (pos + pairing.length()) ? Pair.substring(pos + pairing.length()) : "";
if (!output.containsKey(Key) && (empty || !Value.trim().isEmpty())) output.put((keys + Key).trim(), Value.trim());
}
return output;
}
//Decode and Inflate to XML
private static String decode_inflate(String input, Boolean infflag) throws IOException, DataFormatException {
byte[] inputDecoded = Base64.decode(input.getBytes("UTF-8"));
Inflater inflater = new Inflater(infflag);
inflater.setInput(inputDecoded);
byte[] outputBytes = new byte[1024];
int infLength = inflater.inflate(outputBytes);
inflater.end();
String output = new String(outputBytes, 0, infLength, "UTF-8");
return output;
}
//Deflate and Encode XML
private static String deflate_encode(String input, int level , Boolean infflag) throws IOException {
byte[] inputBytes = input.getBytes("UTF-8");
Deflater deflater = new Deflater(level, infflag);
deflater.setInput(inputBytes);
deflater.finish();
byte[] outputBytes = new byte[1024];
int defLength = deflater.deflate(outputBytes);
deflater.end();
byte[] outputDeflated = new byte[defLength];
System.arraycopy(outputBytes, 0, outputDeflated, 0, defLength);
String output = Base64.encode(outputDeflated);
return output;
}
//Define Date and Time Formats
private static SimpleDateFormat DateFormat = new SimpleDateFormat("yyyy-MM-dd");
private static SimpleDateFormat TimeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
//Formated Actual Time
private static String actualTime(String minTime, String maxTime, int localZone) throws ParseException {
Date actualtime = new Date();
long acttime = actualtime.getTime();
long mintime = resetTime(minTime, localZone);
long maxtime = resetTime(maxTime, localZone);
acttime = (acttime > mintime) && (acttime < maxtime) ? acttime: mintime + 1000;
return formatTime(acttime);
}
//Reset timemillis from String as defined
private static long resetTime(String givenTime, int localZone) throws ParseException {
Date date = DateFormat.parse(givenTime.substring(0, givenTime.indexOf("T")));
long days = date.getTime();
Date time = TimeFormat.parse(givenTime.substring(givenTime.indexOf("T") + 1, givenTime.indexOf("Z")));
long hours = time.getTime();
long zonecorr = localZone * 3600000;
return days + hours - zonecorr;
}
//Format timemillis into a String as required
private static String formatTime(long totalmilliSeconds) {
long date = 86400000 * (totalmilliSeconds/86400000);
long time = totalmilliSeconds % 86400000;
String dateString = DateFormat.format(date).concat("T");
String timeString = TimeFormat.format(time).concat("Z");
return dateString.concat(timeString);
}
public static String noCRLF(String input) {
String lf = "%0D";
String cr = "%0A";
String find = lf;
int pos = input.indexOf(find);
StringBuffer output = new StringBuffer();
while (pos != -1) {
output.append(input.substring(0, pos));
input = input.substring(pos + 3, input.length());
if (find.equals(lf)) find = cr;
else find = lf;
pos = input.indexOf(find);
}
if (output.toString().equals("")) return input;
else return output.toString();
}
}
आप मान्यता प्राप्त हो सकता है के रूप में, कई:
यह "लॉगआउट" एजेंट के लिए कोड है, जो डोमिनो सर्वर से उपयोगकर्ता लॉग आउट और भेजता IdP सेवा प्रदाता के लिए SAML लॉगआउट प्रतिक्रिया है टिप्पणी की गई लाइनों का उपयोग एजेंट को डीबग करने के लिए किया जा सकता है, यदि परिभाषाएं सही नहीं हैं और परिणामस्वरूप सफल लॉगआउट नहीं होता है। आप उन पंक्तियों को शुरू करने "//" को हटाकर उन पंक्तियों को आसानी से बदल सकते हैं और उन पैरामीटर को प्रिंट कर सकते हैं जिन्हें आप अपनी स्क्रीन पर देखना चाहते हैं या उन्हें लॉग में भेजना चाहते हैं।
डोमिनोज सर्वर पर एसएलओ शुरू करने के लिए, मैंने एक ही अवधारणा का उपयोग करके एक और जावा एजेंट लिखा। एजेंट को स्टार्ट एसएलओ कहा जाता है और "लॉगआउट" एजेंट के समान डेटाबेस में स्थित होता है। इस एजेंट का उपयोग सापेक्ष यूआरएल "/domcfg.nsf/startSLO?Open" खोलने वाले बटन बनाकर आपके किसी भी एप्लिकेशन में आसानी से कार्यान्वित किया जा सकता है। "StartSLO" एजेंट में निम्न कोड है .:
import lotus.domino.*;
import java.io.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session ASession = getSession();
AgentContext AContext = ASession.getAgentContext();
Database DB = AContext.getCurrentDatabase();
String DBName = DB.getFileName();
DBName = DBName.replace("\\", "/").replace(" ", "+");
//Load Data from Logout Request
Document Doc = AContext.getDocumentContext();
String ServerName = Doc.getItemValueString("HTTP_HSP_HTTPS_HOST");
int pos = ServerName.indexOf(":");
ServerName = pos > 0 ? ServerName.substring(0, ServerName.indexOf(":")) : ServerName;
String Query = Doc.getItemValueString("Query_String");
pos = Query.indexOf("?Open&");
Query = pos > 0 ? "?" + Query.substring(Query.indexOf("?Open") + 6) : "";
Doc.recycle();
DB.recycle();
//Load Parameters for the Response
DbDirectory Dir = ASession.getDbDirectory(null);
Database idpcat = Dir.openDatabase("idpcat.nsf");
View idpView = idpcat.getView("($IdPConfigs)");
Document idpDoc = idpView.getDocumentByKey(ServerName, false);
String SAMLSLO = idpDoc.getItemValueString("SAMLSloUrl");
idpDoc.recycle();
idpView.recycle();
idpcat.recycle();
Dir.recycle();
//Send Logout to Server and redirect to Response to defined Destination
PrintWriter pwsaml = getAgentOutput();
pwsaml.flush();
pwsaml.println("[" + SAMLSLO + Query + "]");
pwsaml.close();
//Recycle Agent and Session
AContext.recycle();
ASession.recycle();
} catch(Exception e) {
PrintWriter pwerror = getAgentOutput();
pwerror.flush();
pwerror.println(e);
System.out.println(e);
pwerror.close();
}
}
}
अब मुझे यह अपवाद मिल रहा है: ** बेस -64 चार सरणी ** के लिए अमान्य लंबाई **। असल में मैंने अनुरोध से नामक्यूलीफायर विशेषता हटा दी है और मैं पिछले एक के बजाय आरएसए-शाए 256 का उपयोग कर रहा हूं, चरण-दर-चरण ... – Gaucho
अंतिम ADFS2 लॉग: ADFS2: ** SAML अनुरोध अपेक्षित हस्ताक्षर एल्गोरिदम के साथ हस्ताक्षरित नहीं है। \t के साथ साइन इन किया गया: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 \t अपेक्षित: http://www.w3.org/2000/09/xmldsig#rsa-sha1* * – Gaucho
ठीक है, समस्या एल्गोरिदम है। मैं ** SHA1withRSA ** का उपयोग कर हस्ताक्षर उत्पन्न कर रहा हूं। मुझे ** http: //www.w3.org/2000/09/xmldsig#rsa-sha1 "का उपयोग करने की आवश्यकता होगी। [जावा एक्सएमएल एपीआई] का उपयोग करना (http://java.sun.com/developer/technicalArticles/ xml/dig_signature_api /) मैं एक SignedAuthnRequest xml उत्पन्न करने में सक्षम हूं, लेकिन मुझे HTTP-Redirect (SAMLRequest = value और SigAlg = value और Signature = value) लागू करने की आवश्यकता होगी ... – Gaucho