创建react-native项目 ------ zigoo
myths-Mac:~ myth$ react-native init zigoomyths-Mac:~ myth$ cd /Home/myth/zigoo && yarn add react-navigation
import React,{ Component } from 'react';
import {
AppRegistry,
View,
Text,
StyleSheet,
ScrollView,
TouchableOpacity
} from 'react-native';
import { StackNavigator } from 'react-navigation';
import HomeScreen from './src/components/Home';
import Login from './src/components/Login';
import Register from './src/components/Register';
import Profile from './src/components/Profile';
const MyApp = StackNavigator({
Home: { screen: HomeScreen },
Login: { screen: Login },
Register: {screen: Register},
Profile: {screen: Profile}
});
export default MyApp;
AppRegistry.registerComponent('MyApp',() => MyApp);
src/components/Home.js 代码文件内容:
import React,Text,
Button,
TouchableOpacity,
StatusBar,
Image
} from 'react-native';
export default class Home extends Component{
static navigationoptions= ({navigation}) =>({
title: 'Welcome',
});
render(){
const { navigate } = this.props.navigation;
return(
<View style={styles.container}>
<Text style={styles.pageName}>User Login</Text>
<TouchableOpacity
onPress={() => navigate('Login')}
style={styles.btn1}>
<Text style={styles.btnText}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={()=> navigate('Register')}
style={styles.btn2}>
<Text style={styles.btnText}>Register</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
display:'flex',alignItems:'center',
justifyContent:'center'
},
btn1:{
backgroundColor:'orange',
padding:10,margin:10,width:'95%'
},
btn2:{
backgroundColor:'blue',
pageName:{
margin:10,fontWeight:'bold',
color:'#000',textAlign:'center'
},
btnText:{
color:'#fff',fontWeight:'bold'
},
});
AppRegistry.registerComponent('Home',() => Home);
src/components/Register.js 代码文件内容:
import React,{ Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,Button,TextInput,TouchableOpacity
} from 'react-native';
export default class Register extends Component {
static navigationoptions= ({navigation}) =>({
title: 'Register',
headerRight:
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={{margin:10,backgroundColor:'orange',padding:10}}>
<Text style={{color:'#ffffff'}}>Home</Text>
</TouchableOpacity>
});
constructor(props){
super(props)
this.state={
userName:'',
userEmail:'',
userPassword:''
}
}
userRegister = () =>{
const {userName} = this.state;
const {userEmail} = this.state;
const {userPassword} = this.state;
fetch('http://mo.com/register',{
method: 'POST',
headers:{
'Accept': 'application/json',
'Content-type': 'application/json'
},
body:JSON.stringify({
name: userName,
email: userEmail,
password: userPassword,
})
})
.then((response) => response.json())
.then((responseJson) =>{
alert(responseJson);
})
.catch((error)=>{
console.error(error);
});
}
render() {
return (
<View style={styles.container}>
<TextInput
placeholder="Enter Name"
style={{width:250,borderColor:"#333",
borderWidth:1}}
underlineColorAndroid="transparent"
onChangeText= {userName => this.setState({userName})}
/>
<TextInput
placeholder="Enter Email"
style={{width:250,borderWidth:1}}
underlineColorAndroid="transparent"
onChangeText= {userEmail => this.setState({userEmail})}
/>
<TextInput
placeholder="Enter Password"
style={{width:250,borderWidth:1}}
underlineColorAndroid="transparent"
onChangeText= {userPassword => this.setState({userPassword})}
/>
<TouchableOpacity
onPress={this.userRegister}
style={{width:200,padding:10,backgroundColor:'#3d6dcc',
alignItems:'center'}}>
<Text style={{color:'#fff'}}>Signup</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
});
AppRegistry.registerComponent('Register',() => Register);
src/components/Login.js 代码文件内容:
import React,TouchableOpacity,Keyboard
} from 'react-native';
import { StackNavigator } from 'react-navigation';
export default class Login extends Component {
static navigationoptions= ({navigation}) =>({
title: 'Login',
headerRight:
<TouchableOpacity
onPress={() => navigation.navigate('Home')}
style={{margin:12,padding:12}}>
<Text style={{color:'#ffffff'}}>Home</Text>
</TouchableOpacity>
});
constructor(props){
super(props)
this.state = {
userEmail:'',
userPassword:''
}
}
login = () => {
const { userEmail,userPassword } = this.state;
let reg = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;
if(userEmail == "") {
this.setState({email:'Please enter Email address'})
} else if(reg.test(userEmail) === false) {
this.setState({email:'Email is incorrect'})
return false;
} else if(userPassword=="") {
this.setState({email:'Please enter Password'})
} else {
fetch('http://mo.com/login',{
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ email: userEmail,password: userPassword })
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson == "ok"){
// redirect to profile page
alert("Login successfully");
this.props.navigation.navigate("Profile");
}else{
alert("Login Failed");
}
})
.catch((error) => {
console.error(error);
});
}
Keyboard.dismiss();
}
render() {
return (
<View style={styles.container}>
<Text style={{padding:10,color:'red'}}>{this.state.email}</Text>
<TextInput
placeholder="Enter Email"
style={{width:250,borderWidth:1}}
underlineColorAndroid="transparent"
onChangeText={userEmail => this.setState({userEmail})}
/>
<TextInput
placeholder="Enter Password"
style={{width:250,borderWidth:1}}
underlineColorAndroid="transparent"
onChangeText={userPassword => this.setState({userPassword})}
/>
<TouchableOpacity
onPress={this.login}
style={{width:200,alignItems:'center'}}>
<Text style={{color:'white'}}>Login</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
});
AppRegistry.registerComponent('Login',() => Login);
src/components/Profile.js 代码文件内容:
import React,{ Component } from 'react';
import { AppRegistry,View,StyleSheet } from 'react-native';
export default class Profile extends Component{
static navigationoptions= ({navigation}) =>({
title: 'Welcome',
});
render(){
const { navigate } = this.props.navigation;
return(
<View style={styles.container}>
<Text style={styles.pageName}>Profile</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container:{
display:'flex',
});
AppRegistry.registerComponent('Profile',() => Profile);
单向数字证书
[root@contoso ~]# openssl genrsa -out ca-app.key 2048 ## 1). 生成一个CA私钥
Generating RSA private key,2048 bit long modulus
.......................................................................................................................................................+++
..........+++
e is 65537 (0x10001)
[root@contoso ~]# openssl req -x509 -new -nodes -key ca-app.key -days 365 -out ca-app.crt ## 2).使用ca-app私钥生成客户端的数字证书
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.',the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:GuangDong
Locality Name (eg,city) [Default City]:ShenZhen
Organization Name (eg,company) [Default Company Ltd]:ZiGoo
Organizational Unit Name (eg,section) []: ## 直接按回车键跳过
Common Name (eg,your name or your server's hostname) []:mo.com
Email Address []:zhengzizhi@126.com
[root@contoso ~]# cp ca-app.key /etc/pki/tls/private/
[root@contoso ~]# cp ca-app.crt /etc/pki/tls/certs/
私钥文件 ca-app.key
数字证书 ca-app.crt
直接在httpd.conf配置文件查看apache执行用户和执行组,在以下红色字体标识的66行和67行即是用户和用户组,我们要把第66行和第67行改成如下的样子,其中myth是我登录CentOS 7.2系统的用户名
[myth@contoso ~]$ cat -n /etc/httpd/conf/httpd.conf #用此行命令查看httpd.conf文件的内容,注意我们要编辑的66和67行
第66行 User myth
第67行 Group myth
配置Apache服务器:
[myth@contoso ~]$ cat > /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.123.198 mo.com
[myth@contoso ~]$ cat > /etc/httpd/conf.d/httpd-vhosts.conf
<Directory "/home/myth/www/moapp">Options +Indexes +FollowSymLinks
Order allow,deny
Allow from all
AllowOverride All
Require all granted
</Directory>
<VirtualHost *:80>
ServerAdmin zhengzizhi@126.com
DocumentRoot "/home/myth/www/moapp/public"
ServerName mo.com
ServerAlias mo.com
ErrorLog "/home/myth/log/httpd/mo-com-error_log"
CustomLog "/home/myth/log/httpd/mo-com-access_log" common
</VirtualHost>
<Directory "/home/myth/www/moapp">
Options +Indexes +FollowSymLinks
Order allow,deny
Allow from all
AllowOverride All
Require all granted
</Directory>
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/ca-app.crt
SSLCertificateKeyFile /etc/pki/tls/private/ca-app.key
# SSLCertificateChainFile /etc/pki/tls/certs/ca-app.pem
ServerAdmin zhengzizhi@126.com
DocumentRoot "/home/myth/www/moapp/public"
ServerName mo.com
ServerAlias mo.com
ErrorLog "/home/myth/log/httpd/mo-com-s-error_log"
CustomLog "/home/myth/log/httpd/mo-com-s-access_log" common
</VirtualHost>
[myth@contoso ~]$ su -
Password:
Last login: Mon Apr 2 14:11:31 CST 2018 on pts/1
[root@contoso ~]# lsof -i:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 1069 root 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 1315 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 1316 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 1317 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 1318 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 1319 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 2860 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 18468 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
httpd 18688 myth 4u IPv6 23009 0t0 TCP *:http (LISTEN)
[root@contoso ~]# systemctl restart httpd && systemctl status httpd
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2018-04-03 23:44:21 CST; 13ms ago
Docs: man:httpd(8)
man:apachectl(8)
Process: 47406 ExecStop=/bin/kill -WINCH ${MAINPID} (code=exited,status=0/SUCCESS)
Main PID: 47415 (httpd)
Status: "Processing requests..."
CGroup: /system.slice/httpd.service
├─47415 /usr/sbin/httpd -DFOREGROUND
├─47416 /usr/sbin/httpd -DFOREGROUND
├─47417 /usr/sbin/httpd -DFOREGROUND
├─47419 /usr/sbin/httpd -DFOREGROUND
├─47420 /usr/sbin/httpd -DFOREGROUND
└─47421 /usr/sbin/httpd -DFOREGROUND
Apr 03 23:44:21 contoso.org systemd[1]: Starting The Apache HTTP Server...
Apr 03 23:44:21 contoso.org systemd[1]: Started The Apache HTTP Server.
配置macOS系统的hosts文件 ------ macOS这台机器是react-native这台开发机器
myths-Mac:~ myth$ sudo su
Password:
sh-3.2# cat > /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
192.168.123.198 mo.com
接下来我们要在macOS系统的命令行终端里通过命令去修改Android手机模拟器它的操作系统对应的hosts文件,修改它就有点特别啦,请按我的顺序执行指令,注意可能你的设备名称显示出来跟我的不一样,你需要开启两个终端窗口,一个用来首先用来启动安卓模拟用的,另外一个用来修改hosts文件用的,请特别注意192.168.123.198这个IP改成你实际的IP地址,本范例是在VMWare workstation pro 12 中实验的 1台PHP部署环境 用的系统是CentOS 7.2 另外一台开发react-native的机器是macOS系统
如果你已经有安卓模拟打开了 就必须关闭它们,那我们先来用命令以可写信息的模式来启动安卓模拟器吧:
电脑macOS系统中的命令终端窗口1,你发现自己emulator命令不是全局目录命令,
请参考我其它篇幅中讲的1条指令搞定配置部分
myths-Mac:~ emulator -list-avds #列出所有模拟器
Nexus_5X_API_23
myths-Mac:~ emulator -avd Nexus_5X_API_23 -writable-system #以可写信息的模式来启动安卓模拟器
电脑macOS系统中的命令终端窗口2,开始修改手机的hosts文件
myths-Mac:~ myth$ adb shell cat /etc/hosts
127.0.0.1 localhost::1 ip6-localhost
myths-Mac:~ myth$ adb root
adbd is already running as root
myths-Mac:~ myth$ adb remount
remount succeeded
myths-Mac:~ myth$ adb pull /system/etc/hosts ~/Desktop/hosts
/system/etc/hosts: 1 file pulled. 0.0 MB/s (56 bytes in 0.003s)
myths-Mac:~ myth$ echo '192.168.123.198 mo.com' >> ~/Desktop/hosts
myths-Mac:~ myth$ cat ~/Desktop/hosts
127.0.0.1 localhost
::1 ip6-localhost
192.168.123.198 mo.com
myths-Mac:~ myth$ adb push ~/Desktop/hosts /system/etc/hosts
/Users/myth/Desktop/hosts: 1 file pushed. 0.0 MB/s (81 bytes in 0.005s)
myths-Mac:~ myth$ adb shell cat /etc/hosts
127.0.0.1 localhost
::1 ip6-localhost
192.168.123.198 mo.com
myths-Mac:~ myth$
[root@contoso ~]# exit #如果你的命令是root用户模式,请一定要退出root模式
logout
[myth@contoso ~]$
创建基于ThinkPHP 5.1 框架PHP项目 ------ moapp,退出root账户的命令模式环境安装框架并创建moapp项目:
[myth@contoso ~]$ cd /home/myth/www && composer create-project topthink/think moapp --prefer-dist
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`email` varchar(30) DEFAULT NULL,
`password` varchar(36) DEFAULT NULL,
`mobile` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
配置路由:
/home/myth/www/moapp/route/route.PHP
<?PHP
Route::post('login','index/Login/signin'); // POST http://mo.com/login
Route::post('register','index/Register/signup'); // POST http://mo.com/register
return [
];
实现控制器方法:
/home/myth/www/moapp/application/index/controller/Register.PHP
<?PHP
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;
class Register extends Controller {
public function signup(Request $request) {
$name = $request->param('name');
$email = $request->param('email');
$password = md5($request->param('password'));
$user = ['name' => $name,'email' => $email,'password' => $password];
// 启动事务
Db::startTrans();
try {
$count = Db::name('users')->where(['email' => $email])->count('id');
if ($count == 0) {
Db::name('users')->insert($user);
}
// 提交事务
Db::commit();
if ($count == 0) {
return json('Registered Successfully');
} else {
return json('E-mail already exist');
}
} catch (Exception $ex) {
// 回滚事务
Db::rollback();
return json('signup Failed');
}
}
}
/home/myth/www/moapp/application/index/controller/Login.PHP
<?PHP
namespace app\index\controller;
use think\Controller;
use think\Request;
use think\Db;
class Login extends Controller {
public function signin(Request $request) {
$email = $request->param('email');
$password = md5($request->param('password'));
// 启动事务
Db::startTrans();
try {
$count = Db::name('users')
->where(['email' => $email])
->where(['password' => $password])
->count('id');
// 提交事务
Db::commit();
if ($count == 0) {
return json('login Failed');
} else {
return json('ok');
}
} catch (Exception $ex) {
// 回滚事务
Db::rollback();
return json('login Failed');
}
}
}
补充强调:模拟器必须用以下方式启动,开发工具上的启动方式启动安卓模拟器会立刻闪退,一旦模拟器被删掉,配置的手机hosts文件就立即被删掉
myths-Mac:~ Nexus_5X_API_23
以此处显示的Nexus_5X_API_23是模拟器的实际名称,我们可以用它来启动模拟器,当你发现开发工具上的模拟器按钮无法启动模拟器时,必须删除这个模拟重新创建一个新的模拟即可启动了,当然安卓手机的hosts文件也就恢复到了默认值 ------ 你配置的IP到域名映射关系就不存在啦
myths-Mac:~ emulator -avd Nexus_5X_API_23 -writable-system #以可写信息的模式来启动安卓模拟器