首页 > 解决方案 > ReadyAPI-在无头模式下请求访问令牌失败以在 CI/CD 管道中检索 oauth 2 令牌

问题描述

我正在使用下面的代码来生成 accessToken。

import com.eviware.soapui.impl.rest.actions.oauth.OltuOAuth2ClientFacade;
    import com.eviware.soapui.support.editor.inspectors.auth.TokenType;
    import com.eviware.soapui.model.support.ModelSupport;
    
    // Set up variables
    def project = ModelSupport.getModelItemProject(context.getModelItem());
    def authProfile = project.getAuthRepository().getEntry("user");
    def oldToken = authProfile.getAccessToken();
    def tokenType = TokenType.ACCESS;
    //log.info("OLD TOKEN: " + oldToken);
    
    // Create a facade object
    def oAuthFacade = new OltuOAuth2ClientFacade(tokenType);
    
    // Request an access token in headless mode
    oAuthFacade.requestAccessToken(authProfile, true, true);
    
    // Wait until the access token gets updated
    //while(oldToken == authProfile.getAccessToken()) {
    //}
    //The sleep method can be used instead of a while loop
    //sleep(3000);
    
    for(int i = 0; i<=6000; i++){
    if(oldToken != authProfile.getAccessToken()){
    break
    }
    sleep(1)
    }
    
    // Post the info to the log
    def token = authProfile.getAccessToken();
    log.info("NEW TOKEN: " + authProfile.getAccessToken());
    
    testRunner.testCase.testSuite.project.setPropertyValue( "accessToken", token )

此代码在笔记本电脑中没有问题。但是在 CI/CD 管道中配置时,代码失败并显示错误消息:-

发生错误[/tmp/JxBrowser/7.12/libbrowsercore_toolkit.so: libX11.so.6: cannot open shared object file: No such file or directory],详见错误日志 Groovy Script测试的脚本发生错误步骤 [Groovy 脚本 3]:[errorlog] java.lang.UnsatisfiedLinkError:/tmp/JxBrowser/7.12/libbrowsercore_toolkit.so:libX11.so.6:无法打开共享对象文件:没有这样的文件或目录 java.lang.UnsatisfiedLinkError: /tmp/JxBrowser/7.12/libbrowsercore_toolkit.so:libX11.so.6:无法打开共享对象文件:没有这样的文件或目录

标签: groovysoapuiready-api

解决方案


我能够通过将以下代码放在“安装脚本”中来解决该问题。在过去的 2 天里,这些脚本正在运行,管道中没有任何问题。

import com.eviware.soapui.impl.wsdl.submit.filters.AbstractRequestFilter
import com.eviware.soapui.impl.wsdl.submit.filters.OAuth2RequestFilter
import com.eviware.soapui.impl.wsdl.submit.RequestTransportRegistry
RequestTransportRegistry.getTransport("https").replaceRequestFilter(OAuth2RequestFilter, new modifiedOAuth2RequestFilter())


/*
 *   below is a copy of class OAuth2RequestFilter with a new name as retrieved from 
 *   https://github.com/SmartBear/soapui/blob/next/soapui/src/main/java/com/eviware/soapui/impl/wsdl/submit/filters/OAuth2RequestFilter.java
 *   except that the ACCESS_TOKEN_RETRIEVAL_TIMEOUT value has been changed from 5000 to 10000
 */   

import com.eviware.soapui.config.TimeUnitConfig;
import com.eviware.soapui.impl.rest.OAuth2Profile;
import com.eviware.soapui.impl.rest.OAuth2ProfileContainer;
import com.eviware.soapui.impl.rest.RestRequestInterface;
import com.eviware.soapui.impl.rest.actions.oauth.OAuth2ClientFacade;
import com.eviware.soapui.impl.rest.actions.oauth.OltuOAuth2ClientFacade;
import com.eviware.soapui.impl.support.AbstractHttpRequest;
import com.eviware.soapui.impl.wsdl.submit.transports.http.BaseHttpRequestTransport;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.propertyexpansion.PropertyExpander;
import com.eviware.soapui.support.StringUtils;
import com.eviware.soapui.support.TimeUtils;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.log4j.Logger;

import static com.eviware.soapui.config.CredentialsConfig.AuthType.O_AUTH_2_0;

public class modifiedOAuth2RequestFilter extends AbstractRequestFilter {
    private static final int ACCESS_TOKEN_RETRIEVAL_TIMEOUT = 10000;
    
    // intentionally left non-final to facilitate testing, but should not be modified in production!
    private static Logger log = Logger.getLogger(OAuth2RequestFilter.class);

    /* setLog() and getLog() should only be used for testing */

    static Logger getLog() {
        return log;
    }

    static void setLog(Logger newLog) {
        log = newLog;
    }

