900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 详解ASP.NET MVC SSO单点登录设计实例

详解ASP.NET MVC SSO单点登录设计实例

时间:2021-03-30 15:41:18

相关推荐

详解ASP.NET MVC SSO单点登录设计实例

后端开发|C#.Net教程

,设计,登录

后端开发-C#.Net教程

本篇文章主要介绍了 MVC SSO单点登录设计与实现,具有一定的参考价值,有兴趣的可以了解一下。

澳门新葡京源码下载,ubuntu开机开不开,tomcat404怎么处理,爬虫 假页面,php代码占用cpu过高,丝瓜seolzw

实验环境配置

vc6 串口通信源码下载,ubuntu mpi运行,启动tomcat 地址栏,肯德基餐厅爬虫,php视频加密,天津短视频seo怎么精准获客lzw

HOST文件配置如下:

114系统源码,ubuntu的vi编辑,日志服务器 tomcat,爬虫代码搜索,php批量查询域名注册,seo 友好lzw

127.0.0.1

127.0.0.1

IIS配置如下:

应用程序池采用.Net Framework 4.0

注意IIS绑定的域名,两个完全不同域的域名。

网站配置如下:

网站配置如下:

memcached缓存:

数据库配置:

数据库采用EntityFramework 6.0.0,首次运行会自动创建相应的数据库和表结构。

授权验证过程演示:

在浏览器地址栏中访问:,如果用户还未登陆则网站会自动重定向至:/passport,同时通过QueryString传参数的方式将对应的AppKey应用标识传递过来,运行截图如下:

URL地址:/passport?appkey=670b14728ad9902aecba32e22fa4f6bd&username=

输入正确的登陆账号和密码后,点击登陆按钮系统自动301重定向至应用会掉首页,毁掉成功后如下所示:

由于在不同的域下进行SSO授权登陆,所以采用QueryString方式返回授权标识。同域网站下可采用Cookie方式。由于301重定向请求是由浏览器发送的,所以在如果授权标识放入Handers中的话,浏览器重定向的时候会丢失。重定向成功后,程序自动将授权标识写入到Cookie中,点击其他页面地址时,URL地址栏中将不再会看到授权标示信息。Cookie设置如下:

登陆成功后的后续授权验证(访问其他需要授权访问的页面):

校验地址:/api/passport?sessionkey=xxxxxx&remark=xxxxxx

返回结果:true,false

客户端可以根据实际业务情况,选择提示用户授权已丢失,需要重新获得授权。默认自动重定向至SSO登陆页面,即:/passport?appkey=670b14728ad9902aecba32e22fa4f6bd&username=seo@ 同时登陆页面邮箱地址文本框会自定补全用户的登陆账号,用户只需输入登陆密码即可,授权成功后会话有效期自动延长一年时间。

SSO数据库验证日志:

用户授权验证日志:

用户授权会话Session:

数据库用户账号和应用信息:

应用授权登陆验证页面核心代码:

/// public class PassportController : Controller { private readonly IAppInfoService _appInfoService = new AppInfoService(); private readonly IAppUserService _appUserService = new AppUserService(); private readonly IUserAuthSessionService _authSessionService = new UserAuthSessionService(); private readonly IUserAuthOperateService _userAuthOperateService = new UserAuthOperateService(); private const string AppInfo = "AppInfo"; private const string SessionKey = "SessionKey"; private const string SessionUserName = "SessionUserName"; //默认登录界面 public ActionResult Index(string appKey = "", string username = "") {TempData[AppInfo] = _appInfoService.Get(appKey);var viewModel = new PassportLoginRequest{ AppKey = appKey, UserName = username};return View(viewModel); } //授权登录 [HttpPost] public ActionResult Index(PassportLoginRequest model) {//获取应用信息var appInfo = _appInfoService.Get(model.AppKey);if (appInfo == null){ //应用不存在 return View(model);}TempData[AppInfo] = appInfo;if (ModelState.IsValid == false){ //实体验证失败 return View(model);}//过滤字段无效字符model.Trim();//获取用户信息var userInfo = _appUserService.Get(model.UserName);if (userInfo == null){ //用户不存在 return View(model);}if (userInfo.UserPwd != model.Password.ToMd5()){ //密码不正确 return View(model);}//获取当前未到期的Sessionvar currentSession = _authSessionService.ExistsByValid(appInfo.AppKey, userInfo.UserName);if (currentSession == null){ //构建Session currentSession = new UserAuthSession {AppKey = appInfo.AppKey,CreateTime = DateTime.Now,InvalidTime = DateTime.Now.AddYears(1),IpAddress = Request.UserHostAddress,SessionKey = Guid.NewGuid().ToString().ToMd5(),UserName = userInfo.UserName }; //创建Session _authSessionService.Create(currentSession);}else{ //延长有效期,默认一年 _authSessionService.ExtendValid(currentSession.SessionKey);}//记录用户授权日志_userAuthOperateService.Create(new UserAuthOperate{ CreateTime = DateTime.Now, IpAddress = Request.UserHostAddress, Remark = string.Format("{0} 登录 {1} 授权成功", currentSession.UserName, appInfo.Title), SessionKey = currentSession.SessionKey}); 104 var redirectUrl = string.Format("{0}?SessionKey={1}&SessionUserName={2}", appInfo.ReturnUrl, currentSession.SessionKey, userInfo.UserName);//跳转默认回调页面return Redirect(redirectUrl); } }Memcached会话标识验证核心代码: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("验证成功-{0}", remark),SessionKey = sessionKey }); return true;}_userAuthOperateService.Create(new UserAuthOperate{ CreateTime = DateTime.Now, IpAddress = Request.RequestUri.Host, Remark = string.Format("验证失败-{0}", remark), SessionKey = sessionKey});return false; } }

Client授权验证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 QueryStringif (filterContext.HttpContext.Request.QueryString[SessionKey] != null){ cookieSessionkey = filterContext.HttpContext.Request.QueryString[SessionKey]; filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(SessionKey, cookieSessionkey));}//SessionUserName by QueryStringif (filterContext.HttpContext.Request.QueryString[SessionUserName] != null){ cookieSessionUserName = filterContext.HttpContext.Request.QueryString[SessionUserName]; filterContext.HttpContext.Response.Cookies.Add(new HttpCookie(SessionUserName, cookieSessionUserName));}//从Cookie读取SessionKeyif (filterContext.HttpContext.Request.Cookies[SessionKey] != null){ cookieSessionkey = filterContext.HttpContext.Request.Cookies[SessionKey].Value;}//从Cookie读取SessionUserNameif (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{ //验证 if (CheckLogin(cookieSessionkey, filterContext.HttpContext.Request.RawUrl) == false) {//会话丢失,跳转到登录页面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().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验证特性使用方法:

[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(); } }

总结:

从草稿示例代码中可以看到代码性能上还有很多优化的地方,还有SSO应用授权登陆页面的用户账号不存在、密码错误等一系列的提示信息等。在业务代码运行基本正确的后期,可以考虑往更多的安全性层面优化,比如启用AppSecret私钥签名验证,IP范围验证,固定会话请求攻击、SSO授权登陆界面的验证码、会话缓存自动重建、SSo服务器、缓存的水平扩展等。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。