chapter 10-02

使用方式

此章節說明如何使用網頁端的登入登出功能.


分成 [網頁端] 和 [系統端] 說明.


網頁端

網頁的編碼格式必須是 UTF-8, 如下的宣告 :
<meta http-equiv="content-type" content="text/html; charset=utf-8">


需要的 JS 檔 :
jquery_main.js
md5.js
maam_jslib_api.js



相關的變數 :

[maam_jslib_lib_t this_maam_jslib]
用來儲存相關的的資訊.
會用到的結構成員 :
[request_action]
要執行的動作.
maaam_request_action
(mint_aam/maam_lib/maam_jslib/maam_jslib_api.js)
maaam_request_action.login 登入
maaam_request_action.logout 登出
maaam_request_action.check 檢查連線是否有效
[request_data]
要求的認證資料.
依據 request_action 的值 :
maaam_request_action.login 填入認證資料
maaam_request_action.logout 無作用, 填入空字串
maaam_request_action.check 無作用, 填入空字串
[other_query]
額外的查詢參數, 不需要使用的話填入空字串.

是否允許多個帳號同時登入系統的處裡方式
是否允許同一個帳號被多個使用者同時登入的的處裡方式
maam_limit_multiple_active
(mint_aam/maam_lib/maam_jslib/maam_jslib_api.js)
maam_limit_multiple_active.allow 允許
maam_limit_multiple_active.deny_force_kick_inside 禁止, 發生時踢掉已經登入的使用者
maam_limit_multiple_active.deny_force_kick_outside 禁止, 發生時踢掉正在登入的使用者
maam_limit_multiple_active.deny_permission_kick_inside 禁止, 發生時使用帳號的權限來決定, 高的保留低的踢掉
二邊權限一樣時 :
deny_permission_kick_inside
踢掉已經登入的使用者
deny_permission_kick_outside
踢掉正在登入的使用者

帳號的權限在後續系統端的帳號驗證時設定 [詳細]
maam_limit_multiple_active.deny_permission_kick_outside


相關的函式 :

md5
將資料做 MD5 加密.
參數 說明
data 要加密的字串
回傳
加密後的字串

maam_jslib_run_script
回應的訊息可是 JavaScript 格式, 使用此函式執行.
參數 說明
script_con 要執行的 JavaScript 內容

maam_jslib_account_auth
執行登入, 登出, 檢查等動作.
參數 說明
this_maam_jslib 用來儲存相關的的資訊
需要先設定以下的結構成員 :
request_action [詳細]
request_data [詳細]
other_query [詳細]
回傳 說明
$.rep_code 依據 request_action 的值 :

maaam_request_action.login
$.rep_code 說明 $.rep_data
maam_return_code.pass 成功 網頁導向主要頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
maam_return_code.internal_error
maam_return_code.jslib_internal_error
失敗, 內部錯誤 空資料
maam_return_code.session_table_full 失敗, 系統 session 數以滿 空資料
maam_return_code.miss_verify_name 失敗, 認證資料缺少帳號名稱資料 空資料
maam_return_code.miss_verify_password 失敗, 認證資料缺少帳號密碼資料 空資料
maam_return_code.miss_multiple_user_active_rule 失敗, 認證資料缺少多個帳號同時登入系統的處裡方式的資料 空資料
maam_return_code.miss_same_accout_multiple_active_rule 失敗, 認證資料缺少同一個帳號被多個使用者同時登入的的處裡方式的資料 空資料
maam_return_code.invalid_account_name 失敗, 帳號名稱錯誤 空資料
maam_return_code.invalid_account_password 失敗, 帳號密碼錯誤 空資料
maam_return_code.other_user_has_login 失敗, 此帳號已經被其他使用者登入 空資料
maam_return_code.same_account_has_login 失敗, 此系統已經有其他帳號登入 空資料

maaam_request_action.logout
$.rep_code 說明 $.rep_data
maam_return_code.pass 成功 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
maam_return_code.internal_error
maam_return_code.jslib_internal_error
內部錯誤 空資料
maam_return_code.miss_session_key cookie 內沒有 session 資訊 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
maam_return_code.invalid_session_key 無效的 session 資訊 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
maam_return_code.idle_timeout session 閒置超時 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行

