POSIX 檔案能力:分配根使用者的能力
摘自: http://www.ibm.com/developerworks/cn/linux/l-posixcap.html
Linux® 多年來都使用能力(capability)的概念,但是最近實現了 POSIX 檔案能力。POSIX 檔案能力將根使用者的權力劃分成更小的特權,比如讀取檔案或跟蹤另一個使用者擁有的程序。通過為檔案分配能力,可以讓非特權使用者能夠用這些指定的特權執行檔案。在本文中,瞭解程式如何使用能力,以及如何改變系統 setuid root 二進位制程式碼來使用檔案能力。
些程式需要以非特權使用者的身份執行特權操作。例如,passwd
程式經常對 /etc/passwd
和
/etc/shadow
passwd
程式,而且它對允許使用者執行的操作有嚴格限制,所以這個設定常常是安全的。更復雜的程式使用儲存的 uid 在根使用者和非根使用者之間來回切換。
POSIX 能力將根特權劃分成更小的特權,所以可以只用根使用者特權的一個子集來執行任務。檔案能力特性可以給一個程式分配這樣的特權,這大大簡化了能力的使用。在 Linux 中已經可以使用 POSIX 能力了。與將使用者切換為根使用者相比,使用能力有幾個好處:
exec(3)
Linux 手冊頁上指出:exec()
函式系列用一個新的程序映像替換當前的程序映像。更多細節參見
參考資料。
- 可以將能力從有效集(effective set)中刪除,但是保留在允許集(permitted set)中,從而防止濫用能力。
- 可以從允許集中刪除所有不需要的能力,這樣就無法恢復這些能力。坦率地說,大多數能力是危險的,可能被濫用,減少攻擊者可以利用的能力有助於保護系統。
- 在對常規的可執行檔案執行
exec(3)
之後,所有能力都會丟失。(細節比較複雜,而且這種情況可能不久就會改變。本文後面會進一步解釋這個問題。)
本文講解程式如何使用 POSIX 能力,如何確定一個程式需要哪些能力,以及如何為程式分配這些能力。
程序能力
多年以來,POSIX 能力只能分配給程序,而不能分配給檔案。因此,程式必須由根使用者啟動(或者程式屬於根使用者並設定了它的 setuid 位),然後才能放棄某些根特權,同時保留其他特權。另外,放棄能力的操作次序也非常嚴格:
- 程式告訴系統,它希望保留它的能力,但是要修改它的有效 userid。這要使用
prctl
。 - 程式將它的 userid 改為非根使用者。
- 程式構造所需的能力集並設定為活動集。
程序有三個能力集:允許(permitted,P)、可繼承(inheritable,I) 和有效(effective,E)。在產生程序時,子程序從父程序複製能力集。當一個程序執行一個新程式時,根據公式計算新的能力集(稍後討論這些公式)。
有效集 中的能力是程序當前可以使用的。有效集必須是允許集 的子集。只要有效集不超過允許集的範圍,程序任何時候都可以修改有效集的內容。可繼承集 只用於在執行
exec()
之後計算新的能力集。
清單 1 給出三個公式,它們表示在檔案執行之後根據 POSIX 草案計算出的新能力集(參見 參考資料 中 IEEE Std 1003.1-2001 的連結)。
清單 1. 在執行 exec() 之後計算新能力集的公式
pI' = pI pP' = fP | (fI & pI) pE' = pP' & fE
以 '
結尾的值表示新計算出的值。以 p
開頭的值表示程序能力。以 f
開頭的值表示檔案能力。
可繼承集按原樣從父程序繼承,沒有任何修改,所以程序一旦從可繼承集中刪除一個能力,就應該無法再恢復它(但是請閱讀下面對
SECURE_NOROOT
的討論)。 新的允許集是檔案的允許集與檔案和程序的可繼承集的交集合並的結果。程序的有效集是新的允許集和檔案有效集的交集。從技術上說,在 Linux 中,fE
不是一個集,而是一個布林值。如果這個值是 true,那麼
pE'
就設定為 pP'
。如果是 false,pE'
就是空的。
如果程序要在執行一個檔案之後保留任何能力,那麼這些能力必須被包含在檔案的允許集或可繼承集中。因為 Linux 在相當長的時期內沒有實現檔案能力,所以這是一個難以實施的限制。為了解決這個問題,實現了 “安全模式(secure mode)”。它由兩位組成:
- 如果沒有設定
SECURE_NOROOT
,那麼當程序執行檔案時,就按照完全填充的檔案能力集計算新的能力集。具體地說:- 如果程序的真實 uid 或有效 uid 是 0(根使用者),或者檔案是 setuid root,那麼檔案的可繼承集和允許集就是滿的。
- 如果程序的有效 uid 是根使用者,或者檔案是 setuid root,那麼檔案有效集就是滿的。
- 如果沒有設定
SECURE_NO_SETUID_FIXUP
,那麼當程序將它的真實或有效 uid 切換到 0 或切換回來時,要分幾種情況計算能力集:- 如果程序將它的有效 uid 從 0 切換到非 0,那麼它的有效能力集被清空。
- 如果程序將它的真實、有效或儲存的 uid 從至少一個 0 切換到全部非 0,那麼允許能力集和有效能力集都被清空。
- 如果程序將它的有效 uid 從非 0 切換到 0,那麼有效集被設定為與允許集相同。
這套規則讓程序可以根據根使用者或者通過執行 setuid root 檔案擁有能力。但是,SECURE_NO_SETUID_FIXUP
禁止程序在變成非根之後保留任何能力。但是,如果沒有設定
SECURE_NOROOT
,那麼一個已經放棄一些能力的根程序只需執行另一個程式,就能夠恢復它的能力。所以為了能夠使用能力並保證系統安全,根程序必須能夠不可逆轉地將它的 uid 切換到非 0,同時保留一些能力。
通過使用 prctl(3)
,程序可以請求在下一次呼叫 setuid(2)
時保留它的能力。這意味著程序可以:
- 通過根使用者身份或者執行 setuid root 二進位制檔案,作為根程序啟動。
- 通過呼叫
prctl(2)
設定 PR_SET_KEEPCAPS,這請求系統在呼叫setuid(2)
時保留它的能力。 - 呼叫
setuid(2)
或相關的系統呼叫來修改 userid。 - 呼叫
cap_set_proc(3)
來刪除能力。
現在,程序可以一直用根特權的一個子集執行。如果攻擊者突破了這個程式,他也只能使用有效集中的能力;即使呼叫了 cap_set_proc(3)
,也只能使用允許集中的能力。另外,如果攻擊者迫使這個程式執行另一個檔案,那麼所有能力都會撤消,將作為非特權使用者執行這個檔案。
清單 2 中的 exec_with_caps()
函式可以縮減程式碼的能力,setuid root 程式可以通過它作為指定的 userid 連續執行一個指定的函式,執行時的能力集由一個字串指定。
清單 2. 用縮減的能力執行程式碼
#include <sys/prctl.h> #include <sys/capability.h> #include <sys/types.h> #include <stdio.h> int printmycaps(void *d) { cap_t cap = cap_get_proc(); printf("Running with uid %d\n", getuid()); printf("Running with capabilities: %s\n", cap_to_text(cap, NULL)); cap_free(cap); return 0; } int exec_with_caps(int newuid, char *capstr, int (*f)(void *data), void *data) { int ret; cap_t newcaps; ret = prctl(PR_SET_KEEPCAPS, 1); if (ret) { perror("prctl"); return -1; } ret = setresuid(newuid, newuid, newuid); if (ret) { perror("setresuid"); return -1; } newcaps = cap_from_text(capstr); ret = cap_set_proc(newcaps); if (ret) { perror("cap_set_proc"); return -1; } cap_free(newcaps); f(data); } int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s <capability_list>\n", argv[0]); return 1; } return exec_with_caps(1000, argv[1], printmycaps, NULL); }
為了測試這個函式,將程式碼複製到一個檔案中並儲存為 execwithcaps.c,編譯並作為根使用者執行它:
gcc -o execwithcaps execwithcaps.c -lcap ./execwithcaps cap_sys_admin=eip
檔案能力
檔案能力特性當前是在 -mm
核心樹中實現的,有望在 2.6.24 版中被包含在主線核心中。可以利用檔案能力特性將能力分配給程式。例如,ping 程式需要
CAP_NET_RAW
。因此,它一直是一個 setuid root 程式。有了檔案能力特性之後,就可以減少這個程式的特權數量:
chmod u-s /bin/ping setfcaps -c cap_net_admin=p -e /bin/ping
這需要從 GoogleCode 獲得 libcap 庫和相關程式的最新版本(參見
參考資料 中的連結)。以上命令首先從二進位制檔案上刪除 setuid 位,然後給它分配所需的 CAP_NET_RAW
特權。現在,任何使用者都可以用
CAP_NET_RAW
特權執行 ping,但是如果 ping 程式被突破了,攻擊者也無法掌握其他特權。
問題在於,如何判斷一個非特權使用者在執行某個程式時需要的最小能力集。如果只考慮一個程式的話,那麼可以研究應用程式本身、它的動態連結庫和核心原始碼。但是,需要對所有 setuid root 程式都重複這個過程。當然,在允許非特權使用者作為根使用者執行一個應用程式之前,採用這種方法進行檢查並不是個壞主意,但是這種方法不切實際。
如果一個程式提供詳細的錯誤輸出而且表現正常,那麼不使用任何特權來執行這個程式,然後檢查錯誤訊息,看看它缺少哪些特權。我們來對 ping 試試這種方法。
chmod u-s /bin/ping setfcaps -r /bin/ping su - myuser ping google.com ping: icmp open socket: Operation not permitted
如果我們瞭解 icmp
的實現,這種技巧可以幫助我們判斷問題,但是它確實沒有把問題說清楚。
接下來,我們可以試著在 strace
之下執行這個程式(同樣不設定 suid 位)。strace
會報告這個程式使用的所有系統呼叫及其返回值,所以可以通過檢視
strace
輸出中的返回值來判斷缺少的許可權。
strace -oping.out ping google.com grep EPERM ping.out socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)
我們缺少建立套接字型別 SOCK_RAW
的許可權。檢視 /usr/include/linux/capability.h,會看到:
/* Allow use of RAW sockets */ /* Allow use of PACKET sockets */ #define CAP_NET_RAW 13
顯然,為了允許非特權使用者使用 ping,需要的能力是 CAP_NET_RAW
。但是,有些程式可能會試圖執行它們並不真正需要的操作,-EPERM
會拒絕這些操作。判斷它們真正需要的能力並不這麼容易。
另一種更可行的方法是,在核心中檢查能力的地方插入一個探測。這個探測輸出關於被拒絕的能力的除錯資訊。
開發人員可以用 kprobes
編寫小的核心模組,從而在函式的開頭(jprobe
)、函式的結尾(kretprobe
)或在任何位置(kprobe
)執行程式碼。可以利用這個功能收集資訊,瞭解核心在執行某些程式時需要哪些能力。(本節的餘下部分假設您的核心啟用了
kprobes
和檔案能力。)
清單 3 是一個核心模組,它插入一個 jprobe
來探測 cap_capable()
函式的開頭。
清單 3. capable_probe.c
#include <linux/kernel.h> #include <linux/module.h> #include <linux/kprobes.h> #include <linux/sched.h> static const char *probed_func = "cap_capable"; int cr_capable (struct task_struct *tsk, int cap) { printk(KERN_NOTICE "%s: asking for capability %d for %s\n", __FUNCTION__, cap, tsk->comm); jprobe_return(); return 0; } static struct jprobe jp = { .entry = JPROBE_ENTRY(cr_capable) }; static int __init kprobe_init(void) { int ret; jp.kp.symbol_name = (char *)probed_func; if ((ret = register_jprobe(&jp)) < 0) { printk("%s: register_jprobe failed, returned %d\n", __FUNCTION__, ret); return -1; } return 0; } static void __exit kprobe_exit(void) { unregister_jprobe(&jp); printk("capable kprobes unregistered\n"); } module_init(kprobe_init); module_exit(kprobe_exit); MODULE_LICENSE("GPL");
當插入這個核心模組時,對 cap_capable()
的任何呼叫都被替換為對 cr_capable()
函式的呼叫。這個函式輸出需要能力的程式的名稱和被核查的能力。然後,通過呼叫
jprobe_return()
繼續執行實際的 cap_capable()
呼叫。
使用清單 4 中的 makefile 編譯這個模組:
清單 4. capable_probe 的 makefile
obj-m := capable_probe.o KDIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) default: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -f *.mod.c *.ko *.o
然後作為根使用者執行它:
/sbin/insmod capable_probe.ko
現在在一個視窗中,用以下命令檢視系統日誌:
tail -f /var/log/messages
在另一個視窗中,作為非根使用者執行沒有設定 setuid 位的 ping 二進位制程式:
/bin/ping google.com
系統日誌現在包含關於 ping 的幾條記錄。這些記錄指出這個程式試圖使用的能力。這些能力並非都是必需的。ping 請求的能力是 21、13 和 7,可以檢查 /usr/include/linux/capability.h,將整數轉換為能力名稱:
- 21 是
CAP_SYS_ADMIN
。不要把這個能力授予任何 程式。 - 7 是
CAP_SETUID
。ping 應該不需要這個能力。 - 13 是
CAP_NET_RAW
。ping 應該需要這個能力。
我們將這個能力授予 ping,看看它是否能夠成功執行。
setfcaps -c cap_net_raw=p -e /bin/ping (become non root user) ping google.com
不出所料,ping 成功了。
複雜情況
現有的軟體常常編寫得儘可能可靠,在許多 UNIX 變體上很少有改動。發行版有時候會在此之上應用它們自己的補丁,所以在某些情況下不可能用檔案能力替代 setuid 位。
這種情況的一個例子是 Fedora 上的 at
。at
程式允許使用者將作業安排在以後某個時間執行。例如,可以在下午 2 點提醒使用者打電話:
echo "xterm -display :0.0 -e \ \"echo Call customer 555-5555; echo ^V^G; sleep 10m\" " | \ at 14:00
所有 UNIX 系統上都有 at
程式,任何使用者都可以使用它。使用者共享 /var/spool 下面的一個公用作業假離線檔案。因此它的安全性極其重要,但是它是跨許多系統工作,所以不能使用系統特有的安全機制(比如能力)。無論如何,它試圖通過使用
setuid(2)
減少特權。在此基礎上,Fedora 通過應用補丁使用 PAM 模組。
要想查明非根使用者是否可以執行不帶 setuid 位的 at
,最快的方法是刪除 setuid 位,然後授予所有能力:
chmod u-s /usr/bin/at setfcaps -c all=p -e /usr/bin/at su - (non root user) /usr/bin/at
通過指定 -c all=p
,我們請求在 /usr/bin/at
上設定包含所有能力的允許能力集。所以,執行這個程式的任何使用者都擁有所有根特權。但是在 Fedora 7 上,執行
/usr/bin/at
會產生以下結果:
You do not have permission to run at.
如果下載並研究原始碼,就可以找到原因,但是這些細節對本文沒有幫助。肯定可以修改原始碼,讓 at
能夠使用檔案能力,但是在 Fedora 上簡單地分配檔案能力並不能取代 setuid 位。
檔案能力細節
在前面,我們使用一種專用的格式給可執行程式分配能力。我們對 ping 使用了以下命令:
setfcaps -c cap_net_raw=p -e /bin/ping
setfcaps
程式通過設定一個名為 security.capability 的擴充套件屬性,設定目標檔案的能力。-c
標誌後面是一個格式比較隨意的能力列表:
capability_list=capability_set(s)
capability_set
可以包含 i
和 p
,capability_list
可以包含任何有效能力。能力型別分別代表可繼承集和允許集,可以為每個集指定單獨的能力列表。-e
或
-d
標誌分別表示允許集中的能力在啟動時是否在程式的有效集中。如果能力不在程式的有效集中,那麼程式必須能夠感知能力,必須自己啟用有效集中的位,才能使用能力。
到目前為止,我們已經在允許集中設定了所需的能力,但是還沒有在可繼承集中設定。實際上,我們可以用能力實現更精細更強大的效果。下面回憶一下清單 1:
重複清單 1. 在執行 exec() 之後計算新能力集的公式
pI' = pI pP' = fP | (fI & pI) pE' = pP' & fE
檔案可繼承集決定程序的哪些可繼承能力可以放在新的程序允許集中。如果檔案可繼承集中只有 cap_dac_override
,那麼只能將這個能力繼承到新的程序允許集中。
檔案允許集也稱為 “強迫(forced)” 集,其中的能力總是出現在新的程序允許集中,無論這些能力是否在任務的可繼承集中。
最後,檔案有效位表示任務的新允許集中的位是否應該在新的有效集中設定;也就是說,程式是否能夠馬上使用這些能力,而不需要用 cap_set_proc(3)
顯式地請求它們。
如果沒有設定 SECURE_NOROOT
,系統會對根使用者做一些修改。就是說,系統假設在執行檔案時,可繼承集(fI
)、允許集(fP
)和有效集(fE
)包含所有能力。所以二進位制檔案上的 fI 集只對具有非空能力集的非根程序有作用。對於在變成非根使用者時保留能力的程式,將應用上面的公式,而不會使用上面的假設。SECURE_NOROOT
以後可能會成為每個程序的設定,讓程序樹可以選擇是使用本身的能力,還是使用
root-user-is-privileged 模型。但是到編寫本文時,在任何實際系統上,這還是一個系統範圍的設定,它的預設設定讓根使用者總是擁有所有能力。
為了演示這些集的相互作用,假設管理員用以下命令在 /bin/some_program 上設定了檔案能力:
setfcaps -c cap_sys_admin=i,cap_dac_read_search=p -e \ /bin/some_program
如果一個非根使用者在擁有所有能力的情況下執行這個程式,首先計算它的可繼承集(pI
)和 fI
的交集,所以縮減到只包含
cap_sys_admin
。接下來,計算 fP
和這個集的並集,所以結果是 cap_sys_admin+cap_dac_read_search
。這個整合為新的任務允許集。
最後,因為設定了有效位,新的任務有效集將包含新允許集中的兩個能力。
另一方面,如果一個完全沒有特權的使用者運行同一個程式,他的可繼承集是空的,這個集與 fI
求交集,會產生一個空集。這個空集與
fP
求並集,產生 cap_dac_read_search
。這個整合為新的任務允許集。最後,因為設定了有效位,新的有效集複製新的允許集,同樣只包含
cap_dac_read_search
。
在這兩種情況下,如果沒有設定有效位,那麼任務需要使用 cap_set_proc(3)
將它所需的位從允許集複製到有效集。
總結和練習
下面總結一下:
- 檔案有效位表示程式在預設情況下是否能夠使用它的允許能力。
- 檔案允許集中的能力總會在產生的程序上啟用。
- 檔案可繼承集中的能力可以從父程序的可繼承集繼承到新的允許集。
為了演示前面討論的內容,我們編寫了清單 5 和清單 6 中的程式。在清單 5 中,print_caps
僅僅輸出當前的能力集。在清單 6 中,嘗試作為根使用者執行
exec_as_nonroot_priv
。它請求在下一次呼叫 setuid(2)
時保留它的能力,變成第一個命令列引數指定的非根使用者,將它的能力集設定為第二個命令列引數指定的集,然後執行第三個命令列引數指定的程式。
清單 5. print_caps.c
#include <stdio.h> #include <stdlib.h> #include <sys/capability.h> int main(int argc, char *argv[]) { cap_t cap = cap_get_proc(); if (!cap) { perror("cap_get_proc"); exit(1); } printf("%s: running with caps %s\n", argv[0], cap_to_text(cap, NULL)); cap_free(cap); return 0; }
清單 6. exec_as_nonroot_priv.c
#include <sys/prctl.h> #include <sys/capability.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> void printmycaps(void) { cap_t cap = cap_get_proc(); if (!cap) { perror("cap_get_proc"); return; } printf("%s\n", cap_to_text(cap, NULL)); cap_free(cap); } int main(int argc, char *argv[]) { cap_t cur; int ret; int newuid; if (argc<4) { printf("Usage: %s <uid> <capset>" "<program_to_run>\n", argv[0]); exit(1); } ret = prctl(PR_SET_KEEPCAPS, 1); if (ret) { perror("prctl"); return 1; } newuid = atoi(argv[1]); printf("Capabilities before setuid: "); printmycaps(); ret = setresuid(newuid, newuid, newuid); if (ret) { perror("setresuid"); return 1; } printf("Capabilities after setuid, before capset: "); printmycaps(); cur = cap_from_text(argv[2]); ret = cap_set_proc(cur); if (ret) { perror("cap_set_proc"); return 1; } printf("Capabilities after capset: "); cap_free(cur); printmycaps(); ret = execl(argv[3], argv[3], NULL); if (ret) perror("exec"); }
我們用這些程式檢驗一下可繼承集和允許集的效果。在 print_caps
上設定檔案能力,然後用 exec_as_nonroot_priv
仔細設定初始程序能力集並執行
print_caps
。首先,只在 print_caps
的允許集中設定一些能力:
gcc -o print_caps print_caps.c -lcap setfcaps -c cap_dac_override=p -d print_caps
現在,作為非根使用者執行 print_caps
:
su - (username) ./print_caps
接下來,作為根使用者通過 exec_as_nonroot_priv
執行 print_caps
:
./exec_as_nonroot_priv 1000 cap_dac_override=eip ./print_caps
在這兩種情況下,print_caps
執行時的能力集都是 cap_dac_override=p
。注意,有效位是空的。這意味著
print_caps
必須先呼叫 cap_set_proc(3)
,然後才能使用 cap_dac_override
能力。要想改變這種情況,可以在
setflags
命令中使用 -e
標誌設定有效位。
setfcaps -c cap_dac_override=p -e print_caps
print_caps
的 fI
是空的,所以程序的 pI
中的能力都不能繼承到
pP'
中。pP'
只包含來自檔案強迫集(fP
)中的一位。
另一個有意思的測試檢驗可繼承檔案能力的效果,同樣作為非根使用者和通過 exec_as_nonroot_priv
程式兩種方式執行
print_caps
:
setfcaps -c cap_dac_override=i -e print_caps su - (nonroot_user) ./print_caps exit ./exec_as_nonroot_priv 1000 cap_dac_override=eip ./print_caps
這一次,非根使用者的能力集是空的,作為根使用者啟動的程序的允許集和有效集中包含 cap_dac_override
。
再次執行 print_caps
,這一次直接作為根使用者執行,而不通過 exec_as_nonroot_priv
。注意,能力集是空的。無論檔案能力如何設定,根使用者在執行程式之後總是獲得完整的能力集。exec_as_nonroot_priv
並不作為根使用者執行
print_caps
。相反,它使用根使用者的特權為非根程序設定一些可繼承能力。
相關推薦
POSIX 檔案能力:分配根使用者的能力
摘自: http://www.ibm.com/developerworks/cn/linux/l-posixcap.html Linux® 多年來都使用能力(capability)的概念,但是最近實現了 POSIX 檔案能力。POSIX 檔案能力將根使用者的權力劃分成更小
基於中臺思想的物流系統設計(二):構建物流訂單能力
一、引言 物流訂單能力作為基礎能力,需要設計一套穩定的訂單模型,以及一套能夠在高併發環境下持續可用的介面。這些介面作為原子介面,供上層業務複用。上層業務無論多麼複雜,通過這些原子介面,最終都會收斂到穩定的訂單模型中來,這也是區分基礎能力和產品服務的一個重要的邊界。 本文通過以下5點來介紹如何構建一套物流訂
SRE 彈效能力:使用 Envoy 對應用進行速率限制
作者:dm03514 譯者:楊傳勝 原文:medium.com/dm03514-tec… 速率限制是緩解級聯故障和防止耗盡共享資源的一種簡單有效的方法。Envoy 是一個功能豐富的代理,可以為任何服務輕鬆新增速率限制的功能。本文將介紹在不更改應用程式本身配置的前提下如何配置
Linux:基礎IO(檔案描述符分配規則)(重定向)(inode)(軟硬連結)(動態庫靜態庫)
目錄 檔案描述符的分配規則 重定向原理 FILE 總結 理解檔案系統 inode是什麼 inode內容 硬連結 軟連結 軟硬連結區別: 動態庫和靜態庫 如何生成自己的動態庫和靜態庫 如何連結一個庫生成可執行程式 檔案描述符的分配規則 最
基於中臺思想的物流系統設計(三):構建物流地址能力
一、引言 在電商物流領域我們會涉及到地址,其中包括了基礎的四級地址和使用者填寫的地址。四級地址在整個從下單到收貨的業務流程中都會用到,因此設計的時候要考慮如何最大限度地提高QPS。使用者地址在下單的時候讓使用者填寫或者選擇,然後存在交易訂單和物流訂單上,後續的流程一般不會變,如果使用者需要修改地址,直接變
美國稱大陸具備足夠對臺兩棲登陸能力:將成臺軍噩夢
@央廣軍事11月10日訊息,2018中國航展上首次公開展出的“瞭望者Ⅱ”察打一體導彈無人艇,是剛剛成功進行首發導彈飛行試驗命中靶心的實艇,試驗成功後隨即吊裝到展位與公眾見面。據媒體此前報道,該艇是中國第一艘導彈無人艇,也是繼以色列拉斐爾海上騎士後全球第二個成功發射導彈的無人艇,填補了國內導彈無人艇這一技術空白
資料分析師八大能力之一:收集資訊的能力
文章目錄 1.前景概要 2.業務模式 2.1 掙現金的公司 2.2 圈錢的公司 3.四大角色 3.1 產品 3.2 渠道 3.3 使用者 3.3 運營 4. 組織架構與
讀完這篇文章,就能擁有炫同事一臉的超能力:JavaScript 魔幻代理
前言 什麼是代理? 上小學的時候,李小紅來你家叫你出去玩,第一個迴應的不是你自己,是你媽:“王小明在家寫作業,今天不出去!” 上中學的時候,趙二虎帶著小弟們放學在校門口等著揍你,走在前面的不是你自己,是二虎他爸:“考試沒及格還學會裝黑社會了!”拎起二虎就是一頓胖揍。 上了大學,
教育知識與能力:“系統脫敏療法”考點分析
“系統脫敏療法”考點分析 系統脫敏療法又稱互動抑制法,是由美國學者沃爾帕創立和發展的。這種方法主要是誘導求治者緩慢地暴露出導致神經症焦慮、恐懼的情境,並通過心理的放鬆狀態來對抗這種焦慮情緒,從而達到消除焦慮或恐懼的目的。 系統脫敏療法主要是建立在經典條件反射和操
教育知識與能力:解讀科爾伯格的道德發展階段論
在教師資格考試中很多同學對德育理論中的皮亞傑和科爾伯格的理論都不是很瞭解,覺得內容過於繁複,不好記憶,那麼今天就和大家分享一下科爾伯格的道德發展階段理論的知識內容,通過故事講解的方式來讓大家理解科爾伯格的理論,通過意義記憶把握這一考點。 首先,科爾伯格用“道德兩
學科知識與能力:美術《園林知識點彙總》
園林知識點彙總 根據歷年教資考試彙總的考題來看,發現會有一些經常考到的知識點,所以中公講師特意為大家準備了關於園林部分知識點,希望能夠幫助大家更深入瞭解本節內容,直擊重點內容 一、中國古典園林 1.分類: 私家園林:蘇州獅子林、拙政園、網師園、留園等。 皇家園林
面試時我不在乎候選人的經驗來自培訓班,但會關注商業專案經驗和幹活能力:再說面試時鑑別商業專案的方式 最近面試java後端開發的感受:如果就以平時專案經驗來面試,通過估計很難——再論面試前的準備
我在部落格園裡乃至其它地方看到有不少對培訓班出身的程式設計師的評價,其實至少在我面試時,培訓班出來的程式設計師沒有原罪。 我也面試不少程式設計師,從高階開發到初級開發都有,有985和211名校出身的,也有大專學習通過培訓班積累IT經驗的。我見過有候選人
提高你的架構能力:資料庫拆分實現資料庫能力線性擴充套件
Java全棧技術 2018-12-21 08:45:32 點選關注,快速進階高階架構師 作者:兔龍象 我們公司前幾年的核心繫統,平均80人左右開發至今已經8年多了,至今還在維護,在全國20多個省部署了上千個點的執行,執行六七年後資料量上來了,結果平均每天都要出
產品經理的高階能力:架構圖的設計與畫法
文章結構: 基於抽象和複雜對產品架構圖的一些思考; 產品架構圖的設計思考與畫法。 一、基於抽象和複雜對產品經理個人能力的一些思考 日常的工作中,假如你身邊坐了一個女程式猿,為了讓乏味的工作氛圍增加點提神的荷爾蒙,文藝又懂點技術的你可能會對她說:小姐姐,我能把世間萬物抽象成一
回溯的能力:比起規劃產品,優秀的產品經理規劃“產品發動機”
作為產品經理,我們的任務絕不僅規劃功能那麼簡單,我們還需要負責建立工作流程、探索產品最優落地方式、並且努力搭建一個能讓產品高效進化的團隊文化。以下這些工作,都是在強化產品的進化引擎,讓產品能隨時間持續進化。 回溯(Retrospective)是強化引擎最有價值的方法之一。它幫助我們界定什麼是好的、不好的,推動
Traveler 10上的新能力:支援IMSMO郵件客戶機
大家好,才真是的好。今天我們要講述IMSMO郵件功能,即用Outlook連線Domino伺服器收發郵件。不過這種方式不是通過POP3或IMAP協議,而採用的是IMSMO客戶機方式,其協議主要是HTTP和HTTPS。這樣Outlook不僅僅可以和Domino進行郵件同步,也可以實現聯絡人、日程
專訪阿里雲MVP王俊傑:開發者的超能力是用技術讓世界更美好
【王俊傑:阿里雲MVP,陝西創博網路科技有限公司總經理。大資料與物聯網的愛好者與實踐者。 8年以上網際網路從業經驗,曾從事軍工相關模擬分析軟體研發與整合、4年以上大資料系統開發經驗。目前正與天水市秦州區政府配合建設智慧安監、智慧環保、智慧黨建、智慧婦聯等智慧城市相關配套服務平臺。】 2018年的9月18
【SDCC講師專訪】搜狗劉建:架構師=學習能力+好奇心+持續實踐
CSDN年度技術盛宴 “SDCC 2015中國軟體開發者嘉年華”將於2015年11月19-21日在北京召開。CSDN軟體研發頻道將採訪一些與會講師,談談他們將在會上分享的內容。 本期我們採訪的講師是來自搜狗架構師劉建——負責商業平臺基礎架構,對分散式計算、服務化、流式計算、資料庫架構、高可用高可靠等方面
阿里雲MVP:開發者的超能力,用技術創造更好世界
開發十年,就只剩下這套架構體系了! >>>
阿裏雲MVP:開發者的超能力,用技術創造更好世界
物聯網 ace 故事 上線 傳播 雲計 創業經歷 redis緩存 奧賽 阿裏雲MVP:開發者的超能力,用技術創造更好世界 2019年3月,第8期阿裏雲MVP(最有價值專家)完成終審,截至目前,全球已有27個國家和地區、近500位雲計算專家和優秀開發者成為阿裏雲MVP。阿裏雲