Android權(quán)限機(jī)制簡述及動態(tài)權(quán)限管理的一種解決方案

簡述

Android是一個權(quán)限分離的操作系統(tǒng)幔托,每一個應(yīng)用程序運(yùn)行時(shí)都會有一個明確地系統(tǒng)身份標(biāo)識(Linux的user ID和group ID)静暂。部分系統(tǒng)也同樣被特定身份標(biāo)識而隔開。因此,Linux才能將應(yīng)用程序與其他程序和系統(tǒng)隔離開來隐绵。

這樣的機(jī)制可以說是相當(dāng)安全,但是也阻斷了各個應(yīng)用程序之間或者和系統(tǒng)之間的“交流”朴皆。因此贴彼,Android通過一種“permission”機(jī)制強(qiáng)力限制某些特定地操作來達(dá)到細(xì)粒度的安全能力。

進(jìn)程沙箱

Android進(jìn)程沙箱機(jī)制是借鑒Linux中用戶組的原理窍育,其限制了不同應(yīng)用程序之間的資源和數(shù)據(jù)的互訪卡睦。當(dāng)應(yīng)用首次安裝的時(shí),系統(tǒng)會向其分配一個UID漱抓。如果該應(yīng)用程序是第三方的表锻,那么其UID值大于10000,如果是系統(tǒng)應(yīng)用程序則小于10000乞娄。如果應(yīng)用程序卸載后又重新安裝瞬逊,那么其UID值是會改變的。

    //獲取應(yīng)用程序UID方法
    public void getApplicationUid() {
        PackageManager pm = getPackageManager();
        try {
            ApplicationInfo ai = pm.getApplicationInfo(getPackageName(), PackageManager.GET_ACTIVITIES);
            Log.d(getClass().getSimpleName(), "uid = " + ai.uid);

        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

不同UID的應(yīng)用程序是不能進(jìn)行資源互訪仪或,從而有效達(dá)到進(jìn)程隔離目的确镊。


Android應(yīng)用程序的沙箱機(jī)制

此外,你可以每個應(yīng)用程序的AndroidManifest.xml文件中使用ShareUserID屬性來使他們擁有同一UserID范删。UserID相同的應(yīng)用程序?qū)幌到y(tǒng)當(dāng)做同一應(yīng)用程序蕾域,擁有相同的UserID和文件權(quán)限。

注意:為了保留系統(tǒng)安全性,只有簽名相同(并且需要相同的shareUserId)的應(yīng)用程序才會被分配相同的UserID旨巷。

一個應(yīng)用程序存儲的任何數(shù)據(jù)都會被分配應(yīng)用程序的UserID,通常是不能被其他應(yīng)用程序所訪問巨缘。當(dāng)使用getSharedPreferences(String, int),openFileOutput(String, int)采呐,或者openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory)若锁,你可以使用MODE_WORLD_READABLE或者M(jìn)ODE_WORLD_WRITEABLE標(biāo)記來允許其他應(yīng)用程序讀或?qū)懳募?/p>

權(quán)限使用

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.app.myapp" >
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    ...
</manifest>

權(quán)限的使用是相當(dāng)簡單的,某功能需要申請權(quán)限時(shí)懈万,只需在AndroidManifest.xml文件中申明對應(yīng)權(quán)限就行拴清。如上述代碼。

如果你的App在其manifest文件中聲明一系列normal permissions(不會對用戶隱私或者設(shè)備運(yùn)行構(gòu)成威脅的權(quán)限)会通,系統(tǒng)會自動準(zhǔn)許這些權(quán)限申請口予。如果你的App在其manifest文件中聲明一系列dangerous permissions(對用戶隱私或者設(shè)備運(yùn)行構(gòu)成潛在威脅的權(quán)限),系統(tǒng)將會詢問用戶是否同意這些權(quán)限申請涕侈。
詢問的方式根據(jù)系統(tǒng)的版本而有所不同沪停。
1.靜態(tài)權(quán)限申請?jiān)儐柦缑?br> 若設(shè)備運(yùn)行的系統(tǒng)版本為Android5.1(API版本22)或更低,或者App的targetSdkVersion是22或更低裳涛,Android提供的是靜態(tài)權(quán)限申請?jiān)儐柦缑妗?br> 這種詢問方式只要玩過Android手機(jī)的應(yīng)該都見過木张,當(dāng)應(yīng)用程序首次安裝時(shí),會彈出以下類似界面端三,出現(xiàn)在圖標(biāo)列表中的權(quán)限都是dangerous permissions舷礼。


