2024年7月

在移动互联网飞速发展的今天,如何高效地适配各种设备和屏幕尺寸已成为开发者的共同关切。这些多端开发框架,或许就是你需要的得力助手!

今天为大家带来的是一份特别的推荐清单——四个值得一试的多端开发框架!在移动互联网飞速发展的今天,如何高效地适配各种设备和屏幕尺寸已成为开发者的共同关切。这些多端开发框架,或许就是你需要的得力助手!

1. Flutter

官网地址:https://flutter.dev/

Flutter是Google推出的开源移动UI框架,支持iOS和Android平台的原生开发。凭借Dart语言的强大性能和丰富的组件库,Flutter能帮助你轻松实现各种复杂的界面效果。它的热重载功能也是一大亮点,可以实时预览代码修改效果,大大提高开发效率。

代码片段:

复制

import 'package:flutter/material.dart';  void main() => runApp(MyApp());  class MyApp extends StatelessWidget {  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      title: 'Flutter Demo',  
      theme: ThemeData(  
        primarySwatch: Colors.blue,  
      ),  
      home: MyHomePage(),  
    );  
  }  }  class MyHomePage extends StatefulWidget {  
  @override  
  _MyHomePageState createState() => _MyHomePageState();  }  class _MyHomePageState extends State<MyHomePage> {  
  int _counter = 0;  

  void _incrementCounter() {  
    setState(() {  
      _counter++;  
    });  
  }  

  @override  
  Widget build(BuildContext context) {  
    return Scaffold(  
      appBar: AppBar(  
        title: Text('Flutter Demo Home Page'),  
      ),  
      body: Center(  
        child: Column(  
          mainAxisAlignment: MainAxisAlignment.center,  
          children: <Widget>[  
            Text(  
              'You have pushed the button this many times:',  
            ),  
            Text(  
              '$_counter',  
              style: Theme.of(context).textTheme.headline4,  
            ),  
          ],  
        ),  
      ),  
      floatingActionButton: FloatingActionButton(  
        onPressed: _incrementCounter,  
        tooltip: 'Increment',  
        child: Icon(Icons.add),  
      ),   
    );  
  }  }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.


2. React Native

官网地址:https://reactnative.dev/

React Native是Facebook推出的基于JavaScript和React的开源移动开发框架。它允许开发者使用Web技术来构建原生应用,实现了跨平台的代码复用。React Native拥有丰富的社区资源和教程,可以帮助你快速上手。

代码片段:

复制

import React, { useState } from 'react';  import { View, Text, Button, StyleSheet } from 'react-native';  const App = () => {  
  const [count, setCount] = useState(0);  

  const incrementCount = () => {  
    setCount(count + 1);  
  };  

  return (  
    <View style={styles.container}>  
      <Text>You have pushed the button this many times: {count}</Text>  
      <Button title="Press me" onPress={incrementCount} />  
    </View>  
  );  };  const styles = StyleSheet.create({  
  container: {  
    flex: 1,  
    justifyContent: 'center',  
    paddingHorizontal: 10,  
  },  });  export default App;1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.


3. uni-app

官网地址:https://uniapp.dcloud.net.cn/

uni-app是一个使用Vue.js开发所有前端应用的框架。它允许开发者编写一套代码,然后发布到iOS、Android、Web(响应式)、以及各种小程序、快应用等多个平台。uni-app具有轻量级、易上手的特点,以及强大的跨平台性能,正逐渐成为多端开发领域的新星。

代码片段:

复制

<template>  
  <view class="content">  
    <text class="title">{{ title }}</text>  
    <button @click="incrementCount">Press me</button>  
  </view>  </template>  <script>  export default {  
  data() {  
    return {  
      count: 0,  
      title: 'uni-app Demo'  
    };  
  },  
  methods: {  
    incrementCount() {  
      this.count++;  
      uni.showToast({  
        title: 'You pressed the button!',  
        icon: 'success'  
      });  
    }  
  }  };  </script>  <style>  .content {  
  display: flex;  
  flex-direction: column;  
  align-items: center;  
  justify-content: center;  }  .title {  
  margin-bottom: 20px;  
  font-size: 24px;  }  </style>1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.


4. Taro

官网地址:https://taro-docs.jd.com/

Taro是一款多端统一开发框架,支持使用React进行Web、React Native、微信小程序、支付宝小程序等平台的开发。Taro具有完善的类型定义和文档支持,可以帮助你快速上手并高效开发。它还提供了丰富的插件和工具链,可以帮助你提升开发效率。

Taro支持使用React进行开发,下面是一个简单的Taro应用代码片段:

复制

import Taro, { Component } from '@tarojs/taro';  import { View, Text, Button } from '@tarojs/components';  import './index.scss';  class Index extends Component {  
  state = {  
    count: 0,  
  };  

  incrementCount = () => {  
    this.setState({ count: this.state.count + 1 });  
    Taro.showToast({ title: '你按下了按钮!', icon: 'success' });  
  };  

  render() {  
    return (  
      <View className='index'>  
        <Text>Taro Demo</Text>  
        <Text>你按下了按钮 {this.state.count} 次</Text>  
        <Button onClick={this.incrementCount}>按我</Button>  
      </View>  
    );  
  }  }  export default Index;1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.


总结对比:

  • Flutter凭借Dart语言的强大性能和丰富的组件库,适合构建高质量的原生界面;

  • React Native则允许使用Web技术构建原生应用,实现跨平台的代码复用。两者在性能上均表现出色,但Flutter的学习曲线可能较陡峭。

  • uni-app使用Vue.js开发,具有轻量级、易上手的特点;

  • Taro则支持使用Vue/React进行多平台开发。两者均适合快速构建多端应用,但uni-app的社区资源更为丰富。


原文地址:多端统一框架Taro基础教程 - 知乎

随着微信小程序越来越火,其它平台也都推出了自己的小程序产品(支付宝、快应用、百度、抖音)。小程序最大的特点就是平台能为你提供强大的流量,所以小程序开发变成了前端必会知识。 作为一个从来不想写程序,一心只想泡妹子的程序员,我一直期盼有一种解决方案,可以一次开发,多端运行。这也就是我的学习理念,每多学一点知识,就少些一些代码。期间我尝试Flutter、尝试uni-app、直到我遇到了Taro,我感觉血液在澎湃,多巴胺在快速分泌,又有了开车的心情。

课程共分为11节,篇幅略长,需要有点耐心哦。

P01:Taro框架简介和课程特点

Taro的优点

其实你能搜到这个教程,你至少对Taro这个框架有一个基本的了解。Taro是京东凹凸实验室推出的框架,目的就是解决多端混乱的局面。当我们按照一种模式一种代码进行开发,开发完成后,项目就有了在任何终端显示的能力,这是一种想想都很爽的。那具体Taro有那些优点,请看下面的图片。

目前Taro支持的终端

  • 微信小程序

  • H5 移动端Web页面

  • 百度小程序

  • 支付宝小程序

  • 快应用

  • ReactNative

  • 字节跳动小程序

  • QQ轻应用

是目前支持小程序最多的前端框架,并且支持ReactNatvie,说明我们可以轻易的生成媲美原生的APP应用。所以公司的应用如果想全网推广,占用最多的流量入口的话,使用Taro就完全没有问题。

