相思资源网 Design By www.200059.com

前言

最近轮到我在小组晨会来分享知识点,突然想到单点登录,准备来分享下如何实现单点登录,所以有了下文。实现方案以及代码可能写得不是很严谨,有漏洞的地方或者错误的地方欢迎大家指正。  

刚开始头脑中没有思路,直接在博客园里面看看别人是如何来实现的,看了几篇文章发现,发现解决方案有点问题,或者说不算实现了单点登录

名称定义

为了方便说明先说明几个文中出现的名词的含义:

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站了。

简单关系图
.net 单点登录的设计与实践

泳道流程图.net 单点登录的设计与实践

主要逻辑说明

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

标签:
asp.net,单点登录,.net,单点登录,.net,sso单点登录

相思资源网 Design By www.200059.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
相思资源网 Design By www.200059.com

评论“.net 单点登录的设计与实践”

暂无.net 单点登录的设计与实践的评论...

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。