應(yīng)用程序首次安裝權(quán)限詢問界面

這種詢問方式相當(dāng)霸道,如果想要安裝該應(yīng)用郊闯,我們只有同意其申請的所有權(quán)限妻献。當(dāng)應(yīng)用程序安裝更新時(shí),如果該應(yīng)用程序有新申請的權(quán)限团赁,那么該權(quán)限詢問界面會將新申請的權(quán)限列出育拨。你廢除這些權(quán)限申請的唯一方式就是卸載它們!

  1. 動態(tài)權(quán)限申請?jiān)儐柦缑?br> 如果設(shè)備運(yùn)行的系統(tǒng)版本為Android6.0(API版本23)或更高欢摄,或者App的targetSdkVersion是23或更高熬丧,Android提供了動態(tài)權(quán)限申請?jiān)儐柦缑妗?br> 其實(shí)這種方式,早在Android6.0之前就有大批國產(chǎn)ROM提供動態(tài)權(quán)限管理方式怀挠,市面上主流的安全軟件也提供這種功能析蝴。Google終于在Android6.0提供了動態(tài)權(quán)限管理功能(不過對我大天朝來說然并卵)。


    動態(tài)權(quán)限申請?jiān)儐柦缑?/div>

    這種交互方式更加的人性化绿淋,也更加安全嫌变。在應(yīng)用程序運(yùn)行的過程中,如果需要申請網(wǎng)絡(luò)連接權(quán)限躬它,那么系統(tǒng)會彈出權(quán)限詢問對話框供用戶選擇。

當(dāng)然东涡,權(quán)限并不僅僅局限于此冯吓。我們也可以自定義某些權(quán)限來保證安全性倘待。比如,啟動Activity或者Service時(shí)组贺,增加權(quán)限控制凸舵,防止被外部應(yīng)用程序胡亂啟動。

權(quán)限組

對普通第三方應(yīng)用程序來說失尖,權(quán)限一般分為normal permission和dangerous permission啊奄。Android系統(tǒng)所有的dangerous permissions都屬于某一權(quán)限組。如果設(shè)備運(yùn)行的系統(tǒng)版本為Android6.0(API版本23)或更高掀潮,或者App的targetSdkVersion是23或更高菇夸,當(dāng)你的應(yīng)用程序需要一個dangerous permission時(shí),那么:

  1. 如果應(yīng)用程序在manifest中聲明了一個dangerous permission仪吧,并且它目前沒有該權(quán)限組中的任一權(quán)限择诈,那么系統(tǒng)會彈出一個將要申請權(quán)限組的對話框荷科。但是該對話框不會具體描述是該權(quán)限組中的哪一個權(quán)限。比如應(yīng)用程序需要READ_CONTACTS權(quán)限,那么該對話框僅僅只描述為該應(yīng)用程序需要訪問聯(lián)系人。
    2.如果應(yīng)用程序在manifest中聲明了一個dangerous permission,并且它已經(jīng)擁有該權(quán)限組的其他權(quán)限,那么系統(tǒng)將直接允許其訪問該權(quán)限移袍,不與用戶產(chǎn)生交互啡浊。

若設(shè)備運(yùn)行的系統(tǒng)版本為Android5.1(API版本22)或更低涂籽,或者App的targetSdkVersion是22或更低,系統(tǒng)將會在應(yīng)用程序安裝的時(shí)候讓用戶同意權(quán)限申請。系統(tǒng)僅僅只告訴用戶哪些權(quán)限組被申請,而不是單獨(dú)某一個權(quán)限。

Android6.0動態(tài)權(quán)限管理