作为一个程序员,你用统一的框架,统一的API,统一的代码规范,统一的代码结构,是多么棒的开发体验。从企业讲,一次开发就可以完成所有主流平台的布局,人力和时间成本压缩到最低,老板感觉节省了一个亿哦。

前置知识

学习这门课程你需要一些前置知识,这不是零基础课程,所以你需要在学习前会下面的知识。

  • HTML、CSS和JS的基本了解,你至少要能自己做出简单静态页面。

  • 理解MVVM框架,如果会React框架那是最好的。

  • 了解ES6相关的语法,因为文中我都会用ES6的语法来进行讲解

P02:Taro开发环境的搭建和Hello World

这节算是教程的正式开始,我们需要把Taro的开发环境搭建好,并且写出第一个Hello World程序。

Taro编译工具介绍

Taro是一套遵循React语法规范的多端开发解决方案,使用Taro,只书写一套代码,再通过Taro的编译工具,将源代码分别编译出可以再不同端(微信小程序,H5,RN等)运行代码。

所以说这里的Taro编译工具是非常重要的,这里附带一张图。

其实这些转换也是有很多坑的,这些坑需要在学习中不断给大家讲解。

Taro开发环境的安装

1.第一步是安装@tarojs/cli(脚手架工具),也有教开发工具的。

这个你可以使用npm或者yarn进行全局安装,命令如下:

npm的安装方式

npm install -g @tarojs/cli

yarn的安装方式

yarn global add @tarojs/cli

打开命令行后,输入上边的命令。

2.安装完成后,就可以用脚手架创建项目,命令如下:

taro init myDemo1
这里有个小坑就是如果你使用npm来安装脚手架的时候,有很大机率会失败,这些失败多是因为国内网络环境限制的。有两种解决方案,第一是挂xx来进行安装,第二种是使用yarn来进行暗转,我这里就使用了yarn。

Hello World程序

当我们都完成设置后,就可以在终端进入项目,cd myDemo1,然后执行下面的命令查看代码:

yarn dev:h5

这时候就会自动在浏览器中为我们打开一个网页,并显示出Hello World,这时候的端口是10086,使用这个端口可能京东的程序员当时正在为冲花费发愁。所以就起了这么一个端口。

总结

本节课的内容并不多,课程毕竟刚刚开始。这节主要讲解了Taro开发环境的安装和Hello World程序的编写。

P03:Taro生成小程序代码并预览

Taro可以生成小程序代码,但是我上节课并没有演示,所以很多小伙伴就优点迫不及待了。那这节我们就讲一下生成小程序代码,并在小程序开发工具中预览的详细步骤吧。

生成小程序代码

我们还是接着上节课的代码来作哦,打开VSCode后,打开终端,新进入项目目录,然后执行:

cd mydemo1
yarn dev:weapp  //关键代码

输入完命令后,taro编译器自动为我们生成小程序代码到dist目录中。

在微信开发者工具中预览

如果想开发小程序,你必须下载一个微信开发者工具,下载地址为:

微信开发者工具下载地址:

下载后安装步骤很简单,跟安装QQ几乎一样。

安装完成后,你需要注册一个账号,这个自己按照提示注册就可以了。

注册后导入一个小程序项目,需要注意的是这不是新建,而是导入一个项目。

导入后你就可以看到在微信开发者工具中显示Hello World!了。

必坑指南

讲到这里会出现第一个坑,就是你千万不要在微信开发者工具中修改dist目录中的代码,而是要持续开发Taro代码。因为你既然用了Taro,目的就是想维护一套代码,而在不同的终端中都可以使用。

如果你直接维护dist中的代码就使用使用Taro的意义了。

不要觉的这好像谁都知道,等你们真正工作时,你就会知道我现在强调这个坑的意义。因为你在工作中会遇到很多特殊的小程序独特需求,你就会想着利用这个方法来解决。

总结:我们已经实现了在小程序端预览Taro代码的需求,这节课也就结束了。可能你会觉的很短,但是你练习起来可能会多花一些时间,毕竟你还需要下载微信开发者工具和注册账号。

P04:Taro目录介绍

我们的Taro项目是用@tarojs/cli脚手架工具自动生成的,所以我们有必要了解一下这些目录和用处。这节课就利用几分钟时间来了解一下。

dist目录

这个目录是我们在预览时自动生成的,每次进行预览都会根据我们预览的终端不同,编译成不同代码,比如你使用yarn dev:h5那生成的就是web的代码,如果你使用yarn dev:weapp那生成的就是小程序的代码。

每次编译时都会删除以前的代码,这个小伙伴么要注意一下。

config目录

这个就是项目的一些配置,这些配置以后我们会不断深入学习,但是现在你还不了解,就不要进行配置。否则会影响项目的运行。

node_modules

项目所需的依赖包,就是我们使用npm install进行安装的包,一般你不需要修改。

src目录

这个是最重要的,这个是我们的源码目录,开发的所有代码都在这个里边。

官方给出的目录结构说明

├── dist                   编译结果目录
├── config                 配置目录
|   ├── dev.js             开发时配置
|   ├── index.js           默认配置
|   └── prod.js            打包时配置
├── src                    源码目录
|   ├── pages              页面文件目录
|   |   ├── index          index 页面目录
|   |   |   ├── index.js   index 页面逻辑
|   |   |   └── index.css  index 页面样式
|   ├── app.css            项目总通用样式
|   └── app.js             项目入口文件
└── package.json

P05:Taro使用React Hooks新特性

目前市面上的Taro教程,都是用原来老旧的React语法来讲的,都2020年了,我们应该拥抱React Hooks了。所以这节课我们就改造一下脚手架自动为我们生成的index.jsx页面,让他使用Hooks 新特性呈现。

那到底是用以前的老的React好,还是用Hooks好那?这个就好比你说49岁的莫文蔚好,还是27岁的迪丽热巴好,每个人的喜好可能不一样,但我喜欢年轻的。这就是为什么我个人要用Hooks的原因。

升级脚手架工具

我们每次进行调试的时候,都会出现红字,提示我们不是最新版本,我们可以使用命令进行升级。因为升级使用了npm的形式,所以升级过程非常慢,小伙伴们可以耐心等待一下。

在终端中输入下列命令进行升级。

taro update self

命令的具体意思是升级taro到大版本的最新版。升级完成后就不会显示红字了。

使用Hooks改造Index组件

打开/src/page/index/index.js页面,可以看到目前的代码全部都是React的基本语法,比如:继承components,比如React经典的生命周期,比如原来使用的statesetState赋值。

为了验证Hooks新特性可以使用,我们引入了useState.

import Taro, {  useState } from '@tarojs/taro'

引入后就可以使用function的形式来定义组件了,我这里给出全部代码,然后进行详细讲解。

import Taro, {  useState } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import './index.less'

function Index(){

  const [userName ,setUserName] = useState('Hello World!!!!')

  return ( 
    <View>
        <Text>{userName}</Text>
    </View>
  )

}

export default Index

