Android project network security configuration knowledge record
Android disables plaintext transmission by default after Android 9 (Pie) [Android :targetSdkVersion = 28]. The so-called plaintext transmission is Http request, so if we develop a version higher than 28, Http request in our app cannot succeed after packaging, will be thrown
W/System.err: java.net.UnknownServiceException: CLEARTEXT communication to **** not permitted by network security policy
Copy the code
The error.
Restriction history of Http requests:
- When Android 6.0 (Marshmallow) “(API 23)” was released, Google proposed the configuration in the manifest file:
android:usesCleartextTraffic
As a means of preventing accidental use of plaintext communication
<! -- Allows all plaintext communication by default -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<! -- Trust system to install CA certificate -->
<certificates src="system" />
<! -- Trust the CA certificate added by the user. Charles and Fiddler package capture tools are installed in this category.
<certificates src="user" />
</trust-anchors>
</base-config>
Copy the code
- Android 7.0 (Nougat) introduces the Android Network Security Configuration feature “Network Security Configuration” to transition developers to this property. Between Android 7.0 and 8.0 “(API 24) to (API 27)”, clients can still use Http requests. The default network security configurations are as follows
<! -- Allows all plaintext communication by default -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<! -- Trust system to install CA certificate -->
<certificates src="system" />
</trust-anchors>
</base-config>
Copy the code
- Android 9 (Pie) (API 28) forbids plaintext transmission by default
usesCleartextTraffic = true
And the default trust only system level certificates, that is, we in the mobile phone, set -> Encryption and credentials -> trusted credentials -> system TAB under all certificates.
<! -- Disables all plaintext communication by default -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<! -- Trust system to install CA certificate -->
<certificates src="system" />
</trust-anchors>
</base-config>
Copy the code
The impact of network security configuration on us developers
If we had used the default configuration, after we upgraded targetSdkVersion >= 24, we would have encountered an Https request that could not be captured using the certificate configured by the packet capture tool.
When we upgrade targetSdkVersion >= 28, we will not be able to respond to all Http requests.
From the description of the network configuration version change in the previous section, we can see that the reason is that the user certificate is no longer trusted above 24, so the packet cannot be captured. The reason why HTTP requests cannot be made above 28 is that the system does not allow plaintext transmission by default.
What is network security configuration?
Explained that the configuration can solve above cannot be caught and we meet to the problem of the HTTP request, we probably can be understood as the network security configuration is actually control the outside of the code of a configuration file, application reads the configuration to deciding to check HTTP requests, trusted user certificate.
As you can see, Google has made restrictions, but it has also given developers freedom. The next step is to follow the conscience of the developer.
“Best” practices
Of course, in response to Google dad’s request and user information security concerns, we should upgrade all server domain names to Https requests as soon as possible. However, sometimes we still have some domain names for Http requests cannot be replaced in time, so we need to configure them separately. And as for the formal APP package, we do not want to let others capture the package, to bring security risks to our server.
Allow plaintext transmission
- Methods a
There are two ways to configure plaintext transfer. The first is under the application node of the androidmanifest.xml in the main module of the project
<application ... <! - allows - > android: usesCleartextTraffic = "true"... >... </application>Copy the code
But this property after the Android 7.0 will be Android: networkSecurityConfig properties covered.
- Method 2
Add configure res/ XML /network_security_config. XML in the main project. If not, create a new file. This configuration overrides the default system configuration. So we can configure our own desired network configuration here. After the configuration is complete, we need to configure it under the application node of Androidmanifest.xml
<application ... <application android:networkSecurityConfig="@xml/network_security_config" <! -- will be overwritten after 7.0 --> <! --android:usesCleartextTraffic="true"--> ... >... </application>Copy the code
- How to configure
network_security_config
Can include:
Zero or one
base configuration, which is the default configuration. Any number of
specifies the request configuration for any domain name. 0 or 1
Specifies the configuration of the domain name in debug mode, which can be used to perform some independent configurations during debugging.
If we only need to support plaintext transmission under certain domain names, we can use domain-config to do this separately
<network-security-config> <! Have multiple domain - confing - allows the domain - the domain names under the config allow clear transmission - > < domain - config cleartextTrafficPermitted ="true"> <! --includeSubdomains includeSubdomains --> <domain includeSubdomains="true">example.com</domain>
<domain includeSubdomains="true">cdn.example2.com</domain> </domain-config> <! - in addition to domain - config under the label of the domain names are not allowed to clear transmission - > < base - config cleartextTrafficPermitted ="false" />
</network-security-config>
Copy the code
Trusted User certificate
For example, we need to allow packet capture in debug mode, i.e. the trusted user certificate can be configured as follows
<network-security-config> <! > <debug-overrides> <trust-anchors> <certificates SRC ="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
...
</network-security-config>
Copy the code
For more configuration information you can refer to the Google Documentation section: Network Complete Configuration.
The problem of Https certificate verification suddenly occurred to us when we were solving the complete configuration of the network. Why do we not have a certificate installed locally in our APP and do not need to ignore certificate verification when using OkHttp? Similarly, we did not download certificates when we visited most websites. You can access it. OkHttp validates server certificates issued by the CA authority by default. Some companies’ self-signed certificates do not. For example, 12306.
# reference
-
OkHttp3 official document HTTPS
-
Android Developers document
-
Complete network configuration
-
Android Developers document