國產(chǎn)ROM和各類安全軟件早已提供了動態(tài)權(quán)限管理功能诬留,實(shí)現(xiàn)方式上大同小異腺劣,雖然對用戶來說這是相當(dāng)利好的消息涡上,但是對我們開發(fā)者來說,還是很麻煩的腮恩,各種ROM的兼容性讓我們很頭疼武契。終于在棉花糖上,Android提供了動態(tài)權(quán)限管理的相關(guān)API荡含,我們在處理權(quán)限問題上方便了很多咒唆。
當(dāng)你的需要申請一個dangerous permission時(shí)候,你必須在每次申請之前進(jìn)行權(quán)限檢查释液。權(quán)限檢查的方法如下全释。

int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);

如果該方法的返回值為PackageManager.PERMISSION_GRANTED,應(yīng)用程序就可以繼續(xù)后續(xù)操作误债。如果應(yīng)用程序沒有該權(quán)限浸船,那么方法的返回值為PERMISSION_DENIED,并且將會詢問用戶是否允許該權(quán)限寝蹈。
我們在Manifest中申請的任何dangerous permission李命,都會詢問用戶是否允許該權(quán)限,Android提供了幾個申請權(quán)限的方法箫老,調(diào)用之后封字,會彈出一個標(biāo)準(zhǔn)的系統(tǒng)對話框供用戶選擇,該對話框是不能自定義的槽惫。

如果一個圖像類軟件申請發(fā)短信權(quán)限周叮,用戶可能會產(chǎn)生懷疑,是不是扣費(fèi)短信界斜。那么我們?nèi)绾谓档陀脩舻牟乱赡胤碌ⅲ緼ndroid提供了一個比較實(shí)用的方法shouldShowRequestPermissionRationale(),該方法給了我們一個解釋的機(jī)會來增加權(quán)限申請通過的概率各薇。如果該權(quán)限之前已被申請過但是被用戶拒絕项贺,那么shouldShowRequestPermissionRationale()方法返回true君躺。

如果你的應(yīng)用程序沒有所需要的權(quán)限,那么你必須要通過調(diào)用requestPermissions()方法來申請權(quán)限开缎,該方法調(diào)用后棕叫,系統(tǒng)會立刻彈出權(quán)限申請?jiān)儐枌υ捒蚬┕┯脩暨x擇,在用戶交互后奕删,系統(tǒng)會立刻通過onRequestPermissionsResult()將結(jié)果返回給應(yīng)用程序俺泣。這里直接將官方文檔中相關(guān)演示代碼貼出來供參考。

// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
                Manifest.permission.READ_CONTACTS)
        != PackageManager.PERMISSION_GRANTED) {

    // Should we show an explanation?
    if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
            Manifest.permission.READ_CONTACTS)) {

        // Show an expanation to the user *asynchronously* -- don't block
        // this thread waiting for the user's response! After the user
        // sees the explanation, try again to request the permission.

    } else {

        // No explanation needed, we can request the permission.

        ActivityCompat.requestPermissions(thisActivity,
                new String[]{Manifest.permission.READ_CONTACTS},
                MY_PERMISSIONS_REQUEST_READ_CONTACTS);

        // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
        // app-defined int constant. The callback method gets the
        // result of the request.
    }
}
@Override
public void onRequestPermissionsResult(int requestCode,
        String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // contacts-related task you need to do.

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.
            }
            return;
        }

        // other 'case' lines to check for other
        // permissions this app might request
    }
}

再一次完残,系統(tǒng)權(quán)限對話框僅僅只描述你所申請權(quán)限所在權(quán)限組的描述伏钠,而不是針對某一特定權(quán)限。對于同一權(quán)限組的權(quán)限谨设,用戶只需同意一次即可熟掂。這種方案的好壞見仁見智,但是有時(shí)候感覺會把一個很小的問題給擴(kuò)大了扎拣,比如我們只是需要簡單的獲取設(shè)備的IMEI碼赴肚,那么這時(shí)候系統(tǒng)對話框的描述為應(yīng)用程序?qū)⒃L問設(shè)備信息。這時(shí)候用戶肯定會想二蓝,你訪問我設(shè)備信息作甚誉券!然后你的申請被無情拒絕了!