maaam_request_action.check
$.rep_code 說明 $.rep_data
maam_return_code.pass session 有效 空資料
maam_return_code.internal_error
maam_return_code.jslib_internal_error
內部錯誤 空資料
maam_return_code.miss_session_key cookie 內沒有 session 資訊 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
maam_return_code.invalid_session_key 無效的 session 資訊 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
maam_return_code.idle_timeout session 閒置超時 網頁導向登入頁面的 JavaScript 程式, 使用 maam_jslib_run_script() 執行
$.rep_data


登入的使用方式 :

步驟-01 : 填入驗證資料.
格式 :
"verify_name=" + $(account-name) + "&" +
"verify_password=" + $(account-password) + "&" +
"multiple_user_active_rule=" + $(multiple-user-active-rule) + "&" +
"same_accout_multiple_active_rule=" + $(same-accout-multiple-active-rule)


$(account-name)
帳號名稱.

$(account-password)
帳號密碼.

$(multiple-user-active-rule)
是否允許多個帳號同時登入系統的處裡方式. [詳細]

$(same-accout-multiple-active-rule)
是否允許同一個帳號被多個使用者同時登入的的處裡方式. [詳細]
注意, 因為判斷的依據是帳號的優先權, 而此處又是登入同一個帳號所以優先權又一樣, 所以在這裡 :
deny_force_kick_inside 行為等同 deny_permission_kick_inside
deny_force_kick_outside 行為等同 deny_permission_kick_outside

步驟-02 : 使用 maam_jslib_account_auth() 處理並判斷回傳值決定處理方式.

範例 :
<html>
<head>
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script language="javascript" type="text/javascript" src="jquery_main.js"></script>
<script language="javascript" type="text/javascript" src="md5.js"></script>
<script language="javascript" type="text/javascript" src="maam_jslib_api.js"></script>
<script type="text/javascript">
function account_login()
{
    var self_maam_jslib, rep_ret, auth_data, error_msg;

    // 安全性考量, 將帳號名稱和帳號密碼使用 MD5 加密.
    auth_data = "verify_name=" + md5($("#name_text").val()) + "&" +
                "verify_password=" + md5($("#password_text").val()) + "&" +
                "multiple_user_active_rule=" +
                maam_limit_multiple_active.allow + "&" +
                "same_accout_multiple_active_rule=" +
                maam_limit_multiple_active.deny_force_kick_inside;

    self_maam_jslib = new maam_jslib_lib_t();
    self_maam_jslib.request_action = maaam_request_action.login;
    self_maam_jslib.request_data = auth_data;
    self_maam_jslib.other_query = "";
    rep_ret = maam_jslib_account_auth(self_maam_jslib);
    if(rep_ret.rep_code < maam_return_code.pass)
    {
        switch(rep_ret.rep_code)
        {
            case maam_return_code.invalid_account_name:
                error_msg = "login fail, invalid name";
                break;
            case maam_return_code.invalid_account_password:
                error_msg = "login fail, invalid password";
                break;
            case maam_return_code.other_user_has_login:
                error_msg = "login fail, other user has login";
                break;
            case maam_return_code.same_account_has_login:
                error_msg = "login fail, same account has login";
                break;
            default:
                error_msg = "call maam_jslib_account_auth() fail" +
                            "[" + rep_ret.rep_code + "]";
        }
        alert(error_msg);
        return;
    }
    maam_jslib_run_script(rep_ret.rep_data);
}
</script>
</head>
<body>
  <input id="name_text" type="text" size="16"><br>
  <input id="password_text" type="text" size="16"><br>
  <button type="button" onclick="account_login()">login</button>
</body>
</html>



登出的使用方式 :

步驟-01 : 使用 maam_jslib_account_auth() 處理並判斷回傳值決定處理方式.

