整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          運維神器!一個可以通過Web訪問Linux終端的工具

          運維神器!一個可以通過Web訪問Linux終端的工具

          開源精選》是我們分享Github、Gitee等開源社區中優質項目的欄目,包括技術、學習、實用與各種有趣的內容。本期推薦的是一個通過Web訪問設備終端的工具——rtty。

          rtty由客戶端和服務端組成。客戶端采用純C實現,服務端采用GO語言實現,前端界面采用vue實現。使用rtty可以在任何地方通過Web訪問您的設備的終端,通過設備ID來區分您的不同的設備。rtty非常適合遠程維護Linux設備。


          特性

          • 客戶端 C 語言實現,非常小,適合嵌入式 Linux

          不支持 SSL:rtty(32K) + libev(56K)

          支持的 SSL:+ libmbedtls(88K) + libmbedcrypto(241K) + libmbedx509(48k)

          • 遠程批量執行命令
          • 支持SSL:openssl, mbedtls, CyaSSl(wolfssl)
          • SSL 雙向認證(mTLS)
          • 非常方便地上傳和下載文件
          • 根據設備ID訪問不同的設備
          • 支持 HTTP 代理 - 訪問您的設備的 Web
          • 基于Xterm.js的全功能終端
          • 部署簡單,使用方便


          客戶端依賴

          • libev - 高性能的事件循環庫
          • mbedtls(polarssl)CyaSSl(wolfssl)或者openssl - 如果您需要支持SSL

          部署服務端

          1 從Release頁面下載編譯好的二進制文件或者自己編譯

          git clone https://github.com/zhaojh329/rttys
          
          cd ui
          npm install
          npm run build
          cd ..
          
          ./build.sh linux amd64

          2 認證

          • Token

          生成一個 token:

          $ rttys token
          Please set a password:******
          Your token is: 34762d07637276694b938d23f10d7164

          使用 token:

          $rttys -t 34762d07637276694b938d23f10d7164
          • SSL 雙向認證(mTLS)

          您可以在配置文件中指定設備 CA 存儲(有效文件)或在 CLI 中指定設備 CA 存儲(參數 ssl-cacert) 來啟用 mTLS。 存儲中沒有有效 CA 的設備將在 TLS 握手中斷開連接。

          3 運行服務

          移動rttys可執行程序到/usr/local/bin/

          sudo mv rttys /usr/local/bin/

          拷貝配置文件到/etc/rttys/

          sudo mkdir /etc/rttys
          sudo cp rttys.conf /etc/rttys/

          創建一個systemd單元文件: /etc/systemd/system/rttys.service

          [Unit]
          Description=rttys
          After=network.target
          
          [Service]
          ExecStart=/usr/local/bin/rttys run -c /etc/rttys/rttys.conf
          TimeoutStopSec=5s
          
          [Install]
          WantedBy=multi-user.target

          要首次啟動該服務,請執行通常的systemctl操作

          sudo systemctl daemon-reload
          sudo systemctl enable rttys
          sudo systemctl start rttys

          可以通過以下方式停止服務

          sudo systemctl stop rttys

          4 數據庫準備(Sqlite、MySql 或者 Mariadb)

          在數據庫實例上,以root用戶身份登錄到數據庫控制臺

          mysql -u root -p

          創建將由 Rttys 使用的數據庫用戶,通過密碼驗證。本例使用 “rttys” 作為密碼。請為您的實例使用安全密碼

          CREATE USER 'rttys' IDENTIFIED BY 'rttys';

          使用 UTF-8 字符集和排序規則創建數據庫。確保使用 utf8mb4 字符集而不是 utf8,因為前者支持基本多語言平面 之外的所有 Unicode字符(包括emojis)。另外,根據您期望的內容選擇排序規則。如有疑問,請使用 unicode_ci 或general_ci

          CREATE DATABASE rttys CHARACTER SET 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';

          將數據庫上的所有權限授予上面創建的數據庫用戶

          GRANT ALL PRIVILEGES ON rttys.* TO 'rttys';
          FLUSH PRIVILEGES;


          安裝rtty(針對Linux發行版)

          安裝依賴

          sudo apt install -y libev-dev libssl-dev      # Ubuntu, Debian
          sudo pacman -S --noconfirm libev openssl      # ArchLinux
          sudo yum install -y libev-devel openssl-devel # Centos

          克隆rtty代碼

          git clone --recursive https://github.com/zhaojh329/rtty.git

          編譯

          cd rtty && mkdir build && cd build
          cmake .. && make install

          運行rtty

          將下面的參數替換為您自己的參數

          sudo rtty -I 'My-device-ID' -h 'your-server' -p 5912 -a -v -d 'My Device Description'

          如果您的 rttys 配置了一個 token,請加上如下參數(將下面的 token 替換為您自己生成的)

          -t 34762d07637276694b938d23f10d7164

          通過瀏覽器訪問

          使用 Web 瀏覽器訪問您的服務器: http://your-server-host:5913,然后點擊連接按鈕。

          或者直接連接設備,無需 Web 登錄(需要在服務端配置設備白名單)

          http://your-server-host:5913/connect/devid1
          
          http://your-server-host:5913/connect/devid2

          從本地傳輸文件到遠程設備

          rtty -R

          從遠程設備傳輸文件到本地

          rtty -S test.txt


          —END—

          開源協議:MIT

          開源地址:https://github.com/zhaojh329/rtty

          譯自: https://nicolasparada.netlify.com/posts/passwordless-auth-client/

          作者: Nicolás Parada

          譯者: qhwdw

          我們繼續 無密碼驗證 的文章。上一篇文章中,我們用 Go 寫了一個 HTTP 服務,用這個服務來做無密碼驗證 API。今天,我們為它再寫一個 JavaScript 客戶端。

          我們將使用 這里的 這個單頁面應用程序(SPA)來展示使用的技術。如果你還沒有讀過它,請先讀它。

          記住流程:

          • 用戶輸入其 email。
          • 用戶收到一個帶有魔法鏈接的郵件。
          • 用戶點擊該鏈接、
          • 用戶驗證成功。

          對于根 URL(/),我們將根據驗證的狀態分別使用兩個不同的頁面:一個是帶有訪問表單的頁面,或者是已驗證通過的用戶的歡迎頁面。另一個頁面是驗證回調的重定向頁面。

          伺服

          我們將使用相同的 Go 服務器來為客戶端提供服務,因此,在我們前面的 main.go 中添加一些路由:

          router.Handle("GET", "/...", http.FileServer(SPAFileSystem{http.Dir("static")}))

          type SPAFileSystem struct {

          fs http.FileSystem

          }

          func (spa SPAFileSystem) Open(name string) (http.File, error) {

          f, err :=spa.fs.Open(name)

          if err !=nil {

          return spa.fs.Open("index.html")

          }

          return f, nil

          }

          這個伺服文件放在 static 下,配合 static/index.html 作為回調。

          你可以使用你自己的服務器,但是你得在服務器上啟用 CORS 。

          HTML

          我們來看一下那個 static/index.html 文件。

          <!DOCTYPE html>

          <html lang="en">

          <head>

          <meta charset="utf-8">

          <meta name="viewport" content="width=device-width, initial-scale=1.0">

          <title>Passwordless Demo</title>

          <link rel="shortcut icon" href="data:,">

          <script src="/js/main.js" type="module"></script>

          </head>

          <body></body>

          </html>

          單頁面應用程序的所有渲染由 JavaScript 來完成,因此,我們使用了一個空的 body 部分和一個 main.js 文件。

          我們將使用 上篇文章 中的 Router。

          渲染

          現在,我們使用下面的內容來創建一個 static/js/main.js 文件:

          import Router from 'https://unpkg.com/@nicolasparada/router'

          import { isAuthenticated } from './auth.js'

          const router=new Router()

          router.handle('/', guard(view('home')))

          router.handle('/callback', view('callback'))

          router.handle(/^\//, view('not-found'))

          router.install(async resultPromise=> {

          document.body.innerHTML=''

          document.body.appendChild(await resultPromise)

          })

          function view(name) {

          return (...args)=> import(`/js/pages/${name}-page.js`)

          .then(m=> m.default(...args))

          }

          function guard(fn1, fn2=view('welcome')) {

          return (...args)=> isAuthenticated()

          ? fn1(...args)

          : fn2(...args)

          }

          與上篇文章不同的是,我們實現了一個 isAuthenticated() 函數和一個 guard() 函數,使用它去渲染兩種驗證狀態的頁面。因此,當用戶訪問 / 時,它將根據用戶是否通過了驗證來展示主頁或者是歡迎頁面。

          驗證

          現在,我們來編寫 isAuthenticated() 函數。使用下面的內容來創建一個 static/js/auth.js 文件:

          export function getAuthUser() {

          const authUserItem=localStorage.getItem('auth_user')

          const expiresAtItem=localStorage.getItem('expires_at')

          if (authUserItem !==null && expiresAtItem !==null) {

          const expiresAt=new Date(expiresAtItem)

          if (!isNaN(expiresAt.valueOf()) && expiresAt > new Date()) {

          try {

          return JSON.parse(authUserItem)

          } catch (_) { }

          }

          }

          return null

          }

          export function isAuthenticated() {

          return localStorage.getItem('jwt') !==null && getAuthUser() !==null

          }

          當有人登入時,我們將保存 JSON 格式的 web 令牌、它的過期日期,以及在 localStorage 上的當前已驗證用戶。這個模塊就是這個用處。

          • getAuthUser() 用于從 localStorage 獲取已認證的用戶,以確認 JSON 格式的 Web 令牌沒有過期。
          • isAuthenticated() 在前面的函數中用于去檢查它是否沒有返回 null。

          獲取

          在繼續這個頁面之前,我將寫一些與服務器 API 一起使用的 HTTP 工具。

          我們使用以下的內容去創建一個 static/js/http.js 文件:

          import { isAuthenticated } from './auth.js'

          function get(url, headers) {

          return fetch(url, {

          headers: Object.assign(getAuthHeader(), headers),

          }).then(handleResponse)

          }

          function post(url, body, headers) {

          return fetch(url, {

          method: 'POST',

          headers: Object.assign(getAuthHeader(), { 'content-type': 'application/json' }, headers),

          body: JSON.stringify(body),

          }).then(handleResponse)

          }

          function getAuthHeader() {

          return isAuthenticated()

          ? { authorization: `Bearer ${localStorage.getItem('jwt')}` }

          : {}

          }

          export async function handleResponse(res) {

          const body=await res.clone().json().catch(()=> res.text())

          const response={

          statusCode: res.status,

          statusText: res.statusText,

          headers: res.headers,

          body,

          }

          if (!res.ok) {

          const message=typeof body==='object' && body !==null && 'message' in body

          ? body.message

          : typeof body==='string' && body !==''

          ? body

          : res.statusText

          const err=new Error(message)

          throw Object.assign(err, response)

          }

          return response

          }

          export default {

          get,

          post,

          }

          這個模塊導出了 get() 和 post() 函數。它們是 fetch API 的封裝。當用戶是已驗證的,這二個函數注入一個 Authorization: Bearer <token_here> 頭到請求中;這樣服務器就能對我們進行身份驗證。

          歡迎頁

          我們現在來到歡迎頁面。用如下的內容創建一個 static/js/pages/welcome-page.js 文件:

          const template=document.createElement('template')

          template.innerHTML=`

          <h1>Passwordless Demo</h1>

          <h2>Access</h2>

          <form id="access-form">

          <input type="email" placeholder="Email" autofocus required>

          <button type="submit">Send Magic Link</button>

          </form>

          `

          export default function welcomePage() {

          const page=template.content.cloneNode(true)

          page.getElementById('access-form')

          .addEventListener('submit', onAccessFormSubmit)

          return page

          }

          這個頁面使用一個 HTMLTemplateElement 作為視圖。這只是一個輸入用戶 email 的簡單表單。

          為了避免干擾,我將跳過錯誤處理部分,只是將它們輸出到控制臺上。

          現在,我們來寫 onAccessFormSubmit() 函數。

          import http from '../http.js'

          function onAccessFormSubmit(ev) {

          ev.preventDefault()

          const form=ev.currentTarget

          const input=form.querySelector('input')

          const email=input.value

          sendMagicLink(email).catch(err=> {

          console.error(err)

          if (err.statusCode===404 && wantToCreateAccount()) {

          runCreateUserProgram(email)

          }

          })

          }

          function sendMagicLink(email) {

          return http.post('/api/passwordless/start', {

          email,

          redirectUri: location.origin + '/callback',

          }).then(()=> {

          alert('Magic link sent. Go check your email inbox.')

          })

          }

          function wantToCreateAccount() {

          return prompt('No user found. Do you want to create an account?')

          }

          它對 /api/passwordless/start 發起了 POST 請求,請求體中包含 email 和 redirectUri。在本例中它返回 404 Not Found 狀態碼時,我們將創建一個用戶。

          function runCreateUserProgram(email) {

          const username=prompt("Enter username")

          if (username===null) return

          http.post('/api/users', { email, username })

          .then(res=> res.body)

          .then(user=> sendMagicLink(user.email))

          .catch(console.error)

          }

          這個用戶創建程序,首先詢問用戶名,然后使用 email 和用戶名做一個 POST 請求到 /api/users。成功之后,給創建的用戶發送一個魔法鏈接。

          回調頁

          這是訪問表單的全部功能,現在我們來做回調頁面。使用如下的內容來創建一個 static/js/pages/callback-page.js 文件:

          import http from '../http.js'

          const template=document.createElement('template')

          template.innerHTML=`

          <h1>Authenticating you</h1>

          `

          export default function callbackPage() {

          const page=template.content.cloneNode(true)

          const hash=location.hash.substr(1)

          const fragment=new URLSearchParams(hash)

          for (const [k, v] of fragment.entries()) {

          fragment.set(decodeURIComponent(k), decodeURIComponent(v))

          }

          const jwt=fragment.get('jwt')

          const expiresAt=fragment.get('expires_at')

          http.get('/api/auth_user', { authorization: `Bearer ${jwt}` })

          .then(res=> res.body)

          .then(authUser=> {

          localStorage.setItem('jwt', jwt)

          localStorage.setItem('auth_user', JSON.stringify(authUser))

          localStorage.setItem('expires_at', expiresAt)

          location.replace('/')

          })

          .catch(console.error)

          return page

          }

          請記住……當點擊魔法鏈接時,我們會來到 /api/passwordless/verify_redirect,它將把我們重定向到重定向 URI,我們將放在哈希中的 JWT 和過期日期傳遞給 /callback。

          回調頁面解碼 URL 中的哈希,提取這些參數去做一個 GET 請求到 /api/auth_user,用 JWT 保存所有數據到 localStorage 中。最后,重定向到主頁面。

          主頁

          創建如下內容的 static/pages/home-page.js 文件:

          import { getAuthUser } from '../auth.js'

          export default function homePage() {

          const authUser=getAuthUser()

          const template=document.createElement('template')

          template.innerHTML=`

          <h1>Passwordless Demo</h1>

          <p>Welcome back, ${authUser.username}

          點擊“了解更多”可訪問文內鏈接

          ginx 安裝配置

          Nginx("engine x")是一款是由俄羅斯的程序設計師Igor Sysoev所開發高性能的 Web和 反向代理 服務器,也是一個 IMAP/POP3/SMTP 代理服務器。

          在高連接并發的情況下,Nginx是Apache服務器不錯的替代品。


          Nginx 安裝

          系統平臺:CentOS release 6.6 (Final) 64位。

          一、安裝編譯工具及庫文件

          yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel

          二、首先要安裝 PCRE

          PCRE 作用是讓 Nginx 支持 Rewrite 功能。

          1、下載 PCRE 安裝包,下載地址: http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz

          [root@bogon src]# wget http://downloads.sourceforge.net/project/pcre/pcre/8.35/pcre-8.35.tar.gz

          2、解壓安裝包:

          [root@bogon src]# tar zxvf pcre-8.35.tar.gz

          3、進入安裝包目錄

          [root@bogon src]# cd pcre-8.35

          4、編譯安裝

          [root@bogon pcre-8.35]# ./configure[root@bogon pcre-8.35]# make && make install

          5、查看pcre版本

          [root@bogon pcre-8.35]# pcre-config --version

          安裝 Nginx

          1、下載 Nginx,下載地址:http://nginx.org/download/nginx-1.6.2.tar.gz

          [root@bogon src]# wget http://nginx.org/download/nginx-1.6.2.tar.gz

          2、解壓安裝包

          [root@bogon src]# tar zxvf nginx-1.6.2.tar.gz

          3、進入安裝包目錄

          [root@bogon src]# cd nginx-1.6.2

          4、編譯安裝

          [root@bogon nginx-1.6.2]# ./configure --prefix=/usr/local/webserver/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.35[root@bogon nginx-1.6.2]# make[root@bogon nginx-1.6.2]# make install

          5、查看nginx版本

          [root@bogon nginx-1.6.2]# /usr/local/webserver/nginx/sbin/nginx -v

          到此,nginx安裝完成。


          Nginx 配置

          創建 Nginx 運行使用的用戶 www:

          [root@bogon conf]# /usr/sbin/groupadd www [root@bogon conf]# /usr/sbin/useradd -g www www

          配置nginx.conf ,將/usr/local/webserver/nginx/conf/nginx.conf替換為以下內容

          [root@bogon conf]# cat /usr/local/webserver/nginx/conf/nginx.conf
          user www www;worker_processes 2; #設置值和CPU核心數一致error_log /usr/local/webserver/nginx/logs/nginx_error.log crit; #日志位置和日志級別pid /usr/local/webserver/nginx/nginx.pid;#Specifies the value for maximum file descriptors that can be opened by this process.worker_rlimit_nofile 65535;events{ use epoll; worker_connections 65535;}http{ include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for'; #charset gb2312; 
           server_names_hash_bucket_size 128; client_header_buffer_size 32k; large_client_header_buffers 4 32k; client_max_body_size 8m; 
           sendfile on; tcp_nopush on; keepalive_timeout 60; tcp_nodelay on; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 128k; gzip on; 
           gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; 
           #limit_zone crawler $binary_remote_addr 10m; #下面是server虛擬主機的配置 server
           { listen 80;#監聽端口 server_name localhost;#域名 index index.html index.htm index.php; root /usr/local/webserver/nginx/html;#站點目錄 location ~ .*\.(php|php5)?$
           { #fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico)$
           { expires 30d; # access_log off; } location ~ .*\.(js|css)?$
           { expires 15d; # access_log off; } access_log off; }}

          檢查配置文件ngnix.conf的正確性命令:

          [root@bogon conf]# /usr/local/webserver/nginx/sbin/nginx -t


          啟動 Nginx

          Nginx 啟動命令如下:

          [root@bogon conf]# /usr/local/webserver/nginx/sbin/nginx


          訪問站點

          從瀏覽器訪問我們配置的站點ip:


          Nginx 其他命令

          以下包含了 Nginx 常用的幾個命令:

          /usr/local/webserver/nginx/sbin/nginx -s reload # 重新載入配置文件/usr/local/webserver/nginx/sbin/nginx -s reopen # 重啟 Nginx/usr/local/webserver/nginx/sbin/nginx -s stop # 停止 Nginx

          主站蜘蛛池模板: 亚洲欧洲一区二区三区| 无码av中文一区二区三区桃花岛 | 国产一区二区三区电影| 日韩一区在线视频| 免费国产在线精品一区| 中文字幕VA一区二区三区| 日本不卡一区二区三区| 无码乱码av天堂一区二区| 亚洲精品日韩一区二区小说| 国产一区二区三区在线观看影院| 好吊视频一区二区三区| 日韩精品无码一区二区中文字幕| 在线电影一区二区| 中文字幕一区二区三区在线播放| 久久久精品人妻一区二区三区蜜桃| 国产欧美色一区二区三区| 国产美女av在线一区| 亚洲视频一区二区在线观看| 日本一区二区三区在线网| 午夜精品一区二区三区免费视频| 夜夜精品视频一区二区| 美女视频在线一区二区三区| 精品深夜AV无码一区二区老年| 一区二区三区免费电影| 日韩好片一区二区在线看| 视频在线观看一区二区| 精品一区二区三区在线成人| 一区二区三区伦理高清| 亚洲爆乳精品无码一区二区| 一本大道东京热无码一区| 精品人妻无码一区二区三区蜜桃一 | 中文字幕日韩一区| 亚洲免费一区二区| 国产激情一区二区三区小说| 亚洲国产精品乱码一区二区| 麻豆视频一区二区三区| 亚洲欧美日韩国产精品一区| 亚洲AV色香蕉一区二区| 99久久精品费精品国产一区二区| 理论亚洲区美一区二区三区| 无码乱码av天堂一区二区|