一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - ASP.NET教程 - ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

2020-04-16 15:03SmartBooks ASP.NET教程

本篇文章主要介紹了ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn),具有一定的參考價(jià)值,有興趣的可以了解一下。

實(shí)驗(yàn)環(huán)境配置

HOST文件配置如下:

127.0.0.1 app.com
127.0.0.1 sso.com

IIS配置如下:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

應(yīng)用程序池采用.Net Framework 4.0

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

注意IIS綁定的域名,兩個(gè)完全不同域的域名。

app.com網(wǎng)站配置如下:

 ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

 sso.com網(wǎng)站配置如下:

memcached緩存:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

 數(shù)據(jù)庫(kù)配置:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

 數(shù)據(jù)庫(kù)采用EntityFramework 6.0.0,首次運(yùn)行會(huì)自動(dòng)創(chuàng)建相應(yīng)的數(shù)據(jù)庫(kù)和表結(jié)構(gòu)。

授權(quán)驗(yàn)證過(guò)程演示:

在瀏覽器地址欄中訪問(wèn):http://app.com,如果用戶(hù)還未登陸則網(wǎng)站會(huì)自動(dòng)重定向至:http://sso.com/passport,同時(shí)通過(guò)QueryString傳參數(shù)的方式將對(duì)應(yīng)的AppKey應(yīng)用標(biāo)識(shí)傳遞過(guò)來(lái),運(yùn)行截圖如下:

URL地址:http://sso.com/passport?appkey=670b14728ad9902aecba32e22fa4f6bd&username=

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

 輸入正確的登陸賬號(hào)和密碼后,點(diǎn)擊登陸按鈕系統(tǒng)自動(dòng)301重定向至應(yīng)用會(huì)掉首頁(yè),毀掉成功后如下所示:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

 由于在不同的域下進(jìn)行SSO授權(quán)登陸,所以采用QueryString方式返回授權(quán)標(biāo)識(shí)。同域網(wǎng)站下可采用Cookie方式。由于301重定向請(qǐng)求是由瀏覽器發(fā)送的,所以在如果授權(quán)標(biāo)識(shí)放入Handers中的話(huà),瀏覽器重定向的時(shí)候會(huì)丟失。重定向成功后,程序自動(dòng)將授權(quán)標(biāo)識(shí)寫(xiě)入到Cookie中,點(diǎn)擊其他頁(yè)面地址時(shí),URL地址欄中將不再會(huì)看到授權(quán)標(biāo)示信息。Cookie設(shè)置如下:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

登陸成功后的后續(xù)授權(quán)驗(yàn)證(訪問(wèn)其他需要授權(quán)訪問(wèn)的頁(yè)面):

校驗(yàn)地址:http://sso.com/api/passport?sessionkey=xxxxxx&remark=xxxxxx

返回結(jié)果:true,false

客戶(hù)端可以根據(jù)實(shí)際業(yè)務(wù)情況,選擇提示用戶(hù)授權(quán)已丟失,需要重新獲得授權(quán)。默認(rèn)自動(dòng)重定向至SSO登陸頁(yè)面,即:http://sso.com/passport?appkey=670b14728ad9902aecba32e22fa4f6bd&[email protected] 同時(shí)登陸頁(yè)面郵箱地址文本框會(huì)自定補(bǔ)全用戶(hù)的登陸賬號(hào),用戶(hù)只需輸入登陸密碼即可,授權(quán)成功后會(huì)話(huà)有效期自動(dòng)延長(zhǎng)一年時(shí)間。

SSO數(shù)據(jù)庫(kù)驗(yàn)證日志:

用戶(hù)授權(quán)驗(yàn)證日志:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

用戶(hù)授權(quán)會(huì)話(huà)Session:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

數(shù)據(jù)庫(kù)用戶(hù)賬號(hào)和應(yīng)用信息:

ASP.NET MVC SSO單點(diǎn)登錄設(shè)計(jì)與實(shí)現(xiàn)代碼