    @Override
    public void filterRestRequest(SubmitContext context, RestRequestInterface request) {

        HttpRequestBase httpMethod = (HttpRequestBase) context.getProperty(BaseHttpRequestTransport.HTTP_METHOD);
    log.info O_AUTH_2_0.toString()
        if (O_AUTH_2_0.toString().equals(request.getAuthType())) {
            OAuth2ProfileContainer profileContainer = request.getResource().getService().getProject()
                    .getOAuth2ProfileContainer();
            OAuth2Profile profile = profileContainer.getProfileByName(((AbstractHttpRequest) request).getSelectedAuthProfile());
            if (profile == null || StringUtils.isNullOrEmpty(profile.getAccessToken())) {
                return;
            }
            OAuth2ClientFacade oAuth2Client = getOAuth2ClientFacade();

            if (accessTokenIsExpired(profile)) {
                if (profile.shouldReloadAccessTokenAutomatically()) {
                    reloadAccessToken(profile, oAuth2Client);
                } else {
                    profile.setAccessTokenStatus(OAuth2Profile.AccessTokenStatus.EXPIRED);
                }
            }
            oAuth2Client.applyAccessToken(profile, httpMethod, request.getRequestContent());
        } 
    }

    protected OAuth2ClientFacade getOAuth2ClientFacade() {
        return new OltuOAuth2ClientFacade();
    }

   
    private boolean accessTokenIsExpired(OAuth2Profile profile) {
        long currentTime = TimeUtils.getCurrentTimeInSeconds();
        long issuedTime = profile.getAccessTokenIssuedTime();
        long expirationTime;

        if (profile.useManualAccessTokenExpirationTime()) {
            String expirationTimeString = profile.getManualAccessTokenExpirationTime() == null ? "" : profile.getManualAccessTokenExpirationTime();
            String expandedValue = PropertyExpander.expandProperties(profile.getContainer().getProject(), expirationTimeString);
            expirationTime = convertExpirationTimeToSeconds(expandedValue, profile.getManualAccessTokenExpirationTimeUnit());
        } else {
            expirationTime = profile.getAccessTokenExpirationTime();
        }

        //10 second buffer to make sure that the access token doesn't expire by the time request is sent
        return !(issuedTime <= 0 || expirationTime <= 0) && expirationTime < (currentTime + 10) - issuedTime;
    }

    private long convertExpirationTimeToSeconds(String expirationTimeString, TimeUnitConfig.Enum timeUnit) throws IllegalArgumentException {
        long expirationTime;
        try {
            expirationTime = Long.valueOf(expirationTimeString.trim());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Manual expiration time cannot be parsed due to invalid characters." +
                    "Please review it and make sure it is set correctly.", e);
        }
        if (timeUnit.equals(TimeUnitConfig.HOURS)) {
            return expirationTime * 3600;
        } else if (timeUnit.equals(TimeUnitConfig.MINUTES)) {
            return expirationTime * 60;
        } else {
            return expirationTime;
        }
    }

    private void reloadAccessToken(OAuth2Profile profile, OAuth2ClientFacade oAuth2Client) {
        try {
            if (profile.getRefreshToken() != null) {
                log.info("The access token has expired, trying to refresh it.");
                oAuth2Client.refreshAccessToken(profile);
                log.info("The access token has been refreshed successfully.");
            } else {
                if (profile.hasAutomationJavaScripts()) {
                    log.info("The access token has expired, trying to retrieve a new one with JavaScript automation.");
                    oAuth2Client.requestAccessToken(profile);
                    profile.waitForAccessTokenStatus(OAuth2Profile.AccessTokenStatus.RETRIEVED_FROM_SERVER,
                            ACCESS_TOKEN_RETRIEVAL_TIMEOUT);
                    if (profile.getAccessTokenStatus() == OAuth2Profile.AccessTokenStatus.RETRIEVED_FROM_SERVER) {
                        log.info("A new access token has been retrieved successfully.");
                    } else {
                        log.info("OAuth2 access token retrieval timed out after " + ACCESS_TOKEN_RETRIEVAL_TIMEOUT + " ms");
                        throw new RuntimeException("OAuth2 access token retrieval timed out after " + ACCESS_TOKEN_RETRIEVAL_TIMEOUT + " ms");
                    }
                } else {
                    log.info("No automation JavaScripts added to OAuth2 profile – cannot retrieve new access token");
                    throw new RuntimeException("No automation JavaScripts added to OAuth2 profile – cannot retrieve new access token");
                }
            }
        } catch (Exception e) {
            //Propagate it up so that it is shown as a failure message in test case log
            throw new RuntimeException("Unable to refresh expired access token.", e);
        }
    }
}

推荐阅读