这段代码就是把原来的基本React改成了用Hooks新特性来写,我们这套教程也尽量使用React Hooks来教学,这样可以保证大家学完后不至于落伍,紧跟前端开发进程。最后还是那句话,一定要动手作,否则你什么都学不会。

P06:Taro中子组件的编写和传值

使用Taro的一个好处就是可以用组件化的方式进行编程,所以编写组件在Taro中是每天都需要作的工作。这节课来看一下如何在Taro中编写一个子组件,并通过父组件进行传值。

编写子组件

打开/myDemo1/src/pages/index文件夹,在文件下面建立一个child.jsx文件,然后打开文件,编写组件代码:

import { View, Text } from '@tarojs/components'
function Child(){
  return ( 
    <View><Text>我是子组件</Text></View>
  )
}
export default Child

编写完成后这就是一个组件,使用也是非常简单的,直接到index.jsx页面中,用import进入这个组件。

import Child from './child.jsx'

需要注意的是这个Child要跟child.jsx中的fucntion的名称一样,否则在小程序中会有问题。引入后就可以直接用标签的形式进行使用了,这里为了方便学习,给出全部代码。

import Taro, {  useState } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import Child from './child.jsx'
import './index.less'

function Index(){

  const [userName ,setUserName] = useState('Hello World!!!!')

  return ( 
    <View>
        <Text>{userName}</Text>
        <Child></Child>
    </View>
  )

}

export default Index

这只是最简单的子组件,现在升级一下难度,我们要给子组件进行传值,看看如何进行操作。

父组件向子组件传值

学过React都知道,父组件向子组件传值是通过props进行,在Taro中也是可以这样传值的,现在修改index.jsx代码,把userName传递给子组件。

import Taro, {  useState } from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import Child from './child.jsx'
import './index.less'

function Index(){

  const [userName ,setUserName] = useState('Hello World!!!!')

  return ( 
    <View>
        <Text>{userName}</Text>
        <Child userName={userName}></Child>
    </View>
  )

}

export default Index

这篇传递后,子组件要增加props参数,然后才能用props进行接收。

import { View, Text } from '@tarojs/components'
function Child(props){
  return ( 
  <View><Text>我是子组件,父组件向我传值为:{props.userName}</Text></View>
  )
}
export default Child

这就完成了父组件向子组件的传值,是不是非常的简单。当我们会用组件的形式编写页面和组件时,你就可以作一些小东西了。但现在你可以看到,我们把页面和组件放到了一个文件夹下,并且都使用了jsx扩展名。那Taro时如何区分那些是组件,那些是页面的?其实它是通过自身的路由来区分的,只要配置路由的,就是页面,没配置的就默认是组件。下节课我们就讲解一下路由的相关操作。

P07:Taro 路由配置介绍

Taro中的路由设置跟React是不同的,它是通过app.jsx中的pages来配置的,并且谁配置在第一个数组位置,谁就是默认打开的首页。 ### 新建一个页面

我们先新建一个页面,这个在前面的课程已经讲过,但是为了练习,大家最好还是手写这些代码。

/src/pages/文件夹下,建立一个/blog文件夹,在文件夹下面建立一个blog.jsx文件,写入下面的代码:

import {View , Text} from '@tarojs/components'
function Blog(){
    return (
        <View>
            <Text>Blog Page</Text>
        </View>
    )
}
export default Blog

这样一个页面就建立好了,当然这个页面非常的简单,这些都无所谓,我们要学习的是路由。

配置路由

有了页面之后就可以到/src/app.jsx下,然后在pages的数组里面加入代码。

pages: [
    'pages/blog/blog',
    'pages/index/index'
],

这里需要注意一点,就是你不需要用import引入Blog页面,这个Taro为我们自动做好了。修改完成后,可以到浏览器中看一下,可以看到默认页面已经变成了Blog页面了。

页面间的跳转

Taro提供了6个相关的导航API,我们可以使用这些API进行跳转,需要注意的是这些有些是小程序专用的。

  • navigateTo: 最基本的跳转方式,可以返回上级页面。三端都支持的,小程序、H5、React Native。

  • redirectTo:不记录上集页面,直接跳转。三端都支持的,小程序、H5、React Native。

  • switchTab: Tab之间进行切换,这个要配合Taro的导航栏一起使用,三端都支持的,小程序、H5、React Native。

  • navigateBack: 返回上一级页面,这个在小程序中常使用,三端都支持的,小程序、H5、React Native。

  • relaunch:关闭所有额面,打开到应用内某个页面。三端都支持的,小程序、H5、React Native。

  • getCurrentPages:获取当前页面信息所用,这个H5是不支持的。(注意)

做个Demo,我们从Blog页面,跳转到Index页面,我们的程序如何来编写。

使用跳转需要使用Taro组件,所以先用import进行引入,然后再引入一个<Button>组件。

import Taro from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'

然后编写跳转方法,这里我们直接在function中进行声明.

const gotoIndex=()=>{
    Taro.navigateTo({url:'/pages/index/index'})
}

有了这个方法后,再编写一个按钮,然后再onClick事件中触发gotoIndex方法就可以了。

<Button onClick={gotoIndex}>我要去Index页面</Button>

为了方便你学习这里给出blog.jsx的全部代码。

import Taro from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Blog(){
    const gotoIndex=()=>{
        Taro.navigateTo({url:'/pages/index/index'})
    }
    return (
        <View>
            <Text>Blog Page</Text>
            <Button onClick={gotoIndex}>我要去Index页面</Button>
        </View>
    )
}
export default Blog

这样我们就实现了Taro中路由的跳转。这节课我们也先到这里,下节课我们讲一下跳转时如何携带参数,然后目标页面如何接收参数。

P08:Taro 页面间传递参数

上节课我们已经对Taro的路由机制有了基本的了解。比如我们在作应用时跳转大部分是需要携带参数的,比如我们从一个美女的列表页面,然后跳转到详细页面。这个就需要带参数。这就好比你去大宝剑,先是选择美女,然后你才能享受服务一样。所以参数很重要,如果参数错了,你选的可能是个极品,进去了却是恐龙。

查询字符串的形式进行传参

在Taro中进行传参,一般会使用查询字符串的形式,也就是在跳转的url上,加一个?问号的形式,然后后边跟上参数。

现在我们就在Blog.jsx页面用,useState的形式声明一个变量,再通过跳转把值带到Index.jsx页面。

import Taro ,{useState}from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Blog(){

    const  [blogTitle,setBlogTitle]=useState('JSPang Blog')

    const gotoIndex=()=>{
        Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle})
    }
    return (
        <View>
            <Text>Blog Page</Text>
            <Button onClick={gotoIndex}>我要去Index页面</Button>
        </View>
    )
}
export default Blog

接收传递参数并显示在页面上

现在参数已经可以传递了,那如何在Index.jsx进行接收那,其实也非常简单。只要使用this.$router.params就可以进行接收。

当然我们要接收参数,可以在useEffect()中进行,

useEffect(()=>{
setBlogTitle(this.$router.params.blogTitle)
},[])

为了你更好的学习,这里给出全部代码:

import Taro, {  useState ,useEffect} from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import Child from './child.jsx'
import './index.less'