注意:你的應(yīng)用程序需要明確地申請每一個你需要的權(quán)限侣夷,即使用戶已經(jīng)同意了該權(quán)限所在權(quán)限組的另外一個權(quán)限横朋。此外,隨著Android版本的更新百拓,權(quán)限組中所含的權(quán)限可能會改變琴锭。因此,不要偷懶衙传,該顯示申請權(quán)限的地方還是要乖乖申請吧决帖。

合理申請權(quán)限

曾幾何時(shí),權(quán)限的濫用導(dǎo)致用戶隱私泄露頻發(fā)蓖捶,而今地回,用戶對隱私也愈發(fā)敏感,過渡的權(quán)限申請會給用戶造成不良的印象俊鱼。因此刻像,作為有節(jié)操的程序員,我們在權(quán)限申請上應(yīng)該慎重并闲,而不是一股腦把所有權(quán)限都給申請细睡。
隨著Android版本的更新,相應(yīng)的權(quán)限也會更新帝火,因此我們一定要注意不同targetSdkVersion屬性所帶來的權(quán)限變化溜徙,并盡可能的提高targetSdkVersion湃缎。在權(quán)限使用上Google也給了我們一些建議。

  1. 考慮使用Intent來完成權(quán)限相關(guān)的操作
    這點(diǎn)建議蠢壹,我覺得可以作為一個比較好的參考嗓违。在Manifest中,我們申請了SEND_SMS權(quán)限图贸,那么可以通過下面代碼完成發(fā)送短信功能蹂季。
SmsManager sm = SmsManager.getDefault();
sm.sendTextMessage(address, null, message, null, null);

如果發(fā)送短信時(shí)候,用戶選擇拒絕該權(quán)限申請疏日,那么你的功能也就Over了乏盐。
如果我們換intent方式進(jìn)行發(fā)送短信,則不會出現(xiàn)權(quán)限被拒絕的情況制恍,代碼如下。

    Intent intent = new Intent(Intent.ACTION_SENDTO);  
    intent.setData(Uri.parse("smsto:" + number));  
    intent.putExtra("sms_body", body);  
    context.startActivity(sendIntent); 

該方法會跳轉(zhuǎn)到發(fā)送短信界面(如果系統(tǒng)裝有多個短信類應(yīng)用神凑,那么系統(tǒng)會彈出一個選擇應(yīng)用對話框净神,讓用戶選擇使用何種應(yīng)用來完成發(fā)送短信功能),并填充好相應(yīng)的內(nèi)容溉委。類似的鹃唯,撥打電話和使用照相機(jī)等都可以使用intent來完成相應(yīng)的功能,降低了用戶拒絕權(quán)限的風(fēng)險(xiǎn)瓣喊。
最后坡慌,權(quán)限方式和intent方式各有千秋,根據(jù)不同的業(yè)務(wù)情景藻三,我們可以選擇不同的方式洪橘。

  1. 只申請你所需要的權(quán)限
    不想讓用戶覺得你的應(yīng)用程序是一個“流氓應(yīng)用”,最好不要過度申請權(quán)限棵帽。
    3.不要“吞噬”用戶
    在Android6.0中熄求,不要在同一時(shí)刻申請多種權(quán)限。因?yàn)橄到y(tǒng)可能會彈出多個系統(tǒng)權(quán)限詢問對話框逗概,這種情況:
    第一弟晚,用戶可能覺得很煩鎖,并退出你的應(yīng)用程序逾苫。
    第二卿城,用戶可能由于誤操作,拒絕了你的某些權(quán)限申請铅搓。
    因此瑟押,最好的方式還是在你需要的時(shí)候進(jìn)行申請吧。
    4.給出你為什么使用權(quán)限的原因
    為了降低權(quán)限申請被拒絕的風(fēng)險(xiǎn)狸吞,最好在調(diào)用requestPermissions()之前勉耀,進(jìn)行權(quán)限申請的說明指煎,使用戶覺得你不是在做“壞事”。

動態(tài)權(quán)限申請的一種解決方案