範例 :
<html>
<head>
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script language="javascript" type="text/javascript" src="jquery_main.js"></script>
<script language="javascript" type="text/javascript" src="maam_jslib_api.js"></script>
<script type="text/javascript">
function account_logout()
{
    var self_maam_jslib, rep_ret, error_msg;

    self_maam_jslib = new maam_jslib_lib_t();
    self_maam_jslib.request_action = maaam_request_action.logout;
    self_maam_jslib.request_data = "";
    self_maam_jslib.other_query = "";
    rep_ret = maam_jslib_account_auth(self_maam_jslib);
    if(rep_ret.rep_code < maam_return_code.pass)
    {
        switch(rep_ret.rep_code)
        {
            case maam_return_code.miss_session_key:
            case maam_return_code.invalid_session_key:
                error_msg = "invalid access, please login";
                break;
            case maam_return_code.idle_timeout:
                error_msg = "idle timeout, please re-login";
                break;
            default:
                error_msg = "call maam_jslib_account_auth() fail" +
                            "[" + rep_ret.rep_code + "]";
        }
        alert(error_msg);
    }
    maam_jslib_run_script(rep_ret.rep_data);
}
</script>
</head>
<body>
  <button type="button" onclick="account_logout()">logout</button>
</body>
</html>



檢查 session 是否有效的使用方式 :

帳號登入後, 會有幾種情況導致 session 無效 :
01.  超過一段時間沒操作 (GET, POST), 閒置超時.
02.  被系統踢掉 (人為踢掉, 多個帳號登入, 同帳號多重登入等等).

可以使用檢查 session 的方式檢查是否有效, 檢查 session 會執行的動作.
01.  session 有效的話, 更新系統 session 資料的最後存取時間.
02.  session 無效的話, 回傳頁導向到登入頁面的 JavaScript 程式.

步驟-01 : 使用 maam_jslib_account_auth() 處理並判斷回傳值決定處理方式.

範例 :
<html>
<head>
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<script language="javascript" type="text/javascript" src="jquery_main.js"></script>
<script language="javascript" type="text/javascript" src="maam_jslib_api.js"></script>
<script type="text/javascript">
function account_check()
{
    var self_maam_jslib, rep_ret, error_msg;

    self_maam_jslib = new maam_jslib_lib_t();
    self_maam_jslib.request_action = maaam_request_action.check;
    self_maam_jslib.request_data = "";
    self_maam_jslib.other_query = "";
    rep_ret = maam_jslib_account_auth(self_maam_jslib);
    if(rep_ret.rep_code < maam_return_code.pass)
    {
        switch(rep_ret.rep_code)
        {
            case maam_return_code.miss_session_key:
            case maam_return_code.invalid_session_key:
                error_msg = "invalid access, please login";
                break;
            case maam_return_code.idle_timeout:
                error_msg = "idle timeout, please re-login";
                break;
            default:
                error_msg = "call maam_jslib_account_auth() fail" +
                            "[" + rep_ret.rep_code + "]";
        }
        alert(error_msg);
        maam_jslib_run_script(rep_ret.rep_data);
    }
}
</script>
</head>
<body>
  <button type="button" onclick="account_check()">check</button>
</body>
</html>



搭配 MintCM 使用的注意事項 :

MintCM 和 MintAAM 的回傳值 (錯誤部分) 的範圍 :
mcm_return_code.daemon_internal_error
~
mcm_return_code.boundary
屬於 MintCM 程式的錯誤值範圍
maam_return_code.internal_error
~
maam_return_code.boundary
屬於 MintAAM 的錯誤值範圍
mcm_return_code.module_internal_error
~
屬於 MintCM 內部模組的錯誤值範圍

使用下列 MintCM 函式要注意, 如果回傳的錯誤值是屬於 MintAAM, 則要另外處理.
mcm_jslib_obtain_max_count() [取得 group 的最大資料筆數限制]
mcm_jslib_obtain_config() [取得資料]
mcm_jslib_submit_config() [設定資料]
mcm_jslib_upload() [上傳 form 資料]

