如何實(shí)現(xiàn)單點(diǎn)登錄?

單點(diǎn)登錄(Single Sign On)给僵,簡(jiǎn)稱為 SSO毫捣,是比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。SSO的定義是在多個(gè)應(yīng)用系統(tǒng)中帝际,用戶只需要登錄一次就可以訪問所有相互信任的應(yīng)用系統(tǒng)蔓同。——百度百科

下面要介紹的單點(diǎn)登錄的實(shí)現(xiàn)方式是我在業(yè)余項(xiàng)目中自己摸索出來的蹲诀,可能跟主流的實(shí)現(xiàn)方式不一樣斑粱,僅做參考。

假設(shè)我現(xiàn)在有一個(gè)博客服務(wù)和一個(gè)圖片服務(wù)脯爪,我希望只用登錄一次就能使用這兩個(gè)服務(wù)则北。按照傳統(tǒng)的開發(fā)方式,博客服務(wù)自己帶一個(gè)登錄模塊痕慢,圖片服務(wù)自己再帶一個(gè)登錄模塊尚揣,加大了工作量不說,用戶體驗(yàn)也很不好掖举。

那么能不能將登錄模塊剝離出來成為一個(gè)獨(dú)立的鑒權(quán)服務(wù)呢快骗?答案是可以。

鑒權(quán)服務(wù)負(fù)責(zé)用戶的注冊(cè)塔次、登錄方篮、注銷等功能,其他服務(wù)需要鑒權(quán)時(shí)只需跳轉(zhuǎn)到鑒權(quán)服務(wù)励负,完成鑒權(quán)后再跳轉(zhuǎn)回服務(wù)頁(yè)面即可恭取。

下面簡(jiǎn)單介紹具體做法,假設(shè):

  1. 登錄頁(yè)面:https://login.abc.com/sigin.html
  2. 博客服務(wù)頁(yè)面:https://blog.abc.com/index.html
  3. 博客服務(wù)與鑒權(quán)服務(wù)均部署在內(nèi)網(wǎng)中熄守,通過 Web 服務(wù)器反向代理供客戶端訪問
  4. 關(guān)于跨域名共享 Cookie前一篇文章已經(jīng)介紹蜈垮,在此不再贅述

判斷是否已經(jīng)登錄

當(dāng)首次打開博客服務(wù)頁(yè)面時(shí),博客后臺(tái)服務(wù)會(huì)首先判斷用戶是否登錄裕照,關(guān)鍵代碼如下:

var token = Request.Cookies["token"];
var uid = Request.Cookies["uid"];

if (string.IsNullOrEmpty(uid) || string.IsNullOrEmpty(token))
{
    msg = "非法操作";
    return false;
}
HttpWebRequest request = WebRequest.CreateHttp($"http://localhost:5000/api/Session/{uid}/{token}");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (var sr = new StreamReader(response.GetResponseStream()))
{
    var json = sr.ReadToEnd();
    var result = JsonConvert.DeserializeObject<RequestResult>(json);
    if (result.Code == 200)
    {
        return true;
    }
    msg = result.Msg;
    return false;
}

這里假設(shè)鑒權(quán)服務(wù)和博客服務(wù)均部署在內(nèi)網(wǎng)的同一臺(tái)服務(wù)器上攒发,若兩者不在同一臺(tái)服務(wù)器,請(qǐng)修改 localhost 為鑒權(quán)服務(wù)的內(nèi)網(wǎng) IP 即可晋南。

同樣惠猿,由于鑒權(quán)服務(wù)部署于內(nèi)網(wǎng),因此預(yù)先假設(shè)內(nèi)部網(wǎng)絡(luò)是安全的负间,所以直接將 uidtoken 作為 GET 請(qǐng)求參數(shù)進(jìn)行傳遞偶妖。如果對(duì)安全要求性高姜凄,可將該請(qǐng)求修改為 POST 請(qǐng)求。

