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
- One line of java code prints a heart
- Linux performance monitoring software netdata Chinese version
- Interface Test Code Coverage (jacoco) Scheme Sharing
- Performance testing framework
- How to Enjoy Performance Testing on Linux Command Line Interface
- Graphic HTTP Brain Map
- How to Test Probabilistic Business Interface
- httpclient handles multi-user simultaneous online
- Automatically convert swagger documents into test code
- Five lines of code to build static blogs
- How httpclient handles 302 redirection
- A preliminary study on the testing framework of linear interface based on java
- Tcloud Cloud Measurement Platform
- How to Test Probabilistic Business Interface
- python plotly process interface performance test data method encapsulation
- Single Sign-on Performance Test Scheme
Selection of non-technical articles
- Why choose software testing as a career path?
- Ten Steps to Become a Great Java Developer
- Writing to everyone about programming thinking
- Obstacles to automated testing
- The Problems of Automated Testing
- Tested "Code Immortality" Brain Map
- Seven Steps to Become an Excellent Automated Testing Engineer
- Attitudes of Excellent Software Developers
- How to Execute Functional API Testing Correctly
- New Trends in Software Testing in the Next 10 Years
- New Trends in Software Testing in the Next 10 Years
- What problems does automated testing solve?
- 17 kinds of efficient skills commonly used by software testers
- 17 kinds of efficient skills commonly used by software testers - below
Great coffee style
- Tcloud Cloud Measurement Platform
- Android App Testing Tools and Knowledge Collection
- 4399AT UI Automation CI and CD
- Android App routine test content