雖然目前Android6.0市場占有率相當(dāng)?shù)捅愠猓请S著時(shí)間的推移至壤,關(guān)于動態(tài)權(quán)限管理這一塊,我們遲早要接觸的枢纠。這里我參考Android官方開發(fā)文檔像街,封裝了動態(tài)權(quán)限管理所需的方法。雖然自己的項(xiàng)目中還未用到動態(tài)權(quán)限管理晋渺,但作為工作之余的學(xué)習(xí)還是大有裨益镰绎!

權(quán)限申請流程

權(quán)限申請流程圖

BaseActivity中完成權(quán)限申請

這里我沒有將權(quán)限申請相關(guān)方法封裝成一個類,而是在BaseActivity中添加相關(guān)方法木西。

public class BaseActivity extends AppCompatActivity {

    //申請請求的request code
    private final static int YZT_PERMISSION_REQUEST = 12;

    public final String TAG = getClass().getSimpleName();

    //是否跳轉(zhuǎn)過應(yīng)用程序信息詳情頁
    private boolean mIsJump2Settings = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mIsJump2Settings) {
            onRecheckPermission();
            mIsJump2Settings = false;
        }
    }
    //單個權(quán)限的檢查
    public void checkPermission(@NonNull final String permission, @Nullable String reason) {
        if (Build.VERSION.SDK_INT < 23) return;
        int permissionCheck = ContextCompat.checkSelfPermission(this, permission);
        if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
            //權(quán)限已經(jīng)申請
            onPermissionGranted(permission);

        } else {
            if (!TextUtils.isEmpty(reason)) {
                //判斷用戶先前是否拒絕過該權(quán)限申請畴栖,如果為true,我們可以向用戶解釋為什么使用該權(quán)限
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission)) {
                    //這里的dialog可以自定義
                    new AlertDialog.Builder(this).setCancelable(false).setTitle("溫馨提示").setMessage(reason).
                            setNegativeButton("我知道了", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    requestPermission(new String[]{permission});
                                    dialog.dismiss();
                                }
                            }).show();
                } else {
                    requestPermission(new String[]{permission});
                }
            } else {
                requestPermission(new String[]{permission});
            }

        }
    }
    //多個權(quán)限的檢查
    public void checkPermissions(@NonNull String... permissions) {
        if (Build.VERSION.SDK_INT < 23) return;
        //用于記錄權(quán)限申請被拒絕的權(quán)限集合
        List<String> permissionDeniedList = new ArrayList<>();
        for (String permission : permissions) {
            int permissionCheck = ContextCompat.checkSelfPermission(this, permission);
            if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
                onPermissionGranted(permission);
            } else {
                permissionDeniedList.add(permission);
            }
        }
        if (!permissionDeniedList.isEmpty()) {
            String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
            requestPermission(deniedPermissions);
        }
    }

    //調(diào)用系統(tǒng)API完成權(quán)限申請
    private void requestPermission(String[] permissions) {
        ActivityCompat.requestPermissions(this, permissions, YZT_PERMISSION_REQUEST);
    }

    //申請權(quán)限被允許的回調(diào)
    public void onPermissionGranted(String permission) {

    }
    //申請權(quán)限被拒絕的回調(diào)
    public void onPermissionDenied(String permission) {

    }
    //申請權(quán)限的失敗的回調(diào)
    public void onPermissionFailure() {

    }

    //如果從設(shè)置界面返回八千,則重新申請權(quán)限
    public void onRecheckPermission() {

    }

    //彈出系統(tǒng)權(quán)限詢問對話框吗讶,用戶交互后的結(jié)果回調(diào)
    @Override
    public final void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case YZT_PERMISSION_REQUEST:
                if (grantResults.length > 0) {
                    //用于記錄是否有權(quán)限申請被拒絕的標(biāo)記
                    boolean isDenied = false;
                    for (int i = 0; i < grantResults.length; i++) {
                        if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
                            onPermissionGranted(permissions[i]);
                        } else {
                            isDenied = true;
                            onPermissionDenied(permissions[i]);
                        }
                    }
                    if (isDenied) {
                        isDenied = false;
                        //如果有權(quán)限申請被拒絕,則彈出對話框提示用戶去修改權(quán)限設(shè)置恋捆。
                        showPermissionSettingsDialog();
                    }

                } else {
                    onPermissionFailure();
                }
                break;
        }
    }

    private void showPermissionSettingsDialog() {
        new AlertDialog.Builder(this).setCancelable(false).setTitle("溫馨提示").
                setMessage("缺少必要權(quán)限\n不然將導(dǎo)致部分功能無法正常使用").setNegativeButton("下次吧", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        }).setPositiveButton("去設(shè)置", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                jump2PermissionSettings();
            }
        }).show();
    }

    /**
     * 跳轉(zhuǎn)到應(yīng)用程序信息詳情頁面
     */
    private void jump2PermissionSettings() {
        mIsJump2Settings = true;
        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }
}

