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

单点登录说的通俗一点,就是一处登录(统一认证中心--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. Linux shell 函数应用示例01

    函数Function的使用 定义函数 (1) 函数名称() {     ...     ... } (2) function 函数名称{     ...     ... } 调用函数         ...

  2. CentOS 7 使用Nexus3搭建maven私服

    安装jdk(略) 安装maven wget http://mirrors.hust.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-maven-3. ...

  3. system.exit(int status)中status值不同时的区别

    status为0时为正常退出程序,也就是结束当前正在运行中的java虚拟机. status为非0的其他整数(包括负数,一般是1或者-1),表示非正常退出当前程序. 可以明确的是,无论status是什么 ...

  4. arXiv上传文章latex源码技巧

    <<2019.09.27>>更新 上传PS文件看来也是不行了,一大早收到邮件被arXiv标记为incomplete了.哎,还是老老实实提交Latex source files吧 ...

  5. hive使用beeline配置远程连接

    hive以hadoop集群为基础,提供hdfs的SQL支持: hive一般可以以mysql为元数据存储,默认Derby:hadoop,hive安装自行百度吧: 介绍hive的远程访问: 未配置之前使用 ...

  6. LCD12864

    /* LCD Arduino PIN1 = GND PIN2 = 5V RS(CS) = 8; RW(SID)= 9; EN(CLK) = 3; PIN15 PSB = GND; */ #includ ...

  7. Numpy | 23 文件读写

    Numpy 可以读写磁盘上的文本数据或二进制数据. NumPy 为 ndarray 对象引入了一个简单的文件格式:npy. npy 文件用于存储重建 ndarray 所需的数据.图形.dtype 和其 ...

  8. C++ CGI报“资源访问错误”问题分析

    一线上CGI偶发性会报“资源访问错误”,经过分析得出是因为CgiHost没有读取到CGI的任务输出,即CGI运行完成后连HTTP头都没有一点输出. 然而实际上,不可能没有任何输出,因为CGI至少有无条 ...

  9. Linux下网络socket编程——实现服务器(select)与多个客户端通信

    一.关于socket通信 服务器端工作流程: 调用 socket() 函数创建套接字 用 bind() 函数将创建的套接字与服务端IP地址绑定 调用listen()函数监听socket() 函数创建的 ...

  10. 洛谷 P1816 忠诚 题解

    P1816 忠诚 题目描述 老管家是一个聪明能干的人.他为财主工作了整整10年,财主为了让自已账目更加清楚.要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意.但是由于一些人的挑拨,财 ...