Original articles, reproduced please indicate: reproduced since Keegan small steel and indicate the original links: http://keeganlee.me/post/architecture/20160107 WeChat subscription number: keeganlee_me written in the 2016-01-07

App Architecture Design Experience talk: Interface design Experience Talk: technology selection Experience Talk: Data Layer design Experience Talk: Business Layer design experience talk: Display layer design

How to design the communication interface between App and server well, there are a lot of places that need to be considered. Here, based on my experience, I will make some summaries and share, aiming to throw off a brick and introduce jade.

Design of security mechanism

Today, most apps use RESTful interfaces. One of the most important design principles of RESTful interfaces is that client and server interactions are stateless between requests. That is, when it comes to user state, authentication information is required for each request. In implementation, most of them use token authentication. The general process is as follows:

  1. After the user successfully logs in using the password, the server returns the token to the client.
  2. The client saves the token locally and sends the token back to the server for subsequent requests.
  3. The server checks the validity of the token. If the token is valid, the server returns data. If the token is invalid, there are two cases:
    • If the token is incorrect, the user needs to re-log in to obtain the correct token
    • If the token expires, the client initiates an authentication request to obtain a new token

However, there is a security problem with this method of authentication: when the login interface is hijacked, the hacker obtains the user’s password and token, and can then do anything with the user. Users must change their passwords to regain control.

How do you optimize it? The first solution is to use HTTPS. Based on HTTP, HTTPS adds SSL security protocol to automatically compress and encrypt data. In certain programs, HTTPS can prevent monitoring, hijacking, and retransmission, which improves security. However, SSL is not completely secure and can be hijacked. In addition, HTTPS configuration on the server is relatively complicated, and you need to apply for a certificate from the CA, and generally charge for it. In addition, HTTPS is inefficient. Generally, HTTPS is only used for systems with high security requirements, such as banks. Most apps with less security requirements still use HTTP.

Our current approach is to add signatures to each interface. Each time a client requests an interface, the key and all parameters are combined into a source string, and the signature value is generated based on the signature algorithm. When sending a request, the signature is sent to the server for verification. For a similar implementation, please refer to OAuth1.0’s signature algorithm. In this way, hackers do not know the key, do not know the signature algorithm, even if the interception of the login interface, subsequent requests cannot be successfully operated. However, because the signature algorithm is cumbersome and error-prone, it is only suitable for internal interfaces. If your interface belongs to an open API, it is not suitable for this kind of signature authentication. It is recommended to use OAuth2.0 authentication mechanism.

We also assign an appKey to each end, such as Android, iOS and wechat. Each end is assigned an appKey and a key respectively. An error will be reported if the appKey is not passed, and an error will be reported if the appKey is passed incorrectly. In this way, the security aspect adds another layer of defense, but also convenient to do some different processing strategies for different ends.

In addition, more and more apps now cancel the password login and adopt the login method of mobile phone number + SMS verification code. I also adopted this login method in the current project. This login method has several benefits:

  1. No need to register, no need to change the password, and no need to reset the password because you forgot it;
  2. Users no longer need to remember passwords and are not afraid of password leakage;
  3. Compared with password login, its security is significantly improved.

Design of interface data

The interface data is usually transmitted in JSON format, but it is important to note that there are only six data types for JSON values:

  • Number: integer or floating point Number
  • String: String
  • Boolean: true or false
  • Array: The Array is enclosed in square brackets []
  • Object: The Object is enclosed in curly braces {}
  • Null: Indicates an empty type

Therefore, no more than these six data types can be transmitted. In the past, we have tried to transfer the Date type, which will be converted to a string like “January 7, 2016 09:17:42 GMT+08:00”. This will cause problems when converting. Different parsing libraries may parse differently, some may be messed up, some may be directly abnormal. To avoid errors, you must do special handling and do the parsing yourself manually. To eradicate this problem, the best solution is to express dates in milliseconds.

In addition, “true” and “false” of the string, or the number of the string, and even “null” of the string appeared in the previous project, resulting in parsing errors, especially “null”, which led to the crash of the App. After a long time of checking, it was found out that the problem was caused by this problem. This is all because the server did not handle the data properly, causing some data to be converted to strings. Therefore, on the client side, the data returned by the server cannot be completely trusted, and all exceptions need to be handled accordingly.

The data structure returned by the server is generally:

{code: 0 message: "success" data: {key1: value1, key2: value2,... }}Copy the code

  • Code: status code. 0 indicates success. Non-0 indicates various errors
  • Message: Indicates the description information. The value is “success” if the information is successful and an error message if the information is incorrect
  • Data: Data returned on success, of type object or array

Different status codes need to be defined for different errors. Errors on the client and server must be distinguished. For example, 1XX indicates an error on the client and 2XX indicates an error on the server. Here are a few examples:

  • Zero: success
  • 100: Request error
  • 101: The appKey is missing
  • 102: Missing signature
  • 103: Missing parameters
  • 200: The server fails
  • 201: The service is unavailable
  • 202: The server is being restarted

Error messages are generally used in two ways: first, client developers debug to see what the error is; Second, it can be directly shown to users as an App error prompt. Mainly as an App error prompt, directly shown to users. So, most of them are short reminders.

The data field returns data only if the request is successful. The data type is limited to an object or an array, returning an object when the data requested is a single object or an array of objects when the data requested is a list. Do not pass data as a string or number. Even if the request requires only one data, such as token, the returned data should be:

// Data: {token: 123456} // Data: 123456Copy the code

Interface version design

Interfaces cannot be static; they will always change over time. There are several types of interface changes:

  • Data changes, such as adding data types that are not supported by older versions
  • Parameter changes, such as new parameters
  • Interface deprecation. The interface is no longer used

To accommodate these changes, interface versions must be designed. In terms of implementation, there are generally two approaches:

  1. Each interface has its own version. Generally, a version parameter is added to the interface.
  2. The interface system has a unified version. Generally, the version number is added to the URL, for example, http://api.domain.com/v2.

In most cases, the first approach is used. When an interface changes, the version number is overlaid on the interface and the interface is compatible with the previous version. The version of the new version of the App will be passed in when the development parameter is passed.

If the foundation of the whole interface system is changed, for example, the Microblogging API is upgraded from OAuth1.0 to OAuth2.0, the whole API is upgraded.

Sometimes, changes to one interface can affect other interfaces, but they may not be noticed at the time of doing so. Therefore, it is desirable to have a comprehensive testing mechanism to ensure that every interface change is tested at all relevant levels.

Write in the last

So much for interface design for the moment. If you have missed something or need to optimize it, welcome to discuss it together.

Scan the following QR code to follow the subscription number. Review images