• 基于C#实现的单点登录


    了解或想探索单点登录的朋友应该对单点登录有一个大致的了解,在这里我不在过多的阐述单点登录的概念。

    单点登录说的通俗一点,就是一处登录(统一认证中心--Server),处处通行(Client)。

    一、第一步我们先来探讨探讨SSO单点登录的过程

       1.当Client第一次登录时,查看自己有没有局部会话,没有的话,则重定向到统一认证中心进行进行登录操作

       2.登录成功后,Server会保存一个全局会话。并会产生一个token返回给Client

       3.这时又回到了Client,Client拿到Server返回的token并不是直接跳转到正确的页面。而是拿着这个token去Server校验这个token是否是Server产生的,校验通过了才进行跳转,同时生成一个局部会话

       4.当第二个Client登录时,同样也会先跳转到Server。然而此时不同的时,这是Server端已经有了一个全局的会话,此时直接重定向到Client,并带着Server端产生的token

    二、上面已经阐述了单点登录的过程,接下来我们结合着代码详细的复现这一过程

      1.Client登录时,查看自己有没有局部会话,没有的话,则重定向到统一认证中心进行进行登录操作

         public override  void OnActionExecuting(ActionExecutingContext filterContext)
            {
                var request = filterContext.HttpContext.Request;
                var response = filterContext.HttpContext.Response;
    
                string ReturnURL = request.Url.AbsoluteUri;                                             //请求的路径
                string Passport = System.Configuration.ConfigurationManager.AppSettings["Server"];      //Server端的路径
                object isLogin = filterContext.HttpContext.Session["isLogin"];    //局部会话
                
                if (isLogin != null)        //有局部会话的时候直接放行
                {
                    return;     
                }
                else
                {
                    //这一部分是校验Server返回的token,第一次登录的时候没有token,会直接跳过这部分
                }
    
           //执行这步操作 filterContext.Result
    = new RedirectResult(string.Format("{0}/Login/CheckLogin?redirectUrl={1}", Passport,ReturnURL)); //第一次登录时没有局部会话,要跳到Server端进行认证 return; }

       2.跳转到Server端进行校验

            public ActionResult CheckLogin(string redirectUrl) {
                object token = Session["token"];
                if (token==null)
                {
                    string url = "http://localhost:52666/Login/Login?redirectUrl="+redirectUrl;   //跳转到登录界面,并携着跳转过来的路径,以方便后续操作
                    return Redirect(url);
                }
                else
                {
                    return Redirect(redirectUrl+ "?tokenId=" + token.ToString());
                }
            }
            public ActionResult Login(string redirectUrl) 
            {
                ViewBag.Url = redirectUrl;          
                return View();            //返回登录界面的视图
            }

       3.对Server登录界面输入的用户和密码进行校验,登录成功就重定向到Client端

            [HttpPost]
            public ActionResult Login(string userName, string password,string RetrunURL) {
    
                if (userName=="admin"&&password=="admin")           //登录成功
                {
                    Session["token"] = Guid.NewGuid().ToString();       //生成一个全局会话
                    MockDatabase.T_Token.Add(Session["token"].ToString());   //将产生的token写到数据库
                    return Redirect(RetrunURL + "?tokenId=" + Session["token"].ToString());  //重定向到Client端并携带着这个token
                }
                else
                {
                    string url = "http://localhost:52666/Login/Login?redirectUrl=" + RetrunURL;     //否则继续返回到登录界面
                    return Redirect(url);
                }   
            }

       4.这里又跳转到Client的过滤器中,进行对token的校验

      public override  void OnActionExecuting(ActionExecutingContext filterContext)
            {
                var request = filterContext.HttpContext.Request;
                var response = filterContext.HttpContext.Response;
    
                string ReturnURL = request.Url.AbsoluteUri;                                             //请求的路径
                string Passport = System.Configuration.ConfigurationManager.AppSettings["Server"];      //Server端的路径
                object isLogin = filterContext.HttpContext.Session["isLogin"];    //局部会话
                
                if (isLogin != null)        //有局部会话的时候直接放行
                {
                    return;     
                }
                else
                {
              //执行这步操作
    //从Server端跳转到这里,对token进行校验 string token = request["tokenId"]; if (!string.IsNullOrWhiteSpace(token)) { using (HttpClient http = new HttpClient()) { HttpContent httpContent = new StringContent(token); httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); httpContent.Headers.ContentType.CharSet = "utf-8"; //验证Tokend是否有效 HttpClient httpClient = new HttpClient(); string url = Passport + "Login/Verify?token="+token; //带着token请求到Server端的Verify方法进行校验 HttpResponseMessage res = httpClient.GetAsync(url).Result; string result = res.Content.ReadAsStringAsync().Result; if (res.StatusCode.ToString()=="OK") { if (result == "True") { filterContext.HttpContext.Session["isLogin"] = true; return; //通过校验就放行 } } } } } filterContext.Result = new RedirectResult(string.Format("{0}/Login/CheckLogin?redirectUrl={1}", Passport,ReturnURL)); //第一次登录时没有局部会话,要跳到Server端进行认证 return; }

        5.Server端的Verify方法对token进行校验(校验token是否由Server产生的)

          public string Verify(string token) {
                return MockDatabase.T_Token.Contains(token).ToString();   //判断数据库中存入的token,有没有包含传递过来的token
            }

        6、当第二个Client登录时,Server端已经有了全局会话,则直接跳转回去

           public ActionResult CheckLogin(string redirectUrl) {
                object token = Session["token"];
                if (token==null)
                {
                    string url = "http://localhost:52666/Login/Login?redirectUrl="+redirectUrl;   //跳转到登录界面,并携着跳转过来的路径,以方便后续操作
                    return Redirect(url);
                }
                else
                {
             //走这段逻辑
    return Redirect(redirectUrl+ "?tokenId=" + token.ToString()); //当第二个Client登录时,此时已经有了一个全局会话。会直接跳转过去并带上token } }

    三、上面一步一步的操作不是那么完整,这里给出Server端和Client端过滤器的完整代码,希望能对研究这块东西的小伙伴有所帮助

       1.Client端过滤器的代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Web;
    using System.Web.Mvc;
    
    namespace ClientO.Filter
    {
        public class AuthAttribute : ActionFilterAttribute
        {
            public static List<string> Tokens = new List<string>();
            public override  void OnActionExecuting(ActionExecutingContext filterContext)
            {
                var request = filterContext.HttpContext.Request;
                var response = filterContext.HttpContext.Response;
    
                string ReturnURL = request.Url.AbsoluteUri;                                             //请求的路径
                string Passport = System.Configuration.ConfigurationManager.AppSettings["Server"];      //Server端的路径
                object isLogin = filterContext.HttpContext.Session["isLogin"];    //局部会话
                
                if (isLogin != null)        //有局部会话的时候直接放行
                {
                    return;     
                }
                else
                {
                    //从Server端跳转到这里,对token进行校验
                    string token = request["tokenId"];
                    if (!string.IsNullOrWhiteSpace(token))
                    {
                        using (HttpClient http = new HttpClient())
                        {
                            HttpContent httpContent = new StringContent(token);
                            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                            httpContent.Headers.ContentType.CharSet = "utf-8";
                            //验证Tokend是否有效
                            HttpClient httpClient = new HttpClient();
                            
                            string url = Passport + "Login/Verify?token="+token;        //带着token请求到Server端的Verify方法进行校验
                            HttpResponseMessage res = httpClient.GetAsync(url).Result;
                            string result = res.Content.ReadAsStringAsync().Result;
                            if (res.StatusCode.ToString()=="OK")
                            {
                                if (result == "True")
                                {
                                    filterContext.HttpContext.Session["isLogin"] = true;
                                    return;                       //通过校验就放行
                                }
                            }
                        }
                    }
                }
    
                filterContext.Result = new RedirectResult(string.Format("{0}/Login/CheckLogin?redirectUrl={1}", Passport,ReturnURL));   //第一次登录时没有局部会话,要跳到Server端进行认证
                return;
    
            }
        }
    }

        2.Server端Control中的代码

    using Server.Filter;
    using Server.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Security;
    
    namespace Server.Controllers
    {
        public class LoginController : Controller
        {
            // GET: Login
          
            public ActionResult Index()
            {
                return View();
            }
    
            public ActionResult CheckLogin(string redirectUrl) {
                object token = Session["token"];
                if (token==null)
                {
                    string url = "http://localhost:52666/Login/Login?redirectUrl="+redirectUrl;   //跳转到登录界面,并携着跳转过来的路径,以方便后续操作
                    return Redirect(url);
                }
                else
                {
                    return Redirect(redirectUrl+ "?tokenId=" + token.ToString());           //当第二个Client登录时,此时已经有了一个全局会话。会直接跳转过去并带上token
                }
            }
            public ActionResult Login(string redirectUrl) 
            {
                ViewBag.Url = redirectUrl;          
                return View();            //返回登录界面的视图
            }
    
    
            [HttpPost]
            public ActionResult Login(string userName, string password,string RetrunURL) {
    
                if (userName=="admin"&&password=="admin")           //登录成功
                {
                    Session["token"] = Guid.NewGuid().ToString();       //生成一个全局会话
                    MockDatabase.T_Token.Add(Session["token"].ToString());   //将产生的token写到数据库
                    return Redirect(RetrunURL + "?tokenId=" + Session["token"].ToString());  //重定向到Client端并携带着这个token
                }
                else
                {
                    string url = "http://localhost:52666/Login/Login?redirectUrl=" + RetrunURL;     //否则继续返回到登录界面
                    return Redirect(url);
                }   
            }
         public string Verify(string token) {
                return MockDatabase.T_Token.Contains(token).ToString();   //判断数据库中存入的token,有没有包含传递过来的token
            }
    
        }
    }

        

  • 相关阅读:
    hdu 4403 枚举
    hdu 4405概率dp
    lightoj 1036 dp
    lightoj 1033 区间dp
    lightoj 1032 二进制的dp
    hdu 4293 dp求最大权值不重合区间
    poj 2449 第k短路
    hdu 4284 状态压缩
    hdu4281 区间dp
    poj 2288 tsp经典问题
  • 原文地址:https://www.cnblogs.com/HTLucky/p/11799529.html
Copyright © 2020-2023  润新知