若用戶已登錄趾访,則直接往下執(zhí)行業(yè)務(wù)流程态秧;若用戶未登錄,則跳轉(zhuǎn)到登錄頁(yè)面扼鞋,并在 url 中帶上登錄成功后的回調(diào)頁(yè)面申鱼,比如:
https://login.abc.com/signin.html?redirect=https://blog.abc.com/index.html

執(zhí)行登錄

跳轉(zhuǎn)到登錄頁(yè)面后,填寫用戶名云头、密碼后向鑒權(quán)服務(wù)發(fā)起登錄請(qǐng)求捐友,鑒權(quán)服務(wù)執(zhí)行登錄驗(yàn)證,若驗(yàn)證通過溃槐,則向客戶端返回登錄成功的信息匣砖,同時(shí)將 uidtoken 寫入 Cookie 返回給客戶端供后續(xù)鑒權(quán)使用,然后客戶端跳轉(zhuǎn)到登錄前頁(yè)面昏滴;若驗(yàn)證失敗猴鲫,則向客戶端返回登錄失敗信息。

var cookieOptions = new CookieOptions
{
    HttpOnly = true,
    Secure = false,
    Domain = "abc.com",
    Path = "/",
    Expires = DateTime.Now.AddDays(7)
};
Response.Cookies.Append("uid", user.Uid, cookieOptions);
Response.Cookies.Append("token", user.Token, cookieOptions);

保持登錄狀態(tài)

為了保持登錄狀態(tài)影涉,可在每次請(qǐng)求時(shí)刷新 token 的時(shí)間戳变隔。

退出登錄

客戶端發(fā)起注銷請(qǐng)求:

$.ajax({
    type: 'DELETE',
    url: 'https://login.abc.com/api/Session',
    xhrFields: { withCredentials: true }, // 發(fā)送憑據(jù)
    dataType: "json",
    success: function (response) {
    },
    error: function (error) {
    }
});

服務(wù)端收到注銷請(qǐng)求后规伐,清理登錄信息:

var uid = Request.Cookies["uid"];
var token = Request.Cookies["token"];
if (!Utils.IsLogon(_context, uid, token, _tokenExpiredTimeMin, out string msg))
{
    return Ok(new RequestResult(StatusCodes.Status401Unauthorized, msg));
}

var user = await _context.Userinfo.FindAsync(uid);
if (user == null)
{
    return Ok(new RequestResult(StatusCodes.Status404NotFound, "用戶不存在"));
}

user.Token = null;
user.Tokenrefreshtime = null;

_context.Entry(user).State = EntityState.Modified;

await _context.SaveChangesAsync();

Response.Cookies.Delete("uid");
Response.Cookies.Delete("token");

return Ok(new RequestResult(StatusCodes.Status200OK, null));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蟹倾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子猖闪,更是在濱河造成了極大的恐慌鲜棠,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件培慌,死亡現(xiàn)場(chǎng)離奇詭異豁陆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吵护,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門盒音,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人馅而,你說我怎么就攤上這事祥诽。” “怎么了瓮恭?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵雄坪,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我屯蹦,道長(zhǎng)维哈,這世上最難降的妖魔是什么绳姨? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮阔挠,結(jié)果婚禮上飘庄,老公的妹妹穿的比我還像新娘。我一直安慰自己谒亦,他們只是感情好竭宰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著份招,像睡著了一般切揭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锁摔,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天廓旬,我揣著相機(jī)與錄音,去河邊找鬼谐腰。 笑死孕豹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的十气。 我是一名探鬼主播励背,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼砸西!你這毒婦竟也來了叶眉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤芹枷,失蹤者是張志新(化名)和其女友劉穎衅疙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸳慈,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饱溢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了走芋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绩郎。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖翁逞,靈堂內(nèi)的尸體忽然破棺而出肋杖,到底是詐尸還是另有隱情,我是刑警寧澤熄攘,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布兽愤,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏浅萧。R本人自食惡果不足惜逐沙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望洼畅。 院中可真熱鬧吩案,春花似錦、人聲如沸帝簇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)丧肴。三九已至残揉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間芋浮,已是汗流浹背抱环。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纸巷,地道東北人镇草。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瘤旨,于是被迫代替她去往敵國(guó)和親梯啤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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