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

单点登录说的通俗一点,就是一处登录(统一认证中心--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
} }
}

    

最新文章

  1. Spring 自带的定时任务
  2. [Java入门笔记] Java语言基础(三):运算符
  3. .Net Core 控制台输出中文乱码
  4. 深入理解js——prototype原型
  5. wifi详解(二)
  6. R文件相关(坑)
  7. MongoDB 聚合
  8. JavaScript设计模式之构造器、模块和原型
  9. C# 中的线程安全集合类
  10. java中级——集合框架【3】-HashSet
  11. MyBatis(四):mybatis中使用in查询时的注意事项
  12. 《Python》网络编程基础
  13. VS中的类模板
  14. 转:css知多少(12)——目录
  15. JAVA Iterator 转成 List
  16. 【Centos】【Python3】yum install 报错
  17. DokuWiki 开源wiki引擎程序
  18. SUST OJ 1642: 绝地求生—死亡顺序
  19. ECMAScript 6 Promise 对象
  20. tcp/ip学习笔记-TCP

热门文章

  1. 查看ISTIO-CITADEL的证书信息
  2. bootm跳转到kernel的流程
  3. 201671010450-姚玉婷-实验十四 团队项目评审&amp;课程学习总结
  4. 16-cmake语法-OpeCV3.3.1_CMakeLists.txt的部分注释
  5. VIJOS-P1066 弱弱的战壕
  6. Spring Boot版本号说明
  7. HTML基础三-JS
  8. ESA2GJK1DH1K升级篇: STM32远程乒乓升级,基于(WIFI模块AT指令TCP透传方式),定时访问升级
  9. 联想笔记本上Ubuntu无线网卡问题
  10. PATA1077Kuchiguse