應(yīng)用授權(quán)登陸驗(yàn)證頁(yè)面核心代碼:

 

  1 /// <summary>
  2     ///  公鑰:AppKey
  3     ///  私鑰:AppSecret
  4     ///  會(huì)話(huà):SessionKey
  5     /// </summary>
  6     public class PassportController : Controller
  7     {
  8         private readonly IAppInfoService _appInfoService = new AppInfoService();
  9         private readonly IAppUserService _appUserService = new AppUserService();
 10         private readonly IUserAuthSessionService _authSessionService = new UserAuthSessionService();
 11         private readonly IUserAuthOperateService _userAuthOperateService = new UserAuthOperateService();
 12 
 13         private const string AppInfo = "AppInfo";
 14         private const string SessionKey = "SessionKey";
 15         private const string SessionUserName = "SessionUserName";
 16 
 17         //默認(rèn)登錄界面
 18         public ActionResult Index(string appKey = "", string username = "")
 19         {
 20             TempData[AppInfo] = _appInfoService.Get(appKey);
 21 
 22             var viewModel = new PassportLoginRequest
 23             {
 24                 AppKey = appKey,
 25                 UserName = username
 26             };
 27 
 28             return View(viewModel);
 29         }
 30 
 31         //授權(quán)登錄
 32         [HttpPost]
 33         public ActionResult Index(PassportLoginRequest model)
 34         {
 35             //獲取應(yīng)用信息
 36             var appInfo = _appInfoService.Get(model.AppKey);
 37             if (appInfo == null)
 38             {
 39                 //應(yīng)用不存在
 40                 return View(model);
 41             }
 42 
 43             TempData[AppInfo] = appInfo;
 44 
 45             if (ModelState.IsValid == false)
 46             {
 47                 //實(shí)體驗(yàn)證失敗
 48                 return View(model);
 49             }
 50 
 51             //過(guò)濾字段無(wú)效字符
 52             model.Trim();
 53 
 54             //獲取用戶(hù)信息
 55             var userInfo = _appUserService.Get(model.UserName);
 56             if (userInfo == null)
 57             {
 58                 //用戶(hù)不存在
 59                 return View(model);
 60             }
 61 
 62             if (userInfo.UserPwd != model.Password.ToMd5())
 63             {
 64                 //密碼不正確
 65                 return View(model);
 66             }
 67 
 68             //獲取當(dāng)前未到期的Session
 69             var currentSession = _authSessionService.ExistsByValid(appInfo.AppKey, userInfo.UserName);
 70             if (currentSession == null)
 71             {
 72                 //構(gòu)建Session
 73                 currentSession = new UserAuthSession
 74                 {
 75                     AppKey = appInfo.AppKey,
 76                     CreateTime = DateTime.Now,
 77                     InvalidTime = DateTime.Now.AddYears(1),
 78                     IpAddress = Request.UserHostAddress,
 79                     SessionKey = Guid.NewGuid().ToString().ToMd5(),
 80                     UserName = userInfo.UserName
 81                 };
 82 
 83                 //創(chuàng)建Session
 84                 _authSessionService.Create(currentSession);
 85             }
 86             else
 87             {
 88                 //延長(zhǎng)有效期,默認(rèn)一年
 89                 _authSessionService.ExtendValid(currentSession.SessionKey);
 90             }
 91 
 92             //記錄用戶(hù)授權(quán)日志
 93             _userAuthOperateService.Create(new UserAuthOperate
 94             {
 95                 CreateTime = DateTime.Now,
 96                 IpAddress = Request.UserHostAddress,
 97                 Remark = string.Format("{0} 登錄 {1} 授權(quán)成功", currentSession.UserName, appInfo.Title),
 98                 SessionKey = currentSession.SessionKey
 99             }); 104 
105             var redirectUrl = string.Format("{0}?SessionKey={1}&SessionUserName={2}",
106                 appInfo.ReturnUrl, 
107                 currentSession.SessionKey, 
108                 userInfo.UserName);
109 
110             //跳轉(zhuǎn)默認(rèn)回調(diào)頁(yè)面
111             return Redirect(redirectUrl);
112         }
113     }
 

 

Memcached會(huì)話(huà)標(biāo)識(shí)驗(yàn)證核心代碼:

 

public class PassportController : ApiController
    {
        private readonly IUserAuthSessionService _authSessionService = new UserAuthSessionService();
        private readonly IUserAuthOperateService _userAuthOperateService = new UserAuthOperateService();

        public bool Get(string sessionKey = "", string remark = "")
        {
            if (_authSessionService.GetCache(sessionKey))
            {
                _userAuthOperateService.Create(new UserAuthOperate
                {
                    CreateTime = DateTime.Now,
                    IpAddress = Request.RequestUri.Host,
                    Remark = string.Format("驗(yàn)證成功-{0}", remark),
                    SessionKey = sessionKey
                });

                return true;
            }

            _userAuthOperateService.Create(new UserAuthOperate
            {
                CreateTime = DateTime.Now,
                IpAddress = Request.RequestUri.Host,
                Remark = string.Format("驗(yàn)證失敗-{0}", remark),
                SessionKey = sessionKey
            });

            return false;
        }
    }
 

 