例如 :
rep_ret = ...;
if(rep_ret.rep_code < mcm_return_code.pass)
{
    // 屬於 MintAAM 的範圍.
    if((maam_return_code.internal_error >= rep_ret.rep_code) &&
       (rep_ret.rep_code >= maam_return_code.boundary))
    {
        switch(rep_ret.rep_code)
        {
            case maam_return_code.miss_session_key:
            case maam_return_code.invalid_session_key:
                error_msg = "invalid access, please login";
                break;
            case maam_return_code.idle_timeout:
                error_msg = "idle timeout, please re-login";
                break;
            default:
                error_msg = "call ...() fail [auth]" +
                            "[" + rep_ret.rep_code + "]";
        }
    }
    // 屬於 MintCM 的範圍.
    else
    {
       error_msg = "call ...() fail" +
                   "[" + rep_ret.rep_code + "]";
    }
    alert(error_msg);
    mcm_jslib_run_script(rep_ret.rep_data);
    return;
}



系統端

系統端部分程式需要客製修改.


設定-01 : 網頁檔使用的副檔名.
mint_aam/maam_build/maam_custom.c
// 分別是副檔名的名稱和長度, 如果不是則需要修改.
#define MAAM_HTML_KEY ".html"
#define MAAM_HTML_LEN 5



設定-02 : 登入頁面和登入後主要頁面的路徑.
mint_aam/maam_build/maam_custom.c
// 以 mini_httpd.conf 中 dir=... 的位置為基準.
#define MAAM_PAGE_LOGIN "/login.html"
#define MAAM_PAGE_INDEX "/index.html"



設定-03 : 在 GET 時, 哪些網頁不用登入也允許讀取 (例如登入頁面).
列表 :
mint_aam/maam_build/maam_custom.c
struct maam_access_t maam_access_allow_get_html_list[] =
{
    {MAAM_PAGE_LOGIN, 0, MAAM_CACCESS_ALL, NULL, 0, 0},
    {NULL, 0, 0, NULL, 0, 0}
};


[struct maam_access_t maam_access_allow_get_html_list[]]
結構成員
char *
cmp_path_con
要和路徑部分 (path) 比對的字串
size_t
cmp_path_len
cmp_path_con 的長度
size_t
cmp_path_method
要和路徑部分比對的方法
MAAM_COMPARE_ACCESS_METHOD
(mint_aam/mcm_lib/maam_buildin/maam_local.h)
MAAM_CACCESS_NONE 不比對, 直接認定匹配. (使用此方法 cmp_path_con, cmp_path_len) 無作用
MAAM_CACCESS_ALL 路徑部分和比對的字串需要完全相同 (使用此方法 cmp_path_len) 無作用
MAAM_CACCESS_PREFIX 路徑部分的頭部往後 cmp_path_len 個字元需要和比對的字串相同
MAAM_CACCESS_POSTFIX 路徑部分的尾部往前 cmp_path_len 個字元需要和比對的字串相同
MAAM_CACCESS_SUB 比對部分的字串是路徑部分的子字串 (使用此方法 cmp_path_len) 無作用
char *
cmp_query_con
要和查詢部分 (query) 比對的字串
size_t
cmp_query_len
cmp_query_con 的長度
size_t
cmp_query_method
要和 GET 的查詢部分比對的方法
MAAM_COMPARE_ACCESS_METHOD
(mint_aam/mcm_lib/maam_buildin/maam_local.h)
MAAM_CACCESS_NONE 不比對, 直接認定匹配. (使用此方法 cmp_query_con, cmp_query_len) 無作用
MAAM_CACCESS_ALL 查詢部分和比對的字串需要完全相同 (使用此方法 cmp_query_len) 無作用
MAAM_CACCESS_PREFIX 查詢部分的頭部往後 cmp_query_len 個字元需要和比對的字串相同
MAAM_CACCESS_POSTFIX 查詢部分的尾部往前 cmp_query_len 個字元需要和比對的字串相同
MAAM_CACCESS_SUB 比對的字串是查詢部分的子字串 (使用此方法 cmp_query_len) 無作用
注意事項 :
01.  cmp_query_con 設 NULL 表示不比對查詢部分.
02.  會先處理先 cmp_path_con, 成立才會處理 cmp_query_con.

注意事項 :
01.  至少要填登入網頁.
02.  最後一組必須是 {NULL, 0, 0, NULL, 0, 0}.
03.  未登入時讀取非允許的網頁檔會重導向到登入頁面.

