Single Sign-on Performance Test Scheme

Keywords: Programming Java Apache JSON Linux

Project login system upgrade to single sign on: English full name Single Sign On. SSO is a multi-application system. Users can access all trusted applications with only one login. Previous unified login methods have been abandoned, because the single sign-on system is much more complex than the previous login system. The previous scheme requests an interface to obtain a user verification token. First, share the sequence diagram of the single sign-on technology solution:

Then send me the sequence diagram of the front-end call interface that I combed:

Performance testing is divided into two scenarios: Performance manometry scenario analysis: Skip unnecessary 302 response status requests, test only business logic related interfaces, do not process page related interfaces (resource files, etc.), login to complete the request for additional interfaces to complete login validation.

  • Scenario 1: A single user logs on to a single system. Step 1: Request the cas service login page, parse the page to get the secret key string (lt/execution) Step 2: Request the cas service login interface to obtain the TGC and ST tokens Step 3: Request svr service to verify ST token and obtain admin_jsession ID information Step 4: Request additional interfaces to complete login status verification

  • Scenario 2: A single user logs on to two systems Step 1: Request the cas service login page, parse the page to get the secret key string (lt/execution) Step 2: Request the cas service login interface to obtain the TGC token and ST1 token Step 3: Request the svr1 service to verify the ST1 token and obtain admin_jsession ID information Step 4: Request additional interfaces to complete the status verification of log-in svr1 Step 5: Request the cas service login interface (carrying the TGC token) to obtain the ST2 token corresponding to svr2 Step 6: Request svr2 service validation to verify ST2 token and obtain admin_jsessionid information Step 7: Request additional interfaces to complete svr2 login status verification

For these two scenarios, the test script is as follows:

import com.fun.base.constaint.ThreadBase
import com.fun.config.SqlConstant
import com.fun.frame.excute.Concurrent
import com.fun.utils.Time
import com.okayqa.teacherweb.base.OkayBase
import org.slf4j.Logger
import org.slf4j.LoggerFactory

class Tss extends OkayBase {
    private static Logger logger = LoggerFactory.getLogger(Tss.class)


    public static void main(String[] args) {
        def threadNum = changeStringToInt(args[0])
        def times = changeStringToInt(args[1])
        SqlConstant.flag = false


//        def threadNum = 3
//        def times = 2
        def arrayList = new ArrayList<ThreadBase>()
        for (int i = 0; i < threadNum; i++) {
            def thread = new ThreadBase<Integer>(new Integer(i)) {
                @Override
                protected void before() {

                }

                @Override
                protected void doing() throws Exception {
                    def mark = Time.getTimeStamp()
                    def base = getBase(changeStringToInt(getT()))
//                    def cookies = base.getCookies()
//                    Def base1 = new com.okayqa.public web.base.OkayBase()//Create user objects for public-web projects
//                    base1.init(cookies)//Initialize user objects
//                    def common = new SchoolCommon(base1)// / Create a School Public Interface Request Object
//                    def years = common.getYears()// / Request school year interface
                    def mark0 = Time.getTimeStamp()
                    def i1 = mark0 - mark
                    logger.error("----------------" + i1 + EMPTY)
                }

                @Override
                protected void after() {

                }
            }

            thread.setTimes(times)
            arrayList << thread
        }
        new Concurrent(arrayList).start()
//
        allOver()

    }
}

First, the user object code for each project is as follows:

package com.okayqa.teacherweb.base;

import com.fun.base.bean.BeanUtil;
import com.fun.base.bean.RequestInfo;
import com.fun.base.interfaces.IBase;
import com.fun.config.HttpClientConstant;
import com.fun.config.SqlConstant;
import com.fun.config.SysInit;
import com.fun.frame.SourceCode;
import com.fun.frame.httpclient.FanLibrary;
import com.okayqa.common.CasCredential;
import com.okayqa.common.Common;
import com.okayqa.common.Users;
import com.okayqa.teacherweb.bean.UserInfoBean;
import com.okayqa.teacherweb.function.UserCenter;
import com.okayqa.teacherweb.profile.Profile;
import com.okayqa.teacherweb.profile.UserApi;
import net.sf.json.JSONObject;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;

/**
 * Teacher Space Project
 * qa Project base class
 */
public class OkayBase extends SourceCode implements IBase {

    private static Logger logger = LoggerFactory.getLogger(OkayBase.class);

    private static OkayBase base;

    static {
        SqlConstant.REQUEST_TABLE = Common.SQL_REQUEST;
        SqlConstant.flag = Common.SQL_KEY;
        SqlConstant.PERFORMANCE_TABLE = Common.SQL_PERFORMANCE;
        if (FanLibrary.getiBase() == null) FanLibrary.setiBase(new OkayBase());
    }

    public final static String HOST = Profile.HOST;


    /**
     * Login response
     */
    JSONObject loginResponse;

