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

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

    

基于C#实现的单点登录的更多相关文章

  1. .NET基于Redis缓存实现单点登录SSO的解决方案[转]

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  2. .NET基于Redis缓存实现单点登录SSO的解决方案

    一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...

  3. 前后端分离基于Oauth2的SSO单点登录怎样做?

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼:本文主要介绍跨域间的 前后端分离 项目怎样实现单点登录,并且与 非前后端分离 的差 ...

  4. 如何基于Security实现OIDC单点登录?

    一.说明 本文主要是给大家介绍 OIDC 的核心概念以及如何通过对 Spring Security 的授权码模式进行扩展来实现 OIDC 的单点登录. OIDC 是 OpenID Connect 的简 ...

  5. SSO 基于Cookie+fliter实现单点登录(SSO):工作原理

    SSO的概念: 单点登录SSO(Single Sign-On)是身份管理中的一部分. SSO的一种较为通俗的定义是:SSO是指訪问同一server不同应用中的受保护资源的同一用户,仅仅须要登录一次,即 ...

  6. 基于CAS的SSO(单点登录)实例

    第一步 部署CAS-Server(服务端) 1.从CAS官方网站(http://developer.jasig.org/cas/)下载最新版本的CAS-Server(当前最新版本cas-server- ...

  7. SSO 基于Cookie+fliter实现单点登录 实例解析(一)

    接上文,SSO的理论讲解,接下来实践实践! 1.使用Cookie解决单点登录 技术点: 1.设置Cookie的路径为setPath("/").即Tomcat的目录下都有效 2.设置 ...

  8. Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼.本文主要介绍 同域 和 跨域 两种不同场景单点登录的实现原理,并使用 Spring ...

  9. 基于cookie的SSO单点登录系统

    利用COOKIE实现单点登录功能 近期公司要求帮一个项目实现单点登录功能,在综合考量下决定采用cookie实现,大概的流程如下图所:

  10. 基于JWT机制的单点登录

    使用JWT实现单点登录时,需要注意token时效性.token是保存在客户端的令牌数据,如果永久有效,则有被劫持的可能.token在设计的时候,可以考虑一次性有效或一段时间内有效.如果设置有效时长,则 ...

随机推荐

  1. PHP获取当前服务器版本,Ip等详细信息

    1. 服务器IP地址 $_SERVER['SERVER_ADDR'] 服务器域名 $_SERVER['SERVER_NAME'] 服务器端口 $_SERVER['SERVER_PORT'] 服务器版本 ...

  2. 用js怎么来判断我已点击了窗体中“关闭”按钮?

    onbeforeunload 事件在即将离开当前页面(刷新或关闭)时触发. 该事件可用于弹出对话框,提示用户是继续浏览页面还是离开当前页面. 对话框默认的提示信息根据不同的浏览器有所不同,标准的信息类 ...

  3. 利用pandas映射替换两个字典中的映射值

    在公司处理报表,中英文映射表与数值表替换 import pandas as pd data = { "a":"值一", "b":" ...

  4. CF308C-Sereja and Brackets-(线段树+括号匹配)

    题意:给出一段括号,多次询问某个区间内能匹配多少括号. 题解:线段树,结构体三个属性,多余的左括号l,多余的右括号r,能够匹配的括号数val. 当前结点的val=左儿子的val+右儿子的val+min ...

  5. IComparable<T>.CompareTo(T) 方法

    IComparable<T>.CompareTo(T) 方法 定义 命名空间: System 程序集: System.Runtime.dll, mscorlib.dll, netstand ...

  6. KDiff3使用指南

    http://kdiff3.sourceforge.net/ KDiff3 is a diff and merge program that compares or merges two or thr ...

  7. 用bitSet做百万级ip去重

    如果直接将几百万数据仍到bitset,内存是否够用?实际测试,600万ip放到一个bitSet中,jvm内存会爆. 所以,就简单做了下分组,构建一个HashMap<String, BitSet& ...

  8. 机器学习-MNIST数据集-神经网络

    #设置随机种子 seed = 7 numpy.random.seed(seed) #加载数据 (X_train,y_train),(X_test,y_test) = mnist.load_data() ...

  9. selenium篇之滑动验证码

    一.介绍 现在出现了一种通过用户鼠标移动滑块来填补有缺口图片的验证码,我们叫做滑动验证码.它的原理很简单,首先生成一张图片,然后随机挖去一块,在页面展示被挖去部分的图片,再通过js获取用户滑动距离,以 ...

  10. selenium--操作JS弹框

    前戏 我们常见的弹框有三种,一种是alert弹框,一种是prompt弹框,还有一种是confirm弹框那他们有什么不同呢?不同点就是他们长的不一样,alert弹框有一段文字和一个确定按钮,如下 在来看 ...