範例 :
struct maam_access_t maam_access_allow_get_html_list[] =
{
    // 網頁 "/login.html" 允許存取.
    {MAAM_PAGE_LOGIN, 0, MAAM_CACCESS_ALL, NULL, 0, 0},

    // 目錄 "/debug/" 以下的網頁允許存取.
    {"/debug/", 7, MAAM_CACCESS_PREFIX, NULL, 0, 0},

    // 檔名結尾是 "guest.html" 的網頁允許存取.
    {"guest.html", 10, MAAM_CACCESS_POSTFIX, NULL, 0, 0},

    // 不管存取的網頁為何, GET 的查詢字串中帶有 "open" 關鍵字就允許存取.
    {"", 0, MAAM_CACCESS_NONE, "open", 0, MAAM_CACCESS_SUB},

    {NULL, 0, 0, NULL, 0, 0}
};



設定-04 : 瀏覽器在 GET 時, 哪些非網頁檔在未登入情況下禁止存取.
預設情況下, 在還沒登入時 GET 非網頁檔是允許的 (如 CSS, JS, 圖片檔等等), 可以設定哪些檔案登入後才能存取.
列表 :
mint_aam/maam_build/maam_custom.c
struct maam_access_t maam_access_deny_get_other_list[] =
{
    {NULL, 0, 0, NULL, 0, 0}
};


設定方法和 maam_access_allow_get_html_list[] 一樣 [詳細].

注意事項 :
01.  最後一組必須是 {NULL, 0, 0, NULL, 0, 0}.
02.  還沒登入就存取禁止的非網頁檔會回傳 HTTP 404.

範例 :
struct maam_access_t maam_access_allow_get_html_list[] =
{
    // 系統的設定檔 "/system.cfg" 登入後才能下載.
    {"/system.cfg", 11, MAAM_CACCESS_ALL, NULL, 0, 0},

    {NULL, 0, 0, NULL, 0, 0}
};



設定-05 : 在 POST 時, 哪些項目不用登入也允許使用.
列表 :
mint_aam/maam_build/maam_custom.c
struct maam_access_t maam_access_allow_post_list[] =
{
    {NULL, 0, 0, NULL, 0, 0}
};


設定方法和 maam_access_allow_get_html_list[] 一樣 [詳細].

注意事項 :
01.  最後一組必須是 {NULL, 0, 0, NULL, 0, 0}.
02.  還沒登入就使用禁止的項目會回傳導向登入頁面的 JavaScript 程式.

範例 :
struct maam_access_t maam_access_allow_post_list[] =
{
    // 使用 "/cgi/mcm_cgi_config.cgi" 存取設定時, 如果查詢字串的尾端有 "anyone" 關鍵字就允許使用. 
    {"/cgi/mcm_cgi_config.cgi", 0, MAAM_CACCESS_ALL, "anyone", 6, MAAM_CACCESS_POSTFIX},

    {NULL, 0, 0, NULL, 0, 0}
};



設定-06 : 實作帳號驗證部分.
函式 :
mint_aam/maam_build/maam_custom.c
int maam_verify_account(
    struct maam_login_t *login_info,
    int *verify_result_buf)
{
    int fret = MAAM_RCODE_PASS, cret = MAAM_RCODE_INTERNAL_ERROR;

    ...

    *verify_result_buf = cret;
    return fret;
}


參數的用途 :
參數 說明
struct maam_login_t *
login_info
登入的資料以及建立 session 需要的資料, 登入的資料部分用來做帳號驗證, session 需要的資料需要在帳號驗證成功後給予
int *
verify_result_buf
紀錄帳號驗證是否成功的緩衝

[struct maam_login_t *login_info]
結構成員
usockaddr *
client_addr
登入的資料, 客戶端的位址
char *
verify_name
登入的資料, 帳號名稱
char *
verify_password
登入的資料, 帳號密碼
char
account_name[MAAM_BSIZE_ACCOUNT_NAME]
session 需要的資料, 帳號名稱
int
account_permission
session 需要的資料, 帳號的權限 (值越小代表越高)
long
account_idle_timeout
session 需要的資料, 帳號的閒置超時時間

