前言
最近轮到我在小组晨会来分享知识点,突然想到单点登录,准备来分享下如何实现单点登录,所以有了下文。实现方案以及代码可能写得不是很严谨,有漏洞的地方或者错误的地方欢迎大家指正。
刚开始头脑中没有思路,直接在博客园里面看看别人是如何来实现的,看了几篇文章发现,发现解决方案有点问题,或者说不算实现了单点登录
名称定义
为了方便说明先说明几个文中出现的名词的含义:
P站:统一登录授权验证中心,demo中 域名是www.passport.com:801
A站:处于不同域名下的测试网站,demo中 域名是www.a.com:802
B站:处于不同域名下的测试网站,demo中 域名是www.b.com:803
Token:用户访问P站的秘钥
Ticket:用来保存用户信息的加密字符串
单点登录
访问A站需要登陆的就跳转P站中进行登陆,P站登陆之后跳转回至A站,用户再次访问B站需要登陆的页面,用户不需要进行登陆操作就可以正常访问。
实现思路
未登录用户访问A站,首先会重定向跳转至P站授权中心,P站首先通过检测Cookie来判断当前不是处于登陆状态,就跳转至登陆页面进行登陆操作,登陆成功之后把用户信息加密ticket附在A的请求地址上返回,A站通过解密ticket来获取用户信息,解密成功并存进Session中(这样用户在A中就处于登陆状态了),访问通过;当用户再次访问B站的时候,对于B站来说,用户是处于未登录状态,则同样会重定向跳转至P站授权中心,P站检测Cookie,判断当前用户处于登陆状态,就把当前用户信息加密成ticket附在B的请求地址上返回,后面的操作就和A站处理一样;这样都登陆之后再次访问A或者B,A和B中Session中都存储了用户信息,就不会再次请求P站了。
主要逻辑说明
A站主要逻辑
用户首先访问A站,A站中会生成Token,并存入Cache中。Token是A访问P的钥匙,P在回调给A的时候需要携带这个Token。A请求P,P验证Token,P回调A,A检测Token是否是发送出去的Token,验证之后Token即失效,防止Token被再次使用。
Token的生成是通过取时间戳的不同字段进行MD5加密生成,当然这里可以再加个盐进行防伪。
/// <summary> /// 生成秘钥 /// </summary> /// <param name="timestamp"></param> /// <returns></returns> public static string CreateToken(DateTime timestamp) { StringBuilder securityKey = new StringBuilder(MD5Encypt(timestamp.ToString("yyyy"))); securityKey.Append(MD5Encypt(timestamp.ToString("MM"))); securityKey.Append(MD5Encypt(timestamp.ToString("dd"))); securityKey.Append(MD5Encypt(timestamp.ToString("HH"))); securityKey.Append(MD5Encypt(timestamp.ToString("mm"))); securityKey.Append(MD5Encypt(timestamp.ToString("ss"))); return MD5Encypt(securityKey.ToString()); }
P回调A的时候进行,A中对Token进行校验,校验不成功则请求P站统一授权验证。
/// <summary> /// 授权枚举 /// </summary> public enum AuthCodeEnum { Public = 1, Login = 2 } /// <summary> /// 授权过滤器 /// </summary> public class AuthAttribute : ActionFilterAttribute { /// <summary> /// 权限代码 /// </summary> public AuthCodeEnum Code { get; set; } /// <summary> /// 验证权限 /// </summary> /// <param name="filterContext"></param> public override void OnActionExecuting(ActionExecutingContext filterContext) { var request = filterContext.HttpContext.Request; var session = filterContext.HttpContext.Session; //如果存在身份信息 if (Common.CurrentUser == null) { if (Code == AuthCodeEnum.Public) { return; } string reqToken = request["Token"]; string ticket = request["Ticket"]; Cache cache = HttpContext.Current.Cache; //没有获取到Token或者Token验证不通过或者没有取到从P回调的ticket 都进行再次请求P TokenModel tokenModel= cache.Get(ConstantHelper.TOKEN_KEY)==null"authernUrl">统一授权地址</param> /// <param name="returnUrl">回调地址</param> /// <returns></returns> private string GetAuthernScript(string authernUrl, string returnUrl) { StringBuilder sbScript = new StringBuilder(); sbScript.Append("<script type='text/javascript'>"); sbScript.AppendFormat("window.location.href='{0}&returnUrl=' + encodeURIComponent('{1}');", authernUrl, returnUrl); sbScript.Append("</script>"); return sbScript.ToString(); } }
代码说明:这里为了方便设置Token的过期时间,所以使用Cache来存取Token,设定Token的失效时间为两分钟,当验证成功则从cache中移除Token。
调取过滤器
[Auth(Code = AuthCodeEnum.Login)] public ActionResult Index() { return View(); }
P站主要逻辑
P站收到授权请求,P站首先通过Coookie来判断是否登陆,未登录则跳转至登陆页面进行登陆操作。
/// <summary> /// 授权登陆验证 /// </summary> /// <returns></returns> [HttpPost] public ActionResult PassportVertify() { var cookie=Request.Cookies[ConstantHelper.USER_COOKIE_KEY]; if (cookie == null ||string.IsNullOrEmpty(cookie.ToString())) { return RedirectToAction("Login", new { ReturnUrl = Request["ReturnUrl"] ,Token= Request["Token"] }); } string userinfo = cookie.ToString(); var success= passportservice.AuthernVertify(Request["Token"], Convert.ToDateTime(Request["TimeStamp"])); if (!success) { return RedirectToAction("Login", new { ReturnUrl = Request["ReturnUrl"], Token = Request["Token"] }); } return Redirect(passportservice.GetReturnUrl(userinfo, Request["Token"],Request["ReturnUrl"])); }
已登陆则验证Token
/// <summary> /// 验证令牌 /// </summary> /// <param name="token">令牌</param> /// <param name="timestamp">时间戳</param> /// <returns></returns> public bool AuthernVertify(string token,DateTime timestamp) { return AuthernUtil.CreateToken(timestamp) == token; }
测试说明
1、修改host
127.0.0.1 www.passport.com
127.0.0.1 www.a.com
127.0.0.1 www.b.com
2、部署IIS
P www.passport.com:801
A www.a.com:802
B www.b.com:803
3、测试账号和webconfig
<add key="PassportCenterUrl" value="http://www.passport.com:801"/>
用户名:admin 密码:123
demo
下载地址:源码下载地址
原文链接:http://www.cnblogs.com/minesnil-forfaith/p/6062943.html
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 海来阿木《西楼情歌》开盘母带[WAV+CUE][1.1G]
- TheGesualdoSix-QueenofHeartsLamentsandSongsofRegretforQueensTerrestrialandCele
- 王建杰2011-荣华富贵[喜玛拉雅][WAV+CUE]
- 孙悦2024-时光音乐会[金蜂][WAV+CUE]
- 秦宇子.2020-#YUZI【海蝶】【FLAC分轨】
- 苏有朋.1994-这般发生【华纳】【WAV+CUE】
- 小虎队.1990-红蜻蜓【飞碟】【WAV+CUE】
- 雷婷《寂寞烟火HQⅡ》头版限量[低速原抓WAV+CUE][1G]
- 赵传1996《黑暗英雄》台湾首版[WAV+CUE][1G]
- 张敬轩2005《我的梦想我的路》几何娱乐[WAV+CUE][1G]
- 群星《人到四十男儿情(SRS+WIZOR)》[原抓WAV+CUE]
- 马久越《上善若水HQCDII》[低速原抓WAV+CUE]
- 龚玥《女儿情思》6N纯银SQCD【WAV+CUE】
- 张惠妹《你在看我吗》大碟15 金牌大风[WAV+CUE][1G]
- 群星《左耳·听见爱情》星文唱片[WAV+CUE][1G]