Client授權(quán)驗(yàn)證Filters Attribute

 
public class SSOAuthAttribute : ActionFilterAttribute
    {
        public const string SessionKey = "SessionKey";
        public const string SessionUserName = "SessionUserName";

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var cookieSessionkey = "";
            var cookieSessionUserName = "";

            //SessionKey by QueryString
            if (filterContext.HttpContext.Request.QueryString[SessionKey] != null)
            {
                cookieSessionkey = filterContext.HttpContext.Request.QueryString[SessionKey];
                filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(SessionKey, cookieSessionkey));
            }

            //SessionUserName by QueryString
            if (filterContext.HttpContext.Request.QueryString[SessionUserName] != null)
            {
                cookieSessionUserName = filterContext.HttpContext.Request.QueryString[SessionUserName];
                filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(SessionUserName, cookieSessionUserName));
            }

            //從Cookie讀取SessionKey
            if (filterContext.HttpContext.Request.Cookies[SessionKey] != null)
            {
                cookieSessionkey = filterContext.HttpContext.Request.Cookies[SessionKey].Value;
            }

            //從Cookie讀取SessionUserName
            if (filterContext.HttpContext.Request.Cookies[SessionUserName] != null)
            {
                cookieSessionUserName = filterContext.HttpContext.Request.Cookies[SessionUserName].Value;
            }

            if (string.IsNullOrEmpty(cookieSessionkey) || string.IsNullOrEmpty(cookieSessionUserName))
            {
                //直接登錄
                filterContext.Result = SsoLoginResult(cookieSessionUserName);
            }
            else
            {
                //驗(yàn)證
                if (CheckLogin(cookieSessionkey, filterContext.HttpContext.Request.RawUrl) == false)
                {
                    //會(huì)話(huà)丟失,跳轉(zhuǎn)到登錄頁(yè)面
                    filterContext.Result = SsoLoginResult(cookieSessionUserName);
                }
            }

            base.OnActionExecuting(filterContext);
        }

        public static bool CheckLogin(string sessionKey, string remark = "")
        {
            var httpClient = new HttpClient
            {
                BaseAddress = new Uri(ConfigurationManager.AppSettings["SSOPassport"])
            };

            var requestUri = string.Format("api/Passport?sessionKey={0}&remark={1}", sessionKey, remark);

            try
            {
                var resp = httpClient.GetAsync(requestUri).Result;

                resp.EnsureSuccessStatusCode();

                return resp.Content.ReadAsAsync<bool>().Result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private static ActionResult SsoLoginResult(string username)
        {
            return new RedirectResult(string.Format("{0}/passport?appkey={1}&username={2}",
                    ConfigurationManager.AppSettings["SSOPassport"],
                    ConfigurationManager.AppSettings["SSOAppKey"],
                    username));
        }
    }
 

 

示例SSO驗(yàn)證特性使用方法:

 

[SSOAuth]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
 

 

總結(jié):

從草稿示例代碼中可以看到代碼性能上還有很多優(yōu)化的地方,還有SSO應(yīng)用授權(quán)登陸頁(yè)面的用戶(hù)賬號(hào)不存在、密碼錯(cuò)誤等一系列的提示信息等。在業(yè)務(wù)代碼運(yùn)行基本正確的后期,可以考慮往更多的安全性層面優(yōu)化,比如啟用AppSecret私鑰簽名驗(yàn)證,IP范圍驗(yàn)證,固定會(huì)話(huà)請(qǐng)求攻擊、SSO授權(quán)登陸界面的驗(yàn)證碼、會(huì)話(huà)緩存自動(dòng)重建、SSo服務(wù)器、緩存的水平擴(kuò)展等。

源碼地址:https://github.com/smartbooks/SmartSSO

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/smartbooks/p/3800849.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品免费综合一区视频 | 男人把j放进女人的p里视频 | 久久伊人精品青青草原2021 | www.爱情岛论坛 | 114毛片免费观看网站 | 国产人妖ts在线视频网 | 5x社区在线观看直接进入 | 国偷盗摄自产福利一区在线 | 97蜜桃网| 性吟网 | 日韩欧美一区二区三区视频 | 成人香蕉xxxxxxx| 啊皇上你好大要知画 | 免费十几分视频 | 波多野结衣久久国产精品 | 日韩无砖专区2020在线 | 无人区免费一二三四乱码 | 私人影院免费观看 | boobsmilking流奶水野战 | 好男人好资源在线观看 | 91色+91sesex| 九九热这里只有精品2 | 欧美一级h | 97大香伊在人人线色 | 午夜一级免费视频 | 亚洲国产天堂综合一区 | 欧美视频在线一区二区三区 | 日韩性公交车上xxhd免费 | 91日本| 舔到喷水 | 四虎影院久久 | 国产精品久久久久久久久久久久 | 国产91页 | 青苹果乐园影院在线播放 | 欧美精品综合一区二区三区 | 日日射视频 | 色老板美国在线观看 | 超91精品手机国产在线 | 国产区最新| 99精品国产高清自在线看超 | 韩国三级在线播放 |