[fret]
用來表示處理帳號驗證時是否發生問題, 例如透過 MintCM 取得帳號資料時, 函數呼叫發生錯誤.
可以設定的值 :
MAAM_RCODE_PASS 處理過程沒有發生錯誤
< MAAM_RCODE_PASS 處理過程發生錯誤

[cret]
用來表示帳號名稱和帳號密碼是否正確.
可以設定的值 :
MAAM_RCODE_PASS 帳號正確
MAAM_RCODE_INVALID_ACCOUNT_NAME 帳號名稱錯誤
MAAM_RCODE_INVALID_ACCOUNT_PASSWORD 帳號密碼錯誤

如果網頁端傳送的是加密後的資料, 在系統端也需要先將帳號資料加密後在比對.
maam_md5_hash
將資料做 MD5 加密.
參數 說明
void *
data_con
要加密的資料
size_t
data_len
要加密的資料的長度
char *
out_buf
紀錄小寫字串格式的加密結果的緩衝
size_t
out_size
out_buf 的大小

範例 :
int maam_verify_account(
    struct maam_login_t *login_info,
    int *verify_result_buf)
{
    int fret = MAAM_RCODE_PASS, cret = MAAM_RCODE_INTERNAL_ERROR;

    // 紀錄 MD5 加密後的字串的緩衝.
    char hash_code[MAAM_BSIZE_MD5_HASH];

    // 存取 MintCM 需要的資料.
    char *path1, path2[MCM_PATH_MAX_LENGTH];
    struct mcm_lulib_lib_t self_lulib;
    struct mcm_dv_device_web_account_t account_v;
    MCM_DTYPE_EK_TD account_count, i;


    // 使用 MintCM.
    // device.web.account.* 紀錄帳號的資料.
    self_lulib.socket_path = "@mintcm";
    self_lulib.call_from = MCM_CFROM_USER;
    self_lulib.session_permission = MCM_SPERMISSION_RO;
    self_lulib.session_stack_size = 0;
    if(mcm_lulib_init(&self_lulib) < MCM_RCODE_PASS)
    {
        MAAM_EMSG("call mcm_lulib_init() fail");
        fret = MAAM_RCODE_INTERNAL_ERROR;
        goto FREE_01;
    }

    // 讀出 device.web.account.* 的資料筆數.
    path1 = "device.web.account.*";
    if(mcm_lulib_get_count(&self_lulib, path1, &account_count) < MCM_RCODE_PASS)
    {
        MAAM_EMSG("call mcm_lulib_get_count(%s) fail", path1);
        fret = MAAM_RCODE_INTERNAL_ERROR;
        goto FREE_02;
    }

    // 網頁端傳送的帳號名稱和帳號密碼都經過 MD5 加密, 所以這邊也需要先對資料加密在比對.

    for(i = 0; i < account_count; i++)
    {
        // 讀出帳號資料.
        snprintf(path2, sizeof(path2), "device.web.account.@" MCM_DTYPE_EK_PF, i + 1);
        if(mcm_lulib_get_entry(&self_lulib, path2, &account_v) < MCM_RCODE_PASS)
        {
            MAAM_EMSG("call mcm_lulib_get_entry(%s) fail", path2);
            fret = MAAM_RCODE_INTERNAL_ERROR;
            goto FREE_02;
        }

        // 使用 MD5 處理帳號名稱並比對.
        maam_md5_hash(account_v.name, strlen(account_v.name),
                      hash_code, sizeof(hash_code));
        if(strcmp(login_info->verify_name, hash_code) == 0)
        {
            // 使用 MD5 處理帳號密碼並比對.
            maam_md5_hash(account_v.password, strlen(account_v.password),
                          hash_code, sizeof(hash_code));
            if(strcmp(login_info->verify_password, hash_code) == 0)
            {
                // 帳號名稱和帳號密碼都正確.
                MAAM_BDMSG("login pass [%s]", account_v.name);
                break;
            }
            else
            {
                // 帳號密碼錯誤.
                MAAM_BDMSG("login fail [%s], invalid password", account_v.name);
                cret = MAAM_RCODE_INVALID_ACCOUNT_PASSWORD;
                goto FREE_02;
            }
        }
    }
    if(i >= account_count)
    {
        // 帳號名稱錯誤.
        MAAM_BDMSG("login fail, invalid name");
        cret = MAAM_RCODE_INVALID_ACCOUNT_NAME;
        goto FREE_02;
    }

    // 驗證成功, 填充 session 需要的資料.
    snprintf(login_info->account_name, sizeof(login_info->account_name), "%s", account_v.name);
    login_info->account_permission = account_v.permission;
    login_info->account_idle_timeout = account_v.idle_timeout;

    // 設定帳號驗證正確.
    cret = MAAM_RCODE_PASS;
FREE_02:
    mcm_lulib_exit(&self_lulib);
FREE_01:
    *verify_result_buf = cret;
    return fret;
}



