Skip to content

Commit

Permalink
mvn-jgitflow:merging 'feature/#306-sahi-header' into 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobias Schneck committed Feb 6, 2018
2 parents 4670d80 + bddb57d commit 114b6f6
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 3 deletions.
3 changes: 3 additions & 0 deletions docs/index.adoc
Expand Up @@ -115,7 +115,10 @@ include::manual/testdefinition/advanced-topics/sahi-settings-browser-selection.a
include::manual/testdefinition/advanced-topics/sahi-settings-browser-config.adoc[]
include::manual/testdefinition/advanced-topics/sahi-settings-proxy.adoc[]
include::manual/testdefinition/advanced-topics/sahi-https.adoc[]

==== Sahi known issues
include::manual/testdefinition/advanced-topics/sahi-webpack.adoc[]
include::manual/testdefinition/advanced-topics/sahi-authorization-header.adoc[]

==== Sikuli settings
include::manual/testdefinition/advanced-topics/sikuli-settings-highlighting.adoc[]
Expand Down
@@ -0,0 +1,20 @@

:imagesdir: ../../../images

[[sahi-authorization-headers]]
===== Sahi removes authorization headers
[#git-edit-section]
:page-path: docs/manual/testdefinition/advanced-topics/sahi-authorization-header.adoc
git-link:{page-path}{git-view} | git-link:{page-path}{git-edit}

Due to issue https://github.com/ConSol/sakuli/issues/306[Disable Sahi proxy method which remove the authorization header (e.g. Bearer Token) #306] Sahi OS have currently some problems with handling authorization tokens like Bearer Token correctly. This has been also discussed at https://community.sahipro.com/forums/discussion/3941/authorization-header-getting-stripped-out[Sahi Community - Authorization header getting stripped out] and is a Problem of Sahi OS.

This behavior is not wanted, so the Sakuli team developed a solution which manipulates Sahi by some https://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/html/aop.html[Spring AOP Advice], for some details take look at https://github.com/ConSol/sakuli/blob/feature/%23306-sahi-header/src/core/src/main/java/org/sakuli/aop/SahiHeaderAspect.java#L59[Sahi Header Aspect]

By default nothing have been changed to avoid unexpected impact to other parts of Sahi OS. To skip the execution of the Sahi action which removes the authorization header , see https://github.com/kevlened/Sahi/blob/744f77462badeb3deddce93ddf6374773f70833f/sahi/src/net/sf/sahi/request/HttpRequest.java#L272[`HttpRequest.removeHeader("Authorization")`], set the following <<property loading mechanism,property>> to `false`:

sahi.proxy.removeAuthorizationHeader.enabled=false


For more details see issue https://github.com/ConSol/sakuli/issues/306[#306].

Expand Up @@ -375,8 +375,8 @@ sahi.proxy.maxConnectTries=25
sahi.proxy.reconnectSeconds=1
# amount of firefox profiles
ff.profiles.max_number=1


#### Sahi customisations done by Sakuli only
#
# Sahi delays on Sikuli input (put on helmet!)
#
# Sikuli keyboard events (type/paste) on a Sahi-controlled browser instance can get lost if
Expand All @@ -397,6 +397,12 @@ ff.profiles.max_number=1
# (gets only enabled if delayPerKey is set)
sahi.proxy.onSikuliInput.delayBeforeInput=500
sahi.proxy.onSikuliInput.delayPerKey=
#
# Dis/Enable if Sahi should remove the authorization header.
# See: http://consol.github.io/sakuli/latest/index.html#sahi-authorization-headers
# (Default by Sahi OS: true)
sahi.proxy.removeAuthorizationHeader.enabled=true


### HTTP/HTTPS proxy Settings
### Set a company proxy Sahi should use
Expand Down
70 changes: 70 additions & 0 deletions src/core/src/main/java/org/sakuli/aop/SahiHeaderAspect.java
@@ -0,0 +1,70 @@
/*
* Sakuli - Testing and Monitoring-Tool for Websites and common UIs.
*
* Copyright 2013 - 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sakuli.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.sakuli.datamodel.properties.SahiProxyProperties;
import org.sakuli.loader.BeanLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import static java.lang.Boolean.FALSE;

/**
* Aspect for the External Sahi Library {@link net.sf.sahi}
*
* @author tschneck Date: 17.10.13
*/
@Aspect
@Component
public class SahiHeaderAspect extends BaseSakuliAspect {

private final static Logger LOGGER = LoggerFactory.getLogger(SahiHeaderAspect.class);
private static Boolean removeAuthorizationHeader;

public static boolean getRemoveAuthorizationHeader() {
if (removeAuthorizationHeader == null) {
removeAuthorizationHeader = BeanLoader.loadBaseActionLoader().getSahiProxyProperties().getRemoveAuthorizationHeader();
if (FALSE.equals(removeAuthorizationHeader))
LOGGER.info("{}={}: SAHI remove Header 'Authorization' is DISABLED! ", SahiProxyProperties.REMOVE_AUTHORIZATION_HEADER, removeAuthorizationHeader);
}
return removeAuthorizationHeader;
}

/**
* Aspect to skip the execution of the action {@link net.sf.sahi.request.HttpRequest#removeHeader(String) } functionality for the headerString "Authorization"
*
* @param joinPoint injected joinPoint of the execution
* @param headerString will called with different header values from Sahi
*/
@Around("execution(* net.sf.sahi.StreamHandler.removeHeader(..)) && args(headerString)")
public void aroundSahiRemoveHeaders(ProceedingJoinPoint joinPoint, String headerString) throws Throwable {
if (FALSE.equals(getRemoveAuthorizationHeader()) && "Authorization".equals(headerString)) {
LOGGER.debug("SAHI skip remove Header '{}'", headerString);
//skip execution of method
return;
}
joinPoint.proceed();
}


}
Expand Up @@ -51,6 +51,7 @@ public class SahiProxyProperties extends AbstractProperties {
public static final String RECONNECT_SECONDS = "sahi.proxy.reconnectSeconds";
public static final String REQUEST_DELAY_MS = "sahi.proxy.onSikuliInput.delayPerKey";
public static final String REQUEST_DELAY_REFRESH_MS = "sahi.proxy.onSikuliInput.delayBeforeInput";
public static final String REMOVE_AUTHORIZATION_HEADER = "sahi.proxy.removeAuthorizationHeader.enabled";
public static final String DEFAULT_PROXY_PORT = "9999";
public static final String DEFAULT_RECONNECT_SECONDS = "1";
public static final String DEFAULT_MAX_CONNECT_TRIES = "25";
Expand Down Expand Up @@ -124,6 +125,11 @@ public class SahiProxyProperties extends AbstractProperties {
private Integer requestDelayMs;
@Value("${" + REQUEST_DELAY_REFRESH_MS + ":500}")
private Integer requestDelayRefreshMs;
/**
* Default behaviour of Sahi OS
*/
@Value("${" + REMOVE_AUTHORIZATION_HEADER + ":true}")
private Boolean removeAuthorizationHeader;
@Autowired
private SakuliProperties sakuliProperties;
@Autowired
Expand Down Expand Up @@ -256,4 +262,12 @@ public Integer getRequestDelayRefreshMs() {
public void setRequestDelayRefreshMs(Integer requestDelayRefreshMs) {
this.requestDelayRefreshMs = requestDelayRefreshMs;
}

public Boolean getRemoveAuthorizationHeader() {
return removeAuthorizationHeader;
}

public void setRemoveAuthorizationHeader(Boolean removeAuthorizationHeader) {
this.removeAuthorizationHeader = removeAuthorizationHeader;
}
}
2 changes: 1 addition & 1 deletion src/core/src/main/java/org/sakuli/loader/BeanLoader.java
Expand Up @@ -91,7 +91,7 @@ public static Region loadRegionRectangle(int x, int y, int w, int h, String resu
*/
public static <T> T loadBean(Class<T> classDef) {
try {
logger.debug("load bean '{}' from application context", classDef.getSimpleName());
logger.trace("load bean '{}' from application context", classDef.getSimpleName());
return getBeanFactory().getBean(classDef);
} catch (Throwable e) {
logger.error("error in BeanLoader", e);
Expand Down
72 changes: 72 additions & 0 deletions src/core/src/test/java/org/sakuli/aop/SahiHeaderAspectTest.java
@@ -0,0 +1,72 @@
/*
* Sakuli - Testing and Monitoring-Tool for Websites and common UIs.
*
* Copyright 2013 - 2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sakuli.aop;

import net.sf.sahi.request.HttpRequest;
import org.sakuli.datamodel.actions.LogLevel;
import org.sakuli.loader.BeanLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.util.ReflectionTestUtils;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
* Test for {@link SahiHeaderAspect}
*
* @author tschneck
* Date: 2/25/16
*/
public class SahiHeaderAspectTest extends AopBaseTest {

private final static Logger LOGGER = LoggerFactory.getLogger(SahiHeaderAspect.class);
private HttpRequest testling;

@BeforeMethod
@Override
public void setUp() throws Exception {
super.setUp();
initMocks();
InputStream input = new ByteArrayInputStream(new byte[]{});
testling = new HttpRequest(input);
}

@Test
public void testRemoveHeaderDisabeld() throws Exception {
final SahiHeaderAspect sahiHeaderAspect = BeanLoader.loadBean(SahiHeaderAspect.class);
ReflectionTestUtils.setField(sahiHeaderAspect, "removeAuthorizationHeader", false);
LOGGER.debug("SAHI this is not the correct line!");
testling.removeHeader("Authorization");
assertLastLine(logFile, "SAHI", LogLevel.DEBUG, "SAHI skip remove Header 'Authorization'");
}

@Test
public void testRemoveHeaderNotModiefied() throws Exception {
final SahiHeaderAspect sahiHeaderAspect = BeanLoader.loadBean(SahiHeaderAspect.class);
ReflectionTestUtils.setField(sahiHeaderAspect, "removeAuthorizationHeader", true);
final String controllMessage = "SAHI this is the expected line!";
LOGGER.debug(controllMessage);
testling.removeHeader("Authorization");
assertLastLine(logFile, "SAHI", LogLevel.DEBUG, controllMessage);
}

}

0 comments on commit 114b6f6

Please sign in to comment.