    private UserInfoBean userInfoBean = new UserInfoBean();

    /**
     * Getting Object Method
     * <p>
     * User management is not yet in progress, and consent to use singletons
     * </p>
     *
     * @return
     */
    public static OkayBase getBase() {
        if (base == null) base = new OkayBase(0);
        return base;
    }

    public static OkayBase getBase(int i) {
        return new OkayBase(i);
    }

    public static OkayBase getBase(String name) {
        return new OkayBase(name);
    }

    long uid;

    String token;

    String username;

    public JSONObject getCookies() {
        return cookies;
    }

    public void setCookies(JSONObject cookies) {
        this.cookies = cookies;
    }

    public void addCookie(JSONObject cookies) {
        this.cookies.putAll(cookies);
    }

    JSONObject cookies = new JSONObject();


    @Override
    public void login() {
//        /**
//         * Single sign-on mode
        String url = UserApi.LOGIN;
        JSONObject params = new JSONObject();
        params.put("loginType", "1");
        params.put("platformType", "teacher");
        params.put("username", username);
        params.put("password", getPassword());
        params.put("pictureVerifyCode", "");
        params.put("phone", "");
        params.put("traceno", "");
        params.put("phoneVerifyCode", "");
        JSONObject tgc = CasCredential.getTGC(HOST, params);
        this.cookies = tgc.getJSONObject("cookie");
        String location = tgc.containsKey("location") ? tgc.getString("location") : EMPTY;
        if (!location.contains("ticket=ST-")) logger.error("Logon failed! "";
        JSONObject getResponse = this.getGetResponse(location.replace(HOST, EMPTY));
        UserCenter userCenter = new UserCenter(this.cookies);
        userInfoBean = userCenter.getUserinfo();
        logger.info("Account: {}, nickname: {}, subject name: {}, login success! ", username, userInfoBean. getName (), userInfoBean. getSubjectName ();"
    }

    /**
     * Get the default password for plaintext
     *
     * @return
     */
    public String getPassword() {
        return Profile.PWD;
    }

    public OkayBase(String username) {
        this.username = username;
        login();
    }

    public OkayBase(int i) {
        this.username = Users.getTeaUser(i);
        login();
    }

    protected OkayBase() {
    }

    public OkayBase(OkayBase okayBase) {
        this.uid = okayBase.uid;
        this.username = okayBase.username;
        this.token = okayBase.token;
        this.userInfoBean = okayBase.userInfoBean;
        this.cookies = okayBase.cookies;
    }

    public JSONObject getParams() {
        return getJson("_=" + getMark());
    }


    @Override
    public void init(JSONObject jsonObject) {
        addCookie(jsonObject);
        HttpGet get = FanLibrary.getHttpGet(Profile.LOGIN_REDIRECT);
        get.addHeader(FanLibrary.getCookies(jsonObject));
        JSONObject response = FanLibrary.getHttpResponse(get);
        JSONObject credential = CasCredential.verifyST(response.getString("location"));
        addCookie(credential);
    }

    public JSONObject getLoginResponse() {
        return loginResponse;
    }

    public long getUid() {
        return uid;
    }

    public String getToken() {
        return token;
    }

    public String getUname() {
        return username;
    }

    public UserInfoBean getUserInfoBean() {
        return userInfoBean;
    }

    @Override
    public HttpGet getGet(String s) {
        return FanLibrary.getHttpGet(HOST + s);
    }

    @Override
    public HttpGet getGet(String s, JSONObject jsonObject) {
        return FanLibrary.getHttpGet(HOST + s, jsonObject);
    }

    @Override
    public HttpPost getPost(String s) {
        return FanLibrary.getHttpPost(HOST + s);
    }

    @Override
    public HttpPost getPost(String s, JSONObject jsonObject) {
        return FanLibrary.getHttpPost(HOST + s, jsonObject);
    }

    @Override
    public HttpPost getPost(String s, JSONObject jsonObject, File file) {
        return FanLibrary.getHttpPost(HOST + s, jsonObject, file);
    }

    @Override
    public JSONObject getResponse(HttpRequestBase httpRequestBase) {
        setHeaders(httpRequestBase);
        JSONObject response = FanLibrary.getHttpResponse(httpRequestBase);
        handleResponseHeader(response);
        return response;
    }

    @Override
    public void setHeaders(HttpRequestBase httpRequestBase) {
        httpRequestBase.addHeader(Common.REQUEST_ID);
        this.addCookie(getJson("user_phone_check_" + this.username + "=true"));
        if (!cookies.isEmpty()) httpRequestBase.addHeader(FanLibrary.getCookies(cookies));
    }

    @Override
    public void handleResponseHeader(JSONObject response) {
        if (!response.containsKey(HttpClientConstant.COOKIE)) return;
        cookies.putAll(response.getJSONObject(HttpClientConstant.COOKIE));
        response.remove(HttpClientConstant.COOKIE);
    }

    @Override
    public JSONObject getGetResponse(String s) {
        return getResponse(getGet(s));
    }

    @Override
    public JSONObject getGetResponse(String s, JSONObject jsonObject) {
        return getResponse(getGet(s, jsonObject));
    }

    @Override
    public JSONObject getPostResponse(String s) {
        return getResponse(getPost(s));
    }

    @Override
    public JSONObject getPostResponse(String s, JSONObject jsonObject) {
        return getResponse(getPost(s, jsonObject));
    }

    @Override
    public JSONObject getPostResponse(String s, JSONObject jsonObject, File file) {
        return getResponse(getPost(s, jsonObject, file));
    }

    @Override
    public boolean isRight(JSONObject jsonObject) {
        if (jsonObject.containsKey("success")) return jsonObject.getBoolean("success");
        int code = checkCode(jsonObject, new RequestInfo(getGet(HOST)));
        try {
            JSONObject data = jsonObject.getJSONObject("data");
            return code == 0 && !data.isEmpty();
        } catch (Exception e) {
            output(jsonObject);
            return false;
        }

    }

    /**
     * Get and check the code
     *
     * @param jsonObject
     * @return
     */
    public int checkCode(JSONObject jsonObject, RequestInfo requestInfo) {
        int code = TEST_ERROR_CODE;
        if (SysInit.isBlack(requestInfo.getHost())) return code;
        try {
            code = jsonObject.getInt("code");
        } catch (Exception e) {
            logger.warn("Non-standard response:{}", jsonObject.toString());
        }
        return code;
    }

    /**
     * End of the test, release of resources
     */
    public static void allOver() {
        FanLibrary.testOver();
    }

}

The code for the unified validation class is as follows:

package com.okayqa.common

import com.fun.config.HttpClientConstant
import com.fun.frame.httpclient.FanLibrary
import com.fun.utils.Regex
import net.sf.json.JSONObject
import org.apache.http.client.methods.HttpGet
import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
 * cas Service authentication class, mainly to solve the web-side login authentication function
 */
class CasCredential extends FanLibrary {
    static final String OR="/"
    private static Logger logger = LoggerFactory.getLogger(CasCredential.class)
    /**
     * Check values, random one-time, retrieved from login return page
     */
    String lt
    /**
     * Check value, random one-time, retrieved from login return page, the normal length is 4000 +, less than 4000 please check whether the request connection has entered the address of the callback service.
     */
    String execution

/**
 * Get the token pair from the login page of the cas service, which is temporarily available and will modify form submission in Phase II
 */
    CasCredential(String host) {
        def get = getHttpGet(Common.CAS_LOGIN + (host.endsWith(OR) ? host : host + OR))
        get.addHeader(Common.REQUEST_ID)
        def response = getHttpResponse(get)
        def string = response.getString("content")
        this.lt = Regex.getRegex(string, "<input type=\"hidden\" name=\"lt\" value=\".*?\" />")
        this.execution = Regex.getRegex(string, " <input type=\"hidden\" name=\"execution\" value=\".*?\" />")
//        logger.info("cas service login host:{}, lt:{}, execution:{}", host, lt, execution)
    }

/**
 * The parameters of each server are the same. Each service can assemble the parameters and pass them to the server, and then get the token pair at the cas service.
 * @param host The host address of the service, callback is completed by each service itself, the second verification is also, the host here is not compatible, there is cascredential for processing.
 * @param params Put together the parameters
 * @return
 */
    static JSONObject getTGC(String host, JSONObject params) {
        def credential = new CasCredential(host)
        params.put("lt", credential.getLt());
        params.put("execution", credential.getExecution())
        params.put("_eventId", "submit");
        def post = FanLibrary.getHttpPost(Common.CAS_LOGIN + (host.endsWith(OR) ? host : host + OR), params)
        post.addHeader(Common.REQUEST_ID);
        FanLibrary.getHttpResponse(post)
    }

/**
 * Through user
 * @param url
 * @return
 */
    public static JSONObject verifyST(String url) {
        HttpGet location = FanLibrary.getHttpGet(url);
        location.addHeader(Common.REQUEST_ID);
        JSONObject httpResponse = FanLibrary.getHttpResponse(location);
        httpResponse.getJSONObject(HttpClientConstant.COOKIE) as JSONObject
    }
}

Then it was finished smoothly. Because the previous performance testing solutions used jmeter as a solution, the test cases of this architecture change were difficult to implement, so the script was used. The performance framework uses the previous one. Performance testing framework Interested can click to see, the language is mainly Java, scripts written in Groovy.

Selection of Technical Articles

Selection of non-technical articles

Great coffee style

Click on the Public Number Map

Posted by eastcoastdubs on Tue, 08 Oct 2019 03:25:00 -0700