上述是基本的修改, 另外還有一些額外的部分視需要才要修改.


額外-01 : 共享記憶體的 key 值.
session 的資料會放在共享記憶體內, key 值定義在 :
mint_aam/maam_build/maam_common.h
#define MAAM_SHARE_MEMORY_KEY 518276493



額外-02 : 共享記憶體的檔案互斥鎖的路徑 (此路徑必須可讀寫檔案).
存取 session 的資料必須使用互斥鎖保護避免多程式同時存取, 這邊使用 flock() 做為互斥鎖 :
mint_aam/maam_build/maam_common.h
#define MAAM_MUTEX_PATH "/var/run/maam_mutex"



額外-03 : 最大的 session 數目.
最大允許的已登入的使用者數目, 定義在 :
mint_aam/maam_build/maam_common.h
#define MAAM_MAX_SESSION 8



額外-04 : 權限的比對方式.
在比對權限時 [詳細], 數值越低權限越高, 可以修改比對方式, 定義在 :
mint_aam/maam_build/maam_handle.c
// A 的權限是否高於等於 B.
#define MAAM_PERMISSION_HEIGHT_EQUAL(a, b) ((a) <= (b))
// A 的權限是否等於 B.
#define MAAM_PERMISSION_EQUAL(a, b) ((a) == (b))
// A 的權限是否低於 B.
#define MAAM_PERMISSION_LOW(a, b) ((a) > (b))



範例程式的使用

01.  範例程式目錄在 mint_cm/usage/example/1002.


02.  下面關於 make 的操作沒有特別註明的話都是在 mint_cm 目錄.


03.  第一次使用, 使用 make example_add KEY=1002 載入範例並編譯.


04.  web_app 是範例程式.

範例項目 :
case-01 測試一般存取
case-02 測試上傳檔案
case-03 測試 session 是否有效
case-04 測試登出


05.  先執行 mcm_daemon 和 mini_httpd 才可測試.


06.  瀏覽器連至 http://<server-address> 會自動導到登入頁面.


07.  測試完畢不使用後, 使用 make example_del KEY=1002 將範例移除.


08.  範例程式目錄下的檔案在做完 make example_add 後會複製到真正使用的位置, 要修改做測試的話要改在複製後的.
來源 profile/mcm_data_profile_1002.xml
目地 mint_cm/mcm_build/mcm_data_profile.xml
資料模型範例
有修改要使用 make all 重新編譯
來源 profile/mcm_store_profile_default_1002.txt
目地 mint_cm/mcm_build/mcm_store_profile_default.txt
資料預設值範例
使用 make all 後會再複製到 mint_cm/run
來源 web_app
目地 mint_cm/run/web
網頁程式範例
來源 module/mcm_module_1002.c
目地 mint_cm/mcm_daemon/mcm_module
內部模組範例
有修改要使用 make all 重新編譯
來源 cgi/mcm_cgi_upload_custom.c
目地 mint_cm/mcm_cgi
CGI 端處理檔案上傳範例
有修改要使用 make all 重新編譯
來源 maam_buildin
目地 http_server/mini_httpd/last/mint_aam/maam_buildin
MintAAM 端範例範例
有修改要使用 make all 重新編譯
來源 mini_httpd/Makefile
目地 http_server/mini_httpd/last
mini_httpd 的 Makefile, 主要是加入使用 MintCM 函式庫的連結
有修改要使用 make all 重新編譯