Познакомьтесь с пентестом веб-приложений на практике в нашем новом бесплатном курсе
учитывая корни технологий и любовь МежДелМаша к ынтерпрайзуПопытка окунуть сообщество xPage в JEE
Так оно и есть JEE(JSF), только старое как окаменевший кал мамонта. Современный JSF и пр. уже далеко ушел от того, на котором основывалось XPages. Догонять надо, да никто, похоже, не собирается.Попытка окунуть сообщество xPage в JEE.
DAS норм, есть особенности:мне интересно, тоже читал... сейчас думаю как из J2EE подключиться в Domino: DAS и/или прямое обращение...
DAS норм, есть особенности:
-это хттп и нужны авторизационные куки (если сешн авторизация)
-получение энтрисов и прочая (коллекций) завязано на параметр &Count, надо проверять - что получил по ключу
-если есть фронт - учитывать редайректы (описывал в унификации разработки)
-приятная особенность - PATCH
-json позволяет любую морду рисовать на JS
достаточно SSO и генерить кукия так понимаю, что логиниться можно через URL names.nsf?login + параметрами логин/пароль, где-то я видел это... И надо SSO настраивать,чтобы между серверами проходило... И куки. Или нет?
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" rendered="false">
<xp:this.beforePageLoad><![CDATA[#{javascript:try {
var url = context.getUrl();
var host = url.getHost();
var domain=host.match(/\..*/)[0];
var response=facesContext.getExternalContext().getResponse();
//var token=paramValues.get("token").toString();
//var rUrl=paramValues.get("url").toString();
var user_enc = context.getUrlParameter('id');
print("::xAgent_token::id:" + user_enc);
var user=decrypt(base64_decode(user_enc));
print("::xAgent_token::User:" + user);
/* var httpURL = database.getHttpURL();
var dbUrl= httpURL.replace("http://", "https://").match(/(.+)\?/)[1];
print("url:"+dbUrl);
*/
var generated=LtpaGenerator(user);
//var header="LtpaToken=" + token + "; domain=" + domain + "; path=/";
//response.setHeader("Set-Cookie", header);
//facesContext.getExternalContext().redirect(rUrl);
var externalContext:javax.faces.context.ExternalContext = facesContext.getExternalContext();
var response:javax.servlet.http.HttpServletResponse = externalContext.getResponse();
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", -1);
var externalContext:javax.faces.context.ExternalContext = facesContext.getExternalContext();
var response:javax.servlet.http.HttpServletResponse = externalContext.getResponse();
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", -1);
var gVars=getVars();
print("::xAgent_token::token:"+generated);
response.setHeader("Set-Cookie", "LtpaToken=" + generated + "; domain="+ gVars.domain + "; path=/");
//response.setContentType("text/html;charset=UTF-8");
var writer:java.io.PrintWriter = response.getWriter();
writer.write(generated);
} catch(e) {
_dump(e);
}
}]]></xp:this.beforePageLoad>
<xp:this.resources>
<xp:script src="/SSJSUtils.jss" clientSide="false"></xp:script>
</xp:this.resources>
</xp:view>
function LtpaGenerator(userDN){
importPackage(lmike.org);
try{
var ltpa:LtpaGenerator1=new LtpaGenerator1();
if (arguments.length > 1){
//print("::LtpaGenerator::call Init with:"+arguments[1])
ltpa.initByConfiguration(sessionAsSigner,arguments[1]);
}else{
//print("::LtpaGenerator::call Init");
ltpa.initByConfiguration(sessionAsSigner);
}
//print("::LtpaGenerator::userDN"+userDN);
var token=ltpa.generateLtpaToken(userDN);
return token;
}catch(e){
return errAttr+e.toString();
}
}
/**
* LtpaToken Generator V1.1
*
* This Java class generates a valid LtpaToken valid for any user name.
*
* To use it on SSJS:
* -------------------
* importPackage(com.developi.openntf);
* var ltpa:LtpaGenerator=new LtpaGenerator();
* ltpa.initByConfiguration(sessionAsSigner, "Developi:LtpaToken");
* token=ltpa.generateLtpaToken("CN=Serdar Basegmez/O=developi");
*
* To use the token (make sure replace '.developi.info' with your SSO domain):
* -------------------------------------------------------------------------
* response=facesContext.getExternalContext().getResponse();
* response.setHeader("Set-Cookie", "LtpaToken=" + token + "; domain=.developi.info; path=/");
* facesContext.getExternalContext().redirect(someUrl);
*
* 1. "Developi:LtpaToken" is the SSO configuration key. If you are using Internet site configuration, it will be
* "Organization:TokenName". Otherwise, it will be "TokenName" only. You may check "($WebSSOConfigs)"
* view in the names.nsf database.
* 2. sessionAsSigner should be given as parameter to the initByConfiguration method.
* 3. The signer of the database design should be listed as 'Owner' or 'Administrator' in the SSO configuration.
* 4. Current version only supports Domino keys. Tokens imported from Websphere will not generate valid tokens.
*
* Important Note:
* You will see "LMBCS" encoding below. This is because of that Domino encodes user names in LMBCS charset.
* As long as you use standard ANSI characters, it's OK. However if you use other languages (like Turkish) in
* user names, it will be encoded in default charset (ISO-8859-1). Normally, Domino JVM does not support LMBCS
* encoding. So you have to install a supporting library. I have found ICU (International Components for Unicode) library.
* However, it cannot be attached into NSF. So you have to install it into Domino JVM. To do this;
*
* - Go to ICU Project site (http://www.icu-project.org)
* - Download "icu4j-49_1.jar" and "icu4j-charset-49_1.jar" (or latest versions)
* - Put those files into "{Domino Program Folder}\jvm\lib\ext"
* - Restart your HTTP task
*
* This will install ICU library into your server. This library is licensed under X-License and can be used commercially.
* I didn't try but it can also be installed via OSGi plugin. Let me know if you do it :)
* Direct link for download: http://apps.icu-project.org/icu-jsp/downloadPage.jsp?ver=49.1&base=j&svn=release-49-1
*
*/
package lmike.org;
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 LtpaGenerator1{
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";
private String WebSSOSite="CRUINTERNET:CISsite";
private boolean ready=false;
private int duration=300;
private String ltpaSecret="";
private String classID;
public LtpaGenerator1(){
classID="::"+this.getClass().getName()+"::";
System.out.println("constructor:" + this.getClass().getName());
}
public LtpaGenerator1(String ltpaSecret) {
this();
setLtpaSecret(ltpaSecret);
}
public LtpaGenerator1(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 {
/* System.out.println(memberID+"with:"+configName);
if (session==null)throw new Exception("session is null");
Database db=session.getCurrentDatabase();
if (db==null)throw new Exception("current db is null");
db.recycle();
*/
status="get server name";
String currentServer=session.getServerName();//db.getServer();
status="get NAB from:"+currentServer;
dbNames=session.getDatabase(currentServer, NAMESDB, false);
status="get view"+SSOVIEW;
ssoView=dbNames.getView(SSOVIEW);
status="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));
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", 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
}
}
public class AuthToken {
static final String key=<Мой супер секрет>;//шифруем имя этим ключем, xAgent расшифровывает им (берет из базы)
static final String userName=<Имя пользователя для которого генерим>;
static final String dominoHost=<FQDN сервера>;
static final String serverURL="https://"+dominoHost;
static final String dbPart="/"<Путь к базе от notesdata>;
static final String dasPart="/api/data/collections/name/";
private static final String authPage="/xAgent_token.xsp?id=";
static final String target=serverURL+dbPart+authPage;
static{TrustAllCertificates.install();}//для доверия всем https
}
import com.ibm.commons.util.io.json.JsonObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.URI;
import static com.setralubs.AuthToken.*;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;
public abstract class DASUtilsBase {
static final org.slf4j.Logger LOG = LoggerFactory.getLogger(new Throwable().getStackTrace()[0].getClassName());
public static final String API_BASE_URI = "/api";
public static final String API_DATABASES_URI = "/api/data";
public static final String API_VIEWS_URI = "/api/data/collections";
public static final String API_DOCUMENTS_URI = "/api/data/documents";
// argument prefixes
public static final String SERVER_ARG = "server=";
public static final String DATABASE_ARG = "database=";
public static final String USERNAME_ARG = "user=";
public static final String PASSWORD_ARG = "password=";
public static final String RESOURCES_ARG = "resources=";
public static final String VIEWNAME_ARG = "view=";
static String BaseURI = "https://";
static String databaseName = dbPart;
static String dominoServer=dominoHost;
static String viewName = "All";//"AllNames";
static String resourcesArg = "";
final JWT jwt;
CloseableHttpClient client = null;
public DASUtilsBase() {
jwt = new JWT();
String encBase64=new String(Base64.encodeBase64(jwt.encrypt(userName, key).getBytes()));
RequestConfig customizedRequestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
HttpClientBuilder customizedClientBuilder = HttpClients.custom().setDefaultRequestConfig(customizedRequestConfig);
//https://stackoverflow.com/a/40982127 redirect strategy
customizedClientBuilder.setRedirectStrategy(new DefaultRedirectStrategy() {
public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
Args.notNull(request, "HTTP request");
Args.notNull(response, "HTTP response");
int statusCode = response.getStatusLine().getStatusCode();
switch(statusCode) {
case 301:
case 307:
case 302:
case 308:
case 303:
return true;
case 304:
case 305:
case 306:
default:
return false;
}
}
public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException, ProtocolException {
URI uri = this.getLocationURI(request, response, context);
String method = request.getRequestLine().getMethod();
if(method.equalsIgnoreCase("HEAD")) {
return new HttpHead(uri);
} else if(method.equalsIgnoreCase("GET")) {
return new HttpGet(uri);
} else {
int status = response.getStatusLine().getStatusCode();
HttpUriRequest toReturn = null;
if(status == 301 || status == 307 || status == 308) {
toReturn = RequestBuilder.copy(request).setUri(uri).build();
toReturn.removeHeaders("Content-Length"); //Workaround for an apparent bug in HttpClient
} else {
toReturn = new HttpGet(uri);
}
return toReturn;
}
}
});
// Create the http client
client = customizedClientBuilder.build();
//set Authorization cookie
try {
HttpGet get = new HttpGet(target+encBase64);
HttpResponse response=client.execute(get);
printResponseBodyToConsole(response);
} catch (IOException ioe) {
LOG.error("Unable to connect to '" + serverURL + "'");
LOG.error(ioe.getMessage());
System.exit(-1);
}
}
//https://connect2id.com/products/nimbus-jose-jwt/examples/jwt-with-hmac
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
//import javax.crypto.KeyGenerator;
//import javax.crypto.SecretKey;
public class JWT {
public String sign(String payload, String secret) {
JWSSigner signer=null;
String ret="";
try {
//https://stackoverflow.com/questions/41882474/java-pad-a-string-with-ascii-0-null-to-a-multiple-of-16-bytes
byte[] plainBytes = secret.getBytes("UTF-8");
byte[] paddedBytes = new byte[32];
System.arraycopy(plainBytes, 0, paddedBytes, 0, plainBytes.length);
signer = new MACSigner(paddedBytes);
// Prepare JWT with claims set
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
.subject(payload)
// .issuer("https://c2id.com")
// .expirationTime(new Date(new Date().getTime() + 60 * 1000))
.build();
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
// Apply the HMAC protection
signedJWT.sign(signer);
// Serialize to compact form, produces something like
// eyJhbGciOiJIUzI1NiJ9.SGVsbG8sIHdvcmxkIQ.onO9Ihudz3WkiauDO2Uhyuz0Y18UASXlSc1eS0NkWyA
ret = signedJWT.serialize();
System.out.println("::"+this.getClass().getName()+"::signed:"+ret);
} catch (KeyLengthException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JOSEException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ret;
}
public String encrypt(String text, String key){
//String text = "Hello World";
//String key = "Bar12345Bar12345"; // 128 bit key
// Create key and cipher
Key aesKey = null;
byte[] plainBytes = null;
try {
plainBytes = key.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
byte[] paddedBytes = new byte[16];
System.arraycopy(plainBytes, 0, paddedBytes, 0, plainBytes.length);
aesKey = new SecretKeySpec(paddedBytes, "AES");
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// encrypt the text
try {
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] encrypted = null;
try {
encrypted = cipher.doFinal(text.getBytes("UTF-8"));
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("::"+this.getClass().getName()+"::encrypted size:"+encrypted.length);
return DatatypeConverter.printBase64Binary(encrypted);
//return new String(encrypted);
}
public String decrypt(String text, String key){
// decrypt the text
Key aesKey = null;
byte[] plainBytes=null;
try {
plainBytes = key.getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
byte[] paddedBytes = new byte[16];
System.arraycopy(plainBytes, 0, paddedBytes, 0, plainBytes.length);
aesKey = new SecretKeySpec(paddedBytes, "AES");
Cipher cipher = null;
try {
cipher = Cipher.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
cipher.init(Cipher.DECRYPT_MODE, aesKey);
} catch (InvalidKeyException e) {
e.printStackTrace();
}
String decrypted = null;
try {
System.out.println("::"+this.getClass().getName()+"::encrypted b64 size:"+DatatypeConverter.parseBase64Binary(text).length);
decrypted = new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(text)));
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
//System.err.println(decrypted);
return decrypted;
}
public static void main(String args[]){
JWT jwt=new JWT();
String key=<Мой супер ключ>;
System.out.println(jwt.decrypt(jwt.encrypt("test", key),key));
}
}
function secretEXT(){
var db:NotesDatabase=sessionAsSigner.getDatabase(session.getServerName(), session.getCurrentDatabase().getFilePath());
var NV:NotesView=db.getView(OPTIONS);
var doc:NotesDocument=NV.getDocumentByKey(OPT_SECRET);
// print("optSecret UNID:"+doc.getUniversalID())
secret=doc.getItemValueString(SECRETEXT_FLD);
doc.recycle();NV.recycle();db.recycle();
//print("::secretEXT::secret:\""+secret+"\"");
return secret;
}
function encrypt(text){
importPackage(lmike.org);
try{
var jwt:JWT=new JWT();
return jwt.encrypt(text, secretEXT());
}catch(e){
_dump(e);
}
}
function decrypt(text){
importPackage(lmike.org);
try{
var jwt:JWT=new JWT();
return jwt.decrypt(text, secretEXT());
}catch(e){
_dump(e);
}
}
надо чтобы сервер куки устанавливал, агент врядли сможет, сервлет писать - это практически хэпага@lmike
Круть, спасибо, а если без xpage?
public void authorize() throws IOException {
cookies=null;
URL url=new URL(target+encBase64);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (conn.getResponseCode() == 200) {
//read response from authPage
result2String(conn);
cookies = conn.getHeaderFields().get("Set-Cookie");
/*
for (String el : cookies) {
System.out.println(el);
}
*/
}
}
private String result2String(HttpURLConnection conn) throws IOException {
StringBuilder res = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
//System.out.println(line);
res.append(line);
}
reader.close();
return res.toString();
}
....
public InputStream request2URL(String target) throws IOException {
URL url=new URL(target);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (cookies!=null)
for (String cookie : cookies) {
conn.addRequestProperty("Cookie", cookie.split(";", 2)[0]);
}
InputStream res = null;
if (conn.getResponseCode() == 200) {
//System.out.println("OK");
res= conn.getInputStream();
if (cookies==null)cookies = conn.getHeaderFields().get("Set-Cookie");
}else{
System.out.format("Request status %d -> %s\n",conn.getResponseCode(),conn.getResponseMessage());
}
return res;
}
надо чтобы сервер куки устанавливал, агент врядли сможет, сервлет писать - это практически хэпага
не уверен в устойчивости работы, ща посмотрю...а так?
Ссылка скрыта от гостей&redirectto=/dbname.nsf/api/data/collections/name/<viewName>
или если обернуть в пост:
POSTСсылка скрыта от гостейHTTP/1.1
Content-Type: application/x-www-form-urlencoded
Username=ME&Password=Secret&redirectto=/dbname.nsf/api/data/collections/name/<viewName>
будет работать и без редайрект (redirectto)не уверен в устойчивости работы, ща посмотрю...
//HttpGet get = new HttpGet(target+encBase64);
HttpGet get = new HttpGet(BaseURI + dominoServer+"/names.nsf?Login&Username=Super%20User&Password=mypassword");
import com.ibm.commons.util.io.json.JsonObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.apache.http.*;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.*;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.URI;
import static com.setralubs.AuthToken.*;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;
public abstract class DASUtilsBase {
static final org.slf4j.Logger LOG = LoggerFactory.getLogger(new Throwable().getStackTrace()[0].getClassName());
public static final String API_BASE_URI = "/api";
public static final String API_DATABASES_URI = "/api/data";
public static final String API_VIEWS_URI = "/api/data/collections";
public static final String API_DOCUMENTS_URI = "/api/data/documents";
// argument prefixes
public static final String SERVER_ARG = "server=";
public static final String DATABASE_ARG = "database=";
public static final String USERNAME_ARG = "user=";
public static final String PASSWORD_ARG = "password=";
public static final String RESOURCES_ARG = "resources=";
public static final String VIEWNAME_ARG = "view=";
static String BaseURI = "https://";
static String databaseName = dbPart;
static String dominoServer=dominoHost;
static String viewName = "All";//"AllNames";
static String resourcesArg = "";
final JWT jwt;
CloseableHttpClient client = null;
public DASUtilsBase() {
jwt = new JWT();
String encBase64=new String(Base64.encodeBase64(jwt.encrypt(userName, key).getBytes()));
RequestConfig customizedRequestConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BROWSER_COMPATIBILITY).build();
HttpClientBuilder customizedClientBuilder = HttpClients.custom().setDefaultRequestConfig(customizedRequestConfig);
//https://stackoverflow.com/a/40982127 redirect strategy
customizedClientBuilder.setRedirectStrategy(new DefaultRedirectStrategy() {
public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException {
Args.notNull(request, "HTTP request");
Args.notNull(response, "HTTP response");
int statusCode = response.getStatusLine().getStatusCode();
switch(statusCode) {
case 301:
case 307:
case 302:
case 308:
case 303:
return true;
case 304:
case 305:
case 306:
default:
return false;
}
}
public HttpUriRequest getRedirect(HttpRequest request, HttpResponse response, HttpContext context) throws ProtocolException, ProtocolException {
URI uri = this.getLocationURI(request, response, context);
String method = request.getRequestLine().getMethod();
if(method.equalsIgnoreCase("HEAD")) {
return new HttpHead(uri);
} else if(method.equalsIgnoreCase("GET")) {
return new HttpGet(uri);
} else {
int status = response.getStatusLine().getStatusCode();
HttpUriRequest toReturn = null;
if(status == 301 || status == 307 || status == 308) {
toReturn = RequestBuilder.copy(request).setUri(uri).build();
toReturn.removeHeaders("Content-Length"); //Workaround for an apparent bug in HttpClient
} else {
toReturn = new HttpGet(uri);
}
return toReturn;
}
}
});
// Create the http client
client = customizedClientBuilder.build();
//set Authorization cookie
try {
HttpGet get = new HttpGet(target+encBase64);
//HttpGet get = new HttpGet(BaseURI + dominoServer+"/names.nsf?Login&Username=Super%20User&Password=mypassword");
HttpResponse response=client.execute(get);
printResponseBodyToConsole(response);
} catch (IOException ioe) {
LOG.error("Unable to connect to '" + serverURL + "'");
LOG.error(ioe.getMessage());
System.exit(-1);
}
}
static String getDatabaseName() {
return databaseName;
}
protected abstract JsonObject getDefaultItems();
protected abstract String getForm();
HttpEntity entityFromJson(JsonObject jsonItem) {
return new StringEntity(jsonItem.toString(),
APPLICATION_JSON);
}
HttpEntity entityFromJson(String jsonString) {
return new StringEntity("{"+jsonString+"}",
APPLICATION_JSON);
}
/*
* Use org.apache.commons.httpclient.methods.PostMethod to create a document.
* The new document URI is returned in the Location response-header field.
*/
String createDocument(String url, JsonObject jsonItem) throws IOException {
String NewDocURI = null;
url=url+"?"+"computewithform=true"+"&form="+getForm();
HttpPost post = new HttpPost(url);
post.setEntity(
new StringEntity(jsonItem.toString(),
APPLICATION_JSON));
HttpResponse response = client.execute(post);
if (response.getStatusLine().getStatusCode() != 201) {
LOG.error("Return code: " + response.getStatusLine().getStatusCode()
+ " on POST of url: " + url);
return null;
}
Header newLoc = response.getFirstHeader("Location");
NewDocURI = newLoc.getValue();
printResponseBodyToConsole(response);
return NewDocURI;
}
/*
* Use org.apache.commons.httpclient.methods.GetMethod to read a document.
*/
HttpResponse readDocument(String url) throws IOException {
HttpResponse response=null;
HttpGet get = new HttpGet(url);
get.addHeader("Content-Type", "application/json");
get.addHeader("Accept", "application/json");
response=client.execute(get);
return response;
}
String createBodyContent(String base64content, String attachName){
String fileSuffix = attachName.substring(attachName.lastIndexOf(".")+1);
return " \"Body\": {" +
" \"type\": \"multipart\"," +
" \"content\": [" +
" {" +
" \"contentType\": \""+MIMEType.get(fileSuffix)+"; name=\\\""+attachName+"\\\"\"," +
" \"contentDisposition\": \"attachment; filename=\\\""+attachName+"\\\"\"," +
" \"contentTransferEncoding\": \"base64\",\n" +
" \"data\": \""+base64content+"\"" +
" }" +
" ]" +
" }";
}
String createBodyContent(File file, String attachName) throws FileNotFoundException {
InputStream is=new FileInputStream(file);
String ret=null;
//byte[] bytes=new byte[(int)file.length()];
try {
byte[] bytes = IOUtils.toByteArray(is);
ret=createBodyContent(Base64.encodeBase64String(bytes),attachName);
} catch (IOException e) {
LOG.error(e.getMessage());
//e.printStackTrace();
}
return ret;
}
private void __updateDocument(HttpPatch put) throws IOException {
put.addHeader("Content-Type", "application/json");
put.addHeader("Accept", "application/json");
//put.addHeader("X-HTTP-Method-Override", "PATCH");
HttpResponse response = client.execute(put);
if (response.getStatusLine().getStatusCode() != 200) {
LOG.error("Return code: " + response.getStatusLine().getStatusCode()
+ "\nReason:"+response.getStatusLine().getReasonPhrase()
+ "\n on PUT of uri: " + put.getURI());
return;
}
LOG.debug("success PUT");
printResponseBodyToConsole(response);
LOG.debug("END PUT");
}
void updateDocument(String url, JsonObject jsonItem) throws IOException {
//url=url.replaceAll("http://","https://").replaceFirst(":[0-9]+","");
HttpPatch put = new HttpPatch(url);
put.setEntity(entityFromJson(jsonItem));
__updateDocument(put);
}
void updateDocument(String url, String jsonString) throws IOException{
//url=url.replaceAll("http://","https://").replaceFirst(":[0-9]+","");
HttpPatch put = new HttpPatch(url);
String s="{\n"+ jsonString+"}";
put.setEntity(new StringEntity(s));
__updateDocument(put);
}
/*
* Use org.apache.commons.httpclient.methods.DeleteMethod to delete a document.
*/
void deleteDocument(String url) throws IOException {
HttpDelete delete = null;
//url=url.replaceAll("http://","https://").replaceFirst(":[0-9]+","");
delete = new HttpDelete(url);
delete.addHeader("Content-Type", "application/json");
delete.addHeader("Accept", "application/json");
HttpResponse response = client.execute(delete);
printResponseBodyToConsole(response);
if (response.getStatusLine().getStatusCode() != 200) {
LOG.debug("Error: Return code "
+ response.getStatusLine().getStatusCode() + " with DELETE on url: "
+ url);
}
}
/*
* Print response body to standard out
*/
void printResponseBodyToConsole(HttpResponse response) {
try {
LOG.debug("Result:"+response.getStatusLine().getReasonPhrase());
LOG.debug("Response:\n"+org.apache.http.util.EntityUtils.toString(response.getEntity()));
} catch (IOException ioe) {
LOG.error("Unable to connect to '" + dominoServer
+ "'");
LOG.error(ioe.getMessage());
}
}
}
import com.ibm.commons.util.io.json.JsonJavaObject;
import com.ibm.commons.util.io.json.JsonObject;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class DASUtilsTest extends DASUtilsBase {
static final org.slf4j.Logger LOG = LoggerFactory.getLogger(new Throwable().getStackTrace()[0].getClassName());
public DASUtilsTest(){
super();
}
public static void main(String[] args) throws Exception {
DASUtilsTest obj=new DASUtilsTest();
BaseURI = BaseURI + dominoServer;
obj.testDocuments(BaseURI + "/" + getDatabaseName() + API_DOCUMENTS_URI);
}
/*
* Get list of views and folders of a database
*/
private void testViews(String url) {
HttpGet get = null;
try {
LOG.debug("");
LOG.debug("Test of views resource..\n");
get = new HttpGet(url);
HttpResponse response=client.execute(get);
printResponseBodyToConsole(response);
LOG.debug("End test of views resource..\n\n");
} catch (IOException ioe) {
LOG.error("Unable to connect to '" + dominoServer + "'");
LOG.error(ioe.getMessage());
System.exit(-1);
}
}
/*
* Get list of entries in a given view
*/
private void testViewEntries(String url) {
HttpGet get = null;
try {
LOG.debug("");
LOG.debug("Test of view entries resource..\n");
get = new HttpGet(url);
HttpResponse response=client.execute(get);
printResponseBodyToConsole(response);
LOG.debug("End test of view entries resource..\n\n");
} catch (IOException ioe) {
LOG.error("Unable to connect to '" + dominoServer + "'");
LOG.error(ioe.getMessage());
System.exit(-1);
}
}
/*
* Perform REST style CRUD (Create, Read, Update, and Delete) operations on a single document.
*/
private void testDocuments(String url) {
LOG.debug("");
LOG.debug("Test of documents resource..\n");
// Create a new document in the database and return the URI of the document.
String documentURI = null;
HttpResponse getResponse=null;
try {
documentURI=createDocument(url, getDefaultItems());
// Read the new document
getResponse = readDocument(documentURI);
} catch (IOException ioe) {
LOG.error("Unable to connect to '" + dominoServer
+ "'");
LOG.error(ioe.getMessage());
System.exit(-1);
}
if (getResponse.getStatusLine().getStatusCode() == 200) {
printResponseBodyToConsole(getResponse);
} else {
LOG.debug("Error: GET return code expected 200, actual "
+ getResponse.getStatusLine().getStatusCode());
System.exit(-1);
}
// Update the document, change City from "Quincy" to "Braintree".
JsonObject jsonItem = new JsonJavaObject();
jsonItem.putJsonProperty("TestField", "Test");
try {
updateDocument(documentURI, jsonItem);
String s=
"\"City\": \"FuckBraintree\",\n"+
" \"Subject\": \"Sample file attachment\",\n" +
createBodyContent(new File("add/image_1.jpg"), "image_1.jpg");//Images.testImage,"image.jpg")
updateDocument(documentURI, s);
s=createBodyContent(new File("add/image_1.jpg"), "imageXXX.jpg");
updateDocument(documentURI, s);
// Read the document after update.
getResponse = readDocument(documentURI);
if (getResponse.getStatusLine().getStatusCode() == 200) {
//printResponseBodyToConsole(getResponse);
} else {
LOG.debug("Error: GET return code expected 200, actual "
+ getResponse.getStatusLine().getStatusCode());
System.exit(-1);
}
// Delete the document.
deleteDocument(documentURI);
// Attempt to read the document after delete, should be not found.
getResponse = readDocument(documentURI);
if (getResponse.getStatusLine().getStatusCode() == 404) {
LOG.debug("Document not found, as expected.");
} else {
LOG.debug("Error: GET return code expected 404, actual "
+ getResponse.getStatusLine().getStatusCode());
System.exit(-1);
}
} catch (FileNotFoundException e) {
LOG.error(e.getMessage());
System.exit(-1);
} catch (IOException e) {
LOG.error("Unable to connect to '" + dominoServer
+ "'");
LOG.error(e.getMessage());
System.exit(-1);
}
}
@Override
protected JsonObject getDefaultItems() {
// Use JSON library methods to create a JSON object representing a new document.
JsonObject jsonItem = new JsonJavaObject();
jsonItem.putJsonProperty("FirstName", "Aaron");
jsonItem.putJsonProperty("LastName", "Adams");
jsonItem.putJsonProperty("EMail", "aaron_adams@renovations.com");
jsonItem.putJsonProperty("City", "Quincy");
jsonItem.putJsonProperty("State", "MA");
jsonItem.putJsonProperty("Id", "CN=Aaron Adams/O=renovations");
jsonItem.putJsonProperty("Form", "Contact");
return jsonItem;
}
@Override
protected String getForm() {
return "batch";
}
}
log4j.logger.com.setralubs.DASUtilsTest=DEBUG, DAS
log4j.logger.com.setralubs.DASUtilsBase=DEBUG, DAS
log4j.logger.com.setralubs.DASUtilsBase$1=INFO, DAS
log4j.appender.DAS=org.apache.log4j.ConsoleAppender
log4j.appender.DAS.layout=org.apache.log4j.PatternLayout
log4j.appender.DAS.layout.ConversionPattern=[%5p] %d [%t] %X{file} %c{1}:%L - %m%n
#log4j.rootLogger=INFO, stdout
#log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.Target=System.out
#log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
#[%5p] %d [%t] %X{file} %c{1} - %m%n
log4j.logger.net.sf.jsi=INFO, stdout
log4j.logger.org.apache.pdfbox=INFO, stdout
log4j.logger.org.apache.http=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
#log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
Обучение наступательной кибербезопасности в игровой форме. Начать игру!