function Index(props){
  const [userName ,setUserName] = useState('Hello World!!!!')
  const [blogTitle,setBlogTitle] = useState('')
  useEffect(()=>{
    setBlogTitle(this.$router.params.blogTitle)
  },[])
  return ( 
    <View>
        <Text>{userName}</Text>
        <Child userName={userName}></Child>
        <View>{blogTitle}</View>
    </View>
  )

}

export default Index

多参数的传递和接收

我们再来看看如何传递多个参数和多个参数的接收,传递的时候只要用&进行链接就可以了,比如下面这样。

Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})

这里为了你方便学习,给出blog.jsx全部代码:

import Taro ,{useState}from '@tarojs/taro'
import {View , Text ,Button} from '@tarojs/components'
function Blog(){
introduce
    const  [blogTitle,setBlogTitle]=useState('JSPangBlog')
    const  [introduce,setIntroduce]=useState('111111')

    const gotoIndex=()=>{
        Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})
    }
    return (
        <View>
            <Text>Blog Page</Text>
            <Button onClick={gotoIndex}>我要去Index页面</Button>
        </View>
    )
}
export default Blog

接收参数跟单参数接收方法一样,不作过多介绍,直接给出代码。

import Taro, {  useState ,useEffect} from '@tarojs/taro'
import { View, Text } from '@tarojs/components'
import Child from './child.jsx'
import './index.less'

function Index(props){
  const [userName ,setUserName] = useState('Hello World!!!!')
  const [blogTitle,setBlogTitle] = useState('')
  const  [introduce,setIntroduce]=useState('')
  useEffect(()=>{
    setBlogTitle(this.$router.params.blogTitle)
    setIntroduce(this.$router.params.introduce)
  },[])
  return ( 
    <View>
        <Text>{userName}</Text>
        <Child userName={userName}></Child>
        <View>{blogTitle}</View>
        <View>{introduce}</View>
    </View>
  )

}

export default Index

好的,这节课就到这里了,主要讲解了通过路由传递参数和用React hooks 如何接收参数。

P09:Taro 静态资源引入方式

Taro的静态资源引入方式和以前的使用Webpack的方式稍有不同,这节课我们就以引入JavaScript文件和Image图片文件为例,讲解一下Taro中引入静态资源的正确方法。

JavaScript资源的引入方法

JavaScript资源的引入其实和原来差不多,比如现在我们定义了一个方法叫做XieDaJiao(谢大脚),然后再定义一个方法叫liuying(刘英)。

/src目录下,新建一个/tools文件夹,然后在文件夹下边建立一个index.js文件,输入下面的代码。

export function xiedajiao(){
    console.log('我是谢大脚')
}

export function liuying(){
    console.log('我是刘英')
}

这时候我们如果想在blog.jsx下使用这两个方法,可能你会错误的使用.

import tools from `../../tools`

正确的引入方式应该是:

import {xiedajiao,liuying} from '../../tools'

使用方法如下:

useEffect(()=>{
    xiedajiao()
    liuying()
},[])

图片的引入方式

会了JS的引入和使用,再来看一下最长使用的图片如何引入。这里是不可以直接使用的。

我们通常的做法

<Image src="../../static/newbbd0001.jpg" width="100px" height="100px" />

这种方式是没办法引入成功的,因为我们的程序最终是要通过Taro编译器进行编译的,编译后的文件目录会进行改变,你所引用的图片就会失效。

正确的引入方式是先用import进行引入,然后在使用src属性,这里给出blog.jsx的全部代码。

import Taro ,{useState ,useEffect}from '@tarojs/taro'
import {View , Text ,Button,Image} from '@tarojs/components'
import {xiedajiao,liuying} from '../../tools'
import newbbd  from '../../static/newbbd0001.jpg'

function Blog(){

    useEffect(()=>{
        xiedajiao()
        liuying()
    },[])



    const  [blogTitle,setBlogTitle]=useState('JSPangBlog')
    const  [introduce,setIntroduce]=useState('111111')
    const gotoIndex=()=>{
        Taro.navigateTo({url:'/pages/index/index?blogTitle='+blogTitle+'&introduce='+introduce})
    }
    return (
        <View>
            <Text>Blog Page111</Text>
            <Button onClick={gotoIndex}>我要去Index页面</Button>
            <View>
                <Image src={newbbd} width="100px" height="100px" />
            </View>
        </View>
    )
}
export default Blog

如果你觉的这样比较麻烦,你也可以直接使用require在Image组件中直接使用,代码如下:

<Image src={require('../../static/newbbd0001.jpg')} width="100px" height="100px" />

这就是这节课所学的内容,希望小伙伴能练习一下。

P10:Taro中JSX的列表渲染

列表的渲染在工作是每天要作的工作,所以这节课来学一下Taro中列表的渲染,比如我们要作一个象牙山美女列表。

构建美女数组对象

我们先使用JS的基本语法,构建一个象牙山的美女列表,这里有谢大脚、刘英、王小蒙、香秀。

打开blog.jsx文件然后再blog方法里编写代码:

代码如下:

const girls = [
    {id:1,name:'谢大脚'},
    {id:2,name:'刘英'},
    {id:3,name:'王小蒙'},
    {id:4,name:'香秀'}
]

在JSX中循环列表

有礼列表数组后,我们就可以在JSX中进行循环了,循环也是非常简单的,只要使用ES6的map循环就可以了。代码如下:

{ girls.map((item,index)=>{
    return (
        <View>{item.name}</View>
    )
}) }

如何在JSX中使用逻辑判断

现在美女都准备好了,那要开始选男主角了,男主角有玉田刘能,如果是1,就是玉田,如果不是就是刘能,并且不能在JS代码中判断,要在JSX中进行判断。

错误示范:

<view>
    {
        if(zhujueNum===1){
            return ('玉田')
        }else{
            return('刘能')
        }
    }
</view>

如果碰到这样的情况,我们可以使用三元运算符,代码如下:

<view>
    男主角是:{zhujueNum==1?'玉田':'刘能'}
</view>

当然你也可以使用这种形式,利用短路符来判断,代码如下:

<view>
    男主角是:{zhujueNum==1 && '玉田' || '刘能'}
</view>

这节课的学习就先到这里,下节课我们继续学习。

P11:Taro请求远程数据

上节课学会了基本列表的遍历渲染,但这个列表是手工编写的,这显然不符合工作中的开发需求,工作中都是前后端分离,数据是由后端提供给前端的,所以去后端的接口请求数据变成了一个基础操作。这节课我们就学习一下使用Taro.request获取远程接口数据,并渲染到页面上的操作。

使用Taro.request获取远程数据

直接进入上节课的blog.jsx文件,然后编写一个testHandler方法,方法中使用Taro.request后去远端数据,这里远端数据使用的是我博客接口中的数据,你当然你可以获取任何你知道的接口中的数据。

const testHandler= ()=>{
    Taro.request({
        url:'https://apiblog.aliyun01.com/default/getArticleList'
    }).then(res=>{
        console.log(res.data)
    })
}

然后在JSX中编写一个<Button>按钮,加上onClick事件,代码如下:

<Button onClick={testHandler}>我要去Index页面</Button>

这时候点击按钮时就应该可以在控制台输出接口返回的数据。