使用方法

public class MainActivity extends BaseActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //權(quán)限檢查
        String[] permissionArray = {Manifest.permission.SEND_SMS, Manifest.permission.CALL_PHONE};
        checkPermissions(permissionArray);
//        checkPermission(Manifest.permission.SEND_SMS, "YZT將要發(fā)生短信進(jìn)行身份驗(yàn)證");

    }

    @Override
    public void onRecheckPermission() {
        super.onRecheckPermission();
        String[] permissionArray = {Manifest.permission.SEND_SMS, Manifest.permission.CALL_PHONE};
        checkPermissions(permissionArray);
    }

    @Override
    public void onPermissionGranted(String permission) {
        super.onPermissionGranted(permission);
        switch (permission) {
            case Manifest.permission.SEND_SMS:
                //TODO:發(fā)送短信
                Toast.makeText(this, "發(fā)短信咯", Toast.LENGTH_LONG).show();
                break;
            case Manifest.permission.CALL_PHONE:
                //TODO:打電話
                Toast.makeText(this, "電話咯", Toast.LENGTH_LONG).show();
                break;
        }
    }

    @Override
    public void onPermissionDenied(String permission) {
        super.onPermissionDenied(permission);
        switch (permission) {
            case Manifest.permission.SEND_SMS:
                //TODO:
                break;
            case Manifest.permission.CALL_PHONE:
                //TODO:
                break;
        }
    }

    @Override
    public void onPermissionFailure() {
        super.onPermissionFailure();
        Toast.makeText(this, "權(quán)限獲取失敗", Toast.LENGTH_LONG).show();
    }

隨著用戶安全意識的提升照皆,我們在權(quán)限的使用上也應(yīng)該更加趨于合理和謹(jǐn)慎。雖然目前Android6.0的占有率很低沸停,但是我們也應(yīng)該未雨綢繆膜毁,盡快引入動態(tài)權(quán)限管理機(jī)制。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末愤钾,一起剝皮案震驚了整個濱河市瘟滨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌能颁,老刑警劉巖室奏,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異劲装,居然都是意外死亡胧沫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門占业,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绒怨,“玉大人,你說我怎么就攤上這事谦疾∧硝澹” “怎么了?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵念恍,是天一觀的道長六剥。 經(jīng)常有香客問我晚顷,道長,這世上最難降的妖魔是什么疗疟? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任该默,我火速辦了婚禮,結(jié)果婚禮上策彤,老公的妹妹穿的比我還像新娘栓袖。我一直安慰自己,他們只是感情好店诗,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布裹刮。 她就那樣靜靜地躺著,像睡著了一般庞瘸。 火紅的嫁衣襯著肌膚如雪捧弃。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天擦囊,我揣著相機(jī)與錄音塔橡,去河邊找鬼。 笑死霜第,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的户辞。 我是一名探鬼主播泌类,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼底燎!你這毒婦竟也來了刃榨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤双仍,失蹤者是張志新(化名)和其女友劉穎枢希,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朱沃,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苞轿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逗物。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搬卒。...
    茶點(diǎn)故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翎卓,靈堂內(nèi)的尸體忽然破棺而出契邀,到底是詐尸還是另有隱情,我是刑警寧澤失暴,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布坯门,位于F島的核電站微饥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏古戴。R本人自食惡果不足惜欠橘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望允瞧。 院中可真熱鬧简软,春花似錦、人聲如沸述暂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畦韭。三九已至疼蛾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間艺配,已是汗流浹背察郁。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留转唉,地道東北人皮钠。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像赠法,于是被迫代替她去往敵國和親麦轰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容