遍历数据

这次我们在得到数据后遍历到JSX中,先用useState声明一个articleList,代码如下:

const  [articleList,setArticleList] = useState([])

然后在return中使用map进行遍历,代码如下:

{
    articleList.map((item,index)=>{
        return (<View key={index}>- {item.title} </View>)
    })
}

这时候就可以到服务器看一下结果了。当点击按钮后,就会去接口请求首页数据,然后得到数据后渲染到页面上。


简介

        Nextcloud是一款开源免费的私有云存储网盘项目,可以让你快速便捷地搭建一套属于自己或团队的云同步网盘,从而实现跨平台跨设备文件同步、共享、版本控制、团队协作等功能。Nextcloud是一个网盘式文件管理系统,多用户权限管理,多客户端,使用简单。


        Nextcloud是owncloud的一个分支,由原创始人团队维护,是在owncloud被别的公司收购后,由创始人团队创立的新分支。就像 mysql和mariadb。


        Nextcloud完全开源,功能强大,能够自由更改主题,无限制增加用户,有一个完善的应用中心(在线office办公,pdf在线浏览,图片缩略图浏览等功能)


官网地址:Nextcloud - Open source content collaboration platform


安装

        Nextcloud可使用Docker或者下载安装包手动进行安装。但使用Docker安装感觉是最方便的,这里假设你的Linux中已安装好Docker环境了(如果没有安装Docker,可参考我的另一篇文章Docker基础教程-CSDN博客):


-如果要下载安装包手动进行安装,则安装包下载地址如下:

https://download.nextcloud.com/server/releases/


本文安装则采用较为方便的Docker进行安装。


注意:安装Nextcloud需要MySQL数据库,如果没有,需要提前进行安装。


使用Docker安装Nextcloud步骤如下:


1.安装MySQL并创建Nextcloud所需数据库

MySQL安装和配置过程略。


要求安装Nextcloud的服务器能访问到这台MySQL服务器即可。


2.创建一个用于存储Nextcloud数据的目录:

在Linux终端中执行以下语句即可:


mkdir -p /srv/nextcloud/data


3.拉取官方镜像并运行容器

docker run -d \

    --name nextcloud \

    -v /srv/nextcloud/data:/var/www/html \

    -e MYSQL_HOST=192.168.88.161:3306 \

    -e MYSQL_DATABASE=nextcloud \

    -e MYSQL_USER=root \

    -e MYSQL_PASSWORD=8888 \

    -p 8080:80 \

    nextcloud


注意:


MYSQL_HOST:为MySQL的域名/IP+端口;


MYSQL_DATABASE:为Nextcloud要用到的数据库名称;


MYSQL_USER、MYSQL_PASSWORD:为MySQL用户名和密码。




PS:以上命令仅需要在第一次安装时使用,安装好后,再次启动时则可直接通过命令启动已安装好的nextcloud容器即可:docker start nextcloud


4.访问http://localhost:8080 进行在线安装



这里可自己输入管理员的用户密码和密码,然后点击安装按钮。






这里可根据需要选择所需安装的应用,我就直接选择“跳过”了。




出现这个页面说明安装完成,可以使用Nextcloud了。


注意事项

        安装完成后,如果访问Nextcloud出现“通过不被信任的域名访问”提示:




则可通过修改config.php配置来解决:


-进入nextcloud容器:

docker exec -it nextcloud /bin/bash


-安装vim命令:

apt-get update

apt-get install vim


-修改config.php配置文件(可信任域名配置):

cd html/config

vim config.php


找到trusted_domains部分,修改如下即可:

'trusted_domains' => array(

        0 => '127.0.0.1',

        1 => preg_match('/cli/i',php_sapi_name())?'127.0.0.1':$_SERVER['SERVER_NAME'],

),


服务启动与停止

-启动:

docker start nextcloud


-停止:

docker stop nextcloud


使用

-访问地址:

http://localhost:8080


刚开始只有一个管理员账户,该管理员的用户名密码为安装时手动输入的。


首页



语言设置





文件列表



可添加需要上传的文件、创建文件夹或者创建可在线编辑和查看的Markdown文件。


用户管理





可以新建用户或用户分组。




配额表示用户能上传的网盘空间大小:






文件/文件夹分享











然后点击“保存分享”按钮保存即可:






整合ONLYOFFICE实现Office文档在线浏览与编辑

        Nextcloud默认不支持Office文档在线编辑,只支持txt、markdown文档在线编辑,但可通过安装ONLYOFFICE应用来实现在线编辑功能,具体步骤如下:


1.安装ONLYOFFICE工具

这里采用Docker进行安装比较方便,执行以下命令进行安装和启动容器:


【这里最好用较新版本的Docker来安装,因为之前采用18.x版本安装报错:Error response from daemon: missing signature key】


docker run -i -t -d -p 8088:80 --restart=always -e JWT_SECRET=my_jwt_secret onlyoffice/documentserver


注意:这里的8088为ONLYOFFICE工具访问的端口号,my_jwt_secret为自定义的JWT SECRET,这俩配置后面在Nextcloud中配置会用到。


-验证安装是否完成:


浏览器访问ONLYOFFICE的ip+端口号,出现以下页面即可:




2.Nextcloud整合ONLYOFFICE

用管理员登录Nextcloud,右上角选择“应用”:




然后应用列表右上角点放大镜按钮进行搜索,搜索时输入ONLYOFFICE




然后点击ONLYOFFICE右侧的“下载并启用”按钮即可。








此时“管理设置”中左侧会出现ONLYOFFICE配置菜单:






此时就可以在Nextcloud文件页面中创建或者上传Word或PPT等文件了:




上传或创建文档后,点击文档名称即可实现在线浏览和编辑了:








3.Nextcloud中进行ONLYOFFICE设置

        在ONLYOFFICE中可以进行运行打开的文件格式等相关设置的,只不过并不是所有能打开的格式都能进行在线编辑。


        比如docx、xlsx、pptx、txt是可以打开并编辑的,但doc、xls、ppt、pdf等文件就不能在线编辑只能浏览了。




4.ONLYOFFICE中添加中文字体

如发现有些Office文档中用到的字体显示有问题,则可能是该字体ONLYOFFICE中没有,添加字体可参考这篇文章:

————————————————


                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

                        

原文链接:https://blog.csdn.net/yijian0645/article/details/137109351


当你写项目的时候,如何快速的完成一个项目的搭建,这个时候就需要借助到一些模板了,前端开发的一个好处就是,各类UI模板都是相当的齐全的,直接拿来用就可以了,脱离了一行又一行垒代码的繁琐的工作,以下的开源后台管理系统模板是我在逛GitHub的时候看到的,排名先后是按照2020/5月份GitHub上面的star进行排名的。

1:vue-admin-better

推荐指数:star:14k Github 地址:https://github.com/chuzhixin/vue-admin-better Demo体验:https://vue-admin-beautiful.com/admin-plus/

一个基于 vue2.0 和 Eelement 的控制面板 UI 框架,这是使用vue技术栈开发的前端程序员的首选管理系统模板,模板以及非常的成熟了,并且有相关的社区和维护人员,开发时候遇到问题也不要慌。

2:AdminLTE

推荐指数:star:34.7k Github 地址:https://github.com/almasaeed2010/AdminLTEDemo体验:https://adminlte.io/themes/AdminLTE/index2.html

非常流行的基于 Bootstrap 3.x 的免费的后台 UI 框架,这是一个非常老牌的后台管理系统模板,每个页面都是单独的html网页,适合前端入门新手来做项目。

3:ant-design-pro

推荐指数:star:25.2k Github 地址:https://github.com/ant-design/ant-design-proDemo体验:https://preview.pro.ant.design/

这个就不多说了,选择react技术栈的童鞋们必然离不开这个优秀开箱即用的中台前端/设计解决方案,文档齐全,组件丰富,一键生成模板,更支持开启复制黏贴模式哦。

4:layui

推荐指数:star:21.7k Github 地址:https://github.com/sentsin/layui/Demo体验:https://www.layui.com/admin/pro/

经典模块化前端框架,由职业前端倾情打造,面向全层次的前后端开发者,低门槛开箱即用的前端 UI 解决方案。根据大家的建议,把忘记的这个框架也补充,这个框架有收费和免费的版本,在去年的时候进入过开源中国前端框架最受欢迎的框架前三名,实至名归,确实很好用,支持单页面,PC端和响应式移动端。

5:ng2-admin

推荐指数:star:20.6k Github 地址:https://github.com/akveo/ngx-adminDemo体验:https://www.akveo.com/ngx-admin/pages/dashboard

这是基于 Angular 2, Bootstrap 4 和 Webpack 的后台管理面板框架,要说前面已经有了react和vue技术栈的模板,那怎么能少的了ng的?虽然在国外用的比较多,国内较少使用,但丝毫不影响ng作为前端框架三大巨头之一的地位呀。

6:Gentelella

推荐指数:star:19.1k Github 地址:https://github.com/puikinsh/gentelellaDemo体验:https://colorlib.com/polygon/gentelella/index.html

Gentelella 是一个可免费使用的 Bootstrap 管理界面模版,使用群体比较广泛。这个模版使用默认的 Bootstrap 3 的样式,还有一系列功能强大的 jQuery 插件和工具,可快速创建管理界面模版或者后台的 Dashboard。

7:iview-admin

推荐指数:star:14.7k Github 地址:https://github.com/iview/iview-adminDemo体验:https://admin.iviewui.com/home

iView admin 是基于 iView 的 Vue 2.0 控制面板。搭配使用 iView UI 组件库形成的一套后台集成解决方案 。

8:blur-admin

推荐指数:star:10.9k

Github 地址:https://github.com/akveo/blur-adminDemo体验:https://www.akveo.com/blur-admin-mint/#/dashboard

BlurAdmin 是一款使用 AngularJs + Bootstrap实现的单页管理端模版,视觉冲击极强的管理后台,各种动画效果。

9:vue-manage-system

推荐指数:star:10.6k 地址:https://github.com/lin-xin/vue-manage-systemDemo体验:https://lin-xin.gitee.io/example/work/#/dashboard

vue-manage-system,一个基于 Vue.js 和 element-ui 的后台管理系统模板,挺喜欢这个界面的UI,简约清晰不累赘,多功能的后台框架模板,适用于绝大部分的后台管理系统开发。

10:material-dashboard

推荐指数:star:9.1k Github 地址:https://github.com/creativetimofficial/material-dashboardDemo体验:https://demos.creative-tim.com/material-dashboard

基于 Bootstrap 4 和 Material 风格的控制面板。Material Dashboard 是一个开源的 Material Bootstrap Admin,其设计灵感来自谷歌的 Material Design 。

11:d2-admin

推荐指数:star:8.7k github地址:https://github.com/d2-projects/d2-admin

D2Admin 是一个完全 开源免费 的企业中后台产品前端集成方案,基于 vue.js 和 ElementUI 的管理系统前端解决方案 ,小于 60kb 的本地首屏 js 加载,已经做好大部分项目前期准备工作

12:vuestic-admin

推荐指数:star:7.1k

GitHub:https://github.com/epicmaxco/vuestic-adminDemo体验:https://vuestic.epicmax.co/admin/dashboard

vuestic-admin管理台仪表盘是一个响应式的仪表盘模板,采用Bootstrap 4和Vue.js构建。这个精美的管理台模板提供了自定义元素组件,如地图,聊天,个人资料卡,图标,进度条等,以及用于登录和注册的预建页面。

最后编辑于 :2022.09.21 13:28:50

©著作权归作者所有,转载或内容合作请联系作者



作者:8af0764fec6c
链接:https://www.jianshu.com/p/4262d0405eea
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


1  引言


先思考一个问题:在kubernetes的网络环境下,如何做服务间的访问控制 和 提高访问的安全性?


你可能会想到 进行HTTPS加密、使用NetworkPolicy、使用RBAC控制权限...等等




总结起来要实现以下能力:


数据加密:确保传输中的数据经过加密,难以被截获破解


身份认证:确定客户端和服务端都是真实且经过验证的


权限控制:默认拒绝掉来历不明的请求,开放最小粒度的访问权限给必要的访问者




而原生kubernetes访问控制能力存在着缺陷: 


没有对应用层协议的分析处理能力。 


ServiceAccount 可以做到把服务和身份关联(每个deployment创建一个ServiceAccount),但一个sa token 只能在一个集群中标记负载身份,不能支持 Kubernetes 环境和虚拟机的异构场景、多kubernetes集群联合使用场景。




对此问题istio提出了解决方案:


为每个pod的sidecar自动下发x509证书,支持pod间使用mtls加密通信。


使用了SPIFFE (Secure Production Identity Framework For Everyone)开源的身份认证标准,标识工作负载(身份)。SPIFFE ID 是一个统一资源标识符, istio中 SPIFFE ID 格式为:spiffe://<trust_domain>/ns/<namespace>/sa/<service_ account> 。在kubernetes平台上,istio巧妙的借助kubernetes工作负载的Service Account信息,在istio生成工作负载证书时将  SPIFFE ID 字符串注入 X509 证书的 subjectAltName扩展中,随着 X.509 证书下发到数据面。通信双方通过这个字符串即可获得对方身份,实现了istio中的身份标识。(若工作负载没有配置服务账户的情况下使用命名空间的默认ServiceAccount)。其中“trust domain”参数通过 Istiod 环境变量 TRUST_DOMAIN 注入,用于在多kubernetes集群环境。


通过sidecar代理 拦截处理访问流量,进行权限管控。




2  istio访问管理架构


Istio 为微服务提供了无侵入,可插拔的底层安全基础设施。在istio中服务间端到端的通信安全通过服务网格中的代理实现,在整个请求过程中客户端和服务端应用程序是不感知的。


本文将从istio 证书管理、身份认证、访问鉴权策略  三个方面来介绍 Istio 的安全机制。


istio访问管理架构



3  istio证书管理


Istio通过向数据面代理颁发X.509证书来为工作负载提供身份标识。


证书管理和轮换由与Envoy代理在同一容器中运行的pilot-agent 进程代理完成。


Istio 通过以下流程管理证书:


istio证书下发管理流程

istiod 提供 gRPC 服务以接受证书签名请求(CSR)。


pilot-agent 在启动时创建私钥和 CSR,然后将 CSR 及其凭据发送到 istiod 进行签名。


istiod CA 验证 CSR 中携带的凭据,成功验证后签署 CSR 以生成证书,证书中包含对应的SPIFFEID。


当工作负载启动时,Envoy 通过 Secret 发现服务(SDS)API 向同容器内的 pilot-agent  发送证书和密钥请求。


pilot-agent 通过 Envoy SDS API 将从 istiod 收到的证书和密钥发送给 Envoy。


pilot-agent  监控工作负载证书的过期时间。上述过程会定期重复进行证书和密钥轮换。




4  istio身份认证


认证(Authentication)一般是指验证当前用户的身份,对于微服务而言则是验证请求对端的身份。在安全的理论模型中,身份是任何安全功能的基础条件。


Istio 提供两种类型的身份认证:


对等认证:基于mtls来实现的服务到服务的认证。(即通过x509证书获取对端身份),一般用于kubernetes集群内的服务之间的认证。


请求认证:基于jwt(JSON Web Token)来实现的请求级别的认证,它常被用于终端用户身份认证。


当前istio技术落地时大多数使用对等认证。istio请求认证的使用较少,大多数情况下jwt解析是在应用程序中进行,而不是istio代理解析,因为应用程序需要获取终端用户id来对数据库操作。


本文不介绍请求认证。




4.1 对等认证的概念和原理


TLS 协议是TCP/IP协议组的一部分,用于在两台主机间建立一个加密的双向网络通道。TLS协议一般会和其他协议结合使用来提供安全的应用层,例如我们熟知的HTTPS、FTPS等。




mTLS是TLS协议的扩展,旨在验证双方(Web客户端和Web服务器)的身份并保护他们在网络中的通信安全。


TLS单向认证与mTLS双向认证的区别如下:


TLS单向认证:只有客户端验证服务端的合法身份,服务端不关心客户端身份。服务端维护证书。web应用大多数是单向的TLS认证。


mTLS双向认证:客户端和服务端都要验证对端身份。客户端和服务端都必须持有标识身份的证书。常用于服务到服务的访问。


Istio对等认证基于mTLS,实现以下能力:


真实性:确保双方都是真实且经过验证的


保密性:确保传输中的数据安全


完整性:确保发送数据的正确性




4.2 对等认证的架构


istio的对等认证(mtls)是由网格代理完成的,在整个请求过程中客户端和服务端应用程序是不感知的。


mTLS认证架构和认证过程



4.3 对等认证生效范围


PeerAuthentication 的 metadata.namespace 和 spec.selector 字段 决定对等认证生效范围。


全网格范围:metadata.namespace 为istio-system 且 selector 字段为空。


命名空间范围:metadata.namespace  非istio-system ,selector 字段为空。


特定工作负载:metadata.namespace  非istio-system , selector 字段非空。


只能有一个网格范围的对等认证策略, 每个命名空间也只能有一个命名空间范围的对等认证策略。




一个工作负载只能生效一个认证规则,Istio 按照以下顺序为每个工作负载应用匹配的策略:


特定工作负载的规则 > 命名空间范围规则 > 全网格范围规则




4.4 对等认证生效位置


认证策略是对服务收到的请求生效的,即服务端生效。




4.5 对等认证配置


对等认证示例如下:


apiVersion: security.istio.io/v1beta1

kind: PeerAuthentication

metadata:

  name: "httpbin"

  namespace: "bar"                 ## 只可生效于"bar"命名空间下的工作负载

spec:

  selector:                        ## 通过label匹配pod

    matchLabels:

      app: httpbin # 匹配 httpbin 应用的标签

  mtls:

    mode: STRICT                   ## 安全模式,STRICT代表只接受mtls请求

其中spec.mtls.mode有3种可选值,对应3种身份认证模式:


PERMISSIVE:同时支持明文传输和mtls密文传输。不管是网格内还是网格外,服务间都可通信。


STRICT:此服务只接收双向 TLS 流量。


DISABLE:关闭MutualTLS。从安全的角度而言,官方并不建议在没有其他安全措施的情况下使用该模式。


缺省配置时:将从父级配置中继承(命名空间或网格层面),如果父级没有进行相应的配置,则使用PERMISSIVE模式。




4.4 对等认证部署验证


我们先准备下面的sleep.yaml 和 httpbin.yaml


## sleep.yaml文件

apiVersion: v1

kind: ServiceAccount

metadata:

  name: sleep

---

apiVersion: v1

kind: Service

metadata:

  name: sleep

  labels:

    app: sleep

    service: sleep

spec:

  ports:

  - port: 80

    name: http

  selector:

    app: sleep

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: sleep

spec:

  replicas: 1

  selector:

    matchLabels:

      app: sleep

  template:

    metadata:

      labels:

        app: sleep

    spec:

      terminationGracePeriodSeconds: 0

      serviceAccountName: sleep

      containers:

      - name: sleep

        image: curlimages/curl

        command: ["/bin/sleep", "infinity"]

        imagePullPolicy: IfNotPresent

        volumeMounts:

        - mountPath: /etc/sleep/tls

          name: secret-volume

      volumes:

      - name: secret-volume

        secret:

          secretName: sleep-secret

          optional: true


## httpbin.yaml文件

apiVersion: v1

kind: ServiceAccount

metadata:

  name: httpbin

---

apiVersion: v1

kind: Service

metadata:

  name: httpbin

  labels:

    app: httpbin

    service: httpbin

spec:

  ports:

  - name: http-http

    port: 80

    targetPort: 80

  selector:

    app: httpbin

---

apiVersion: apps/v1

kind: Deployment

metadata:

  name: httpbin

spec:

  replicas: 1

  selector:

    matchLabels:

      app: httpbin

      version: v1

  template:

    metadata:

      labels:

        app: httpbin

        version: v1

    spec:

      serviceAccountName: httpbin

      containers:

      - image: docker.io/kong/httpbin

        imagePullPolicy: IfNotPresent

        name: httpbin

        ports:

        - containerPort: 80

执行以下操作


## 创建三个命名空间

kubectl create ns foo

kubectl create ns bar

kubectl create ns legacy


## 对其中两个命名空间开启istio自动注入,另一个不开启istio自动注入

kubectl label namespace foo istio-injection=enabled

kubectl label namespace bar istio-injection=enabled


## 应用上面的yaml文件

kubectl apply -f  httpbin.yaml -n foo

kubectl apply -f sleep.yaml -n foo

kubectl apply -f httpbin.yaml -n bar

kubectl apply -f sleep.yaml -n bar

kubectl apply -f sleep.yaml -n legacy

实验先从默认的PERMISSIVE模式下开始,PERMISSIVE模式下服务网格对服务的流量都是放通的。遍历不同空间的sleep工作负载访问httpbin工作负载,可以看到是全通的。


服务间访问测试

生效下面的对等认证规则


## pa.yaml文件

apiVersion: security.istio.io/v1beta1

kind: PeerAuthentication

metadata:

  name: "example-peer-policy"

  namespace: "foo"

spec:

  selector:

    matchLabels:

      app: reviews

  mtls:

    mode: STRICT

执行如下命令进行测试:


for from in "foo" "bar" "legacy"; do for to in "foo" "bar"; do kubectl exec "$(kubectl get pod -l app=sleep -n ${from} -o jsonpath={.items..metadata.name})" -c sleep -n ${from} -- curl http://httpbin.${to}:80/ip -s -o /dev/null -w "sleep.${from} to httpbin.${to}: %{http_code}\n"; done; done

应用PeerAuthentication严格模式后,istio代理会自动把请求流量升级为mtls模式,所以foo、bar命名空间的请求正常。而legacy命名空间没有注入sidecar,没有代理为其实现mtls,请求失败。


服务间访问测试



4.5 使用需知


当服务开启严格模式的对等认证,只能用svc来访问pod,无法用podip去请求此工作负载。


bug详情连接  https://github.com/istio/istio/issues/37431#issuecomment-1054450785




5  istio服务访问授权


5.1 访问授权概念和原理


在安装完istio后,默认没有服务访问策略,这时允许全部的服务间访问。


istio提供了AUthorizationPolicy CRD来设置服务访问授权。例如:哪个服务、身份、源IP 可以访问某个服务的某个端口、接口。


由于istio作用的对象是服务,因此授权功能主要适用于四至七层(相比较而言,传统的防火主用于二至四层),例如,gRPC、HTTP、HTTPS、HTTP2,以及TCP等。上述协议Istio都可以提供原生支持。


就像istio的其他流量控制功能一样,Istio中授权功能的实现也是非侵入式的,通过sidecar代理完成。




5.2 访问授权架构


服务网格数据面是真正的授权策略执行角色。规则的配置、下发、执行架构如下:


运维人员将AuthorizationPolicy应用到k8s中,存储在etcd


istiod从 k8s中获取授权配置策略,下发到数据面


envoy在拦截到请求后根据授权策略判断是否允许访问。


istio访问授权架构



5.3 访问授权配置


AuthorizationPolicy 包括三个主要字段 selector、action、rules


selector 字段指定策略的目标


rules 指定何时触发动作


rules 下的 from 字段描述请求来源属性。可以不设置,表示匹配所有来源的请求。 from数组元素间是或的关系,form元素内部各个条件是与的关系。


rules 下的 to 字段述对目标服务的操作属性,如:port methods urlpath。若不配置to条件,则表示匹配所有操作。


rules 下的 when 字段指定应用规则所需的条件


action 字段指定最后的操作,支持 ALLOW、DENY 和 CUSTOM




以下示例授权策略拒绝来源非 foo 命名空间的对 httpbin的 "GET" 请求。我们生效配置,然后再次执行循环请求脚本。


apiVersion: security.istio.io/v1

kind: AuthorizationPolicy

metadata:

  name: httpbin

  namespace: foo

spec:

  selector:                               ## 通过标签指定生效的服务

    matchLabels:

      app: httpbin

      version: v1

  action: DENY                            ## 拒绝请求

  rules:                                  ## 匹配请求的条件

    - from:                               ## 不是来自foo命名空间的请求

        - source:

            notNamespaces: ["foo"]

      to:                                 ## Get方法的请求

        - operation:

            methods: ["GET"]

测试结果如下图:


访问授权测试



5.4 访问授权生效顺序


拒绝策略优先于允许策略。如果请求同时匹配上允许策略和拒绝策略,请求将被拒绝。


访问授权判断顺序



5.5 "访问授权"对"身份认证"的依赖


Istio对等认证使用双向 TLS 将某些信息从客户端安全地传递到服务器,这让服务端可以知道请求者的真实身份。 在使用授权策略中的以下任何字段之前,必须先启用双向 TLS:


source 部分下的 principals 和 notPrincipals 字段


source 部分下的 namespaces 和 notNamespaces 字段


source.principal 自定义条件


source.namespace 自定义条件




6  实战经验


6.1 使用访问管控时,建议开启envoy代理日志,便于分析异常问题


kubectl -n istio-system edit configmap istio

编辑yaml文件的对应配置:


data:

  mesh: |-

    accessLogEncoding: JSON

    accessLogFile: /dev/stdout



6.2 更新认证策略最佳实践


当更改认证策略时,Istio 无法保证所有工作负载都同时收到新政策。 以下建议有助于避免在更新认证策略时造成干扰:


将对等认证策略的模式从 DISABLE 更改为 STRICT 时, 请使用 PERMISSIVE 模式来过渡,反之亦然。当所有工作负载成功切换到所需模式时, 您可以将策略应用于最终模式。您可以使用 Istio 遥测技术来验证工作负载已成功切换。


将请求认证策略从一个 JWT 迁移到另一个 JWT 时, 将新 JWT 的规则添加到该策略中,而不删除旧规则。这样, 工作负载将接受两种类型的 JWT,当所有流量都切换到新的 JWT 时, 您可以删除旧规则。但是,每个 JWT 必须使用不同的位置。




6.3 禁止访问公网


有时候为了安全我们不允许kubernetes pod 随意访问公网,可以设置REGISTRY_ONLY。


在传统环境这个需求是由出口防火墙实现,但是在云环境上一般使用snat对整个子网进行出访代理,可以在istio中进行限制。


## 修改访问模式为REGISTRY_ONLY

kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: ALLOW_ANY/mode: REGISTRY_ONLY/g' | kubectl replace -n istio-system -f -


## 切换回Allow-all

kubectl get configmap istio -n istio-system -o yaml | sed 's/mode: REGISTRY_ONLY/mode: ALLOW_ANY/g' | kubectl replace -n istio-system -f

在完成了修改之后,所有访问外部服务的请求都会返回 502 错误。为了正常访问,需要对外部服务进行注册,注册可通过创建服务条目资源来完成。下面的代码创建了第三方支付服务所对应的 ServiceEntry 资源。


apiVersion: networking.istio.io/v1beta1

kind: ServiceEntry

metadata:

  name: baidu-ip

spec:

  hosts:

  - www.baidu.com

  addresses:

  - 36.152.44.96

  location: MESH_EXTERNAL           ## 声明了该服务位于服务网格之外

  ports:

  - number: 80                      ## 定义了允许访问的端口

    name: baidu-http

    protocol: HTTP

  resolution: NONE                  ## 属性表示服务代理如何解析服务的 IP 地址



6.4 istio入口网关黑名单


您使用 X-Forwarded-For HTTP 标头或代理协议来确定原始客户端 IP 地址,那么可以在 AuthorizationPolicy 中使用 remoteIpBlocks 设置黑白名单。


下面yaml配置禁止来自 "1.2.3.4" 和 “5.6.7.0/24” 网段的请求进入istio


apiVersion: security.istio.io/v1beta1

kind: AuthorizationPolicy

metadata:

  name: ingress-policy

  namespace: istio-system

spec:

  selector:

    matchLabels:

      app: istio-ingressgateway

  action: DENY

  rules:

  - from:

    - source:

        remoteIpBlocks: ["1.2.3.4", "5.6.7.0/24"]

 作者:BeijingToTokyo https://www.bilibili.com/read/cv29652221/ 出处:bilibili