基于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
} }
}
基于C#实现的单点登录的更多相关文章
- .NET基于Redis缓存实现单点登录SSO的解决方案[转]
一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...
- .NET基于Redis缓存实现单点登录SSO的解决方案
一.基本概念 最近公司的多个业务系统要统一整合使用同一个登录,这就是我们耳熟能详的单点登录,现在就NET基于Redis缓存实现单点登录做一个简单的分享. 单点登录(Single Sign On),简称 ...
- 前后端分离基于Oauth2的SSO单点登录怎样做?
一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼:本文主要介绍跨域间的 前后端分离 项目怎样实现单点登录,并且与 非前后端分离 的差 ...
- 如何基于Security实现OIDC单点登录?
一.说明 本文主要是给大家介绍 OIDC 的核心概念以及如何通过对 Spring Security 的授权码模式进行扩展来实现 OIDC 的单点登录. OIDC 是 OpenID Connect 的简 ...
- SSO 基于Cookie+fliter实现单点登录(SSO):工作原理
SSO的概念: 单点登录SSO(Single Sign-On)是身份管理中的一部分. SSO的一种较为通俗的定义是:SSO是指訪问同一server不同应用中的受保护资源的同一用户,仅仅须要登录一次,即 ...
- 基于CAS的SSO(单点登录)实例
第一步 部署CAS-Server(服务端) 1.从CAS官方网站(http://developer.jasig.org/cas/)下载最新版本的CAS-Server(当前最新版本cas-server- ...
- SSO 基于Cookie+fliter实现单点登录 实例解析(一)
接上文,SSO的理论讲解,接下来实践实践! 1.使用Cookie解决单点登录 技术点: 1.设置Cookie的路径为setPath("/").即Tomcat的目录下都有效 2.设置 ...
- Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定
一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼.本文主要介绍 同域 和 跨域 两种不同场景单点登录的实现原理,并使用 Spring ...
- 基于cookie的SSO单点登录系统
利用COOKIE实现单点登录功能 近期公司要求帮一个项目实现单点登录功能,在综合考量下决定采用cookie实现,大概的流程如下图所:
- 基于JWT机制的单点登录
使用JWT实现单点登录时,需要注意token时效性.token是保存在客户端的令牌数据,如果永久有效,则有被劫持的可能.token在设计的时候,可以考虑一次性有效或一段时间内有效.如果设置有效时长,则 ...
随机推荐
- Java枚举的用法和原理深入
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10843644.html 一:枚举的用法 1.定义和组织常量 在JDK1.5之前,我们定义常量都是:publi ...
- rhel7学习第五天
管道命令符的功能的确强大!
- css 高度随宽度比例变化
[方案一:padding实现] 原理: 一个元素的 padding,如果值是一个百分比,那这个百分比是相对于其父元素的宽度而言的,padding-bottom 也是如此. 使用 padding-bot ...
- centos定时删除log文件
#!bin/bash #获取年 time=$(date "+%Y") #查找并删除7天前的文件 find /opt/applog/travelsky -type f -mtime ...
- Taro-UI 2.0样式在H5上生效,微信小程序不生效?
答案: https://taro-ui.aotu.io/#/docs/questions taro-ui 自定义样式覆盖小程序组件样式使用到了 globalClass 这个微信小程序特性,由于微信小程 ...
- 2019年底前的web前端面试题初级-web标准应付HR大多面试问题
作者 | Jeskson来源 | 达达前端小酒馆 问:你知道在css中,html的标签元素分多少中不同的类型吗? 答:大体可分三种:1,块状元素,2,内联元素,3,内联块状元素 块级元素:就是每个块级 ...
- java 集合运算
package testjavapro; import java.util.BitSet; public class testjavaa { public static void main(Strin ...
- klass-oop
(1)Klass Klass 简单来说就是 Java 类在 HotSpot 中的 C++ 对等体,主要用于描述对象实例的具体类型.一般 JVM 在加载 class 文件时,会在方法区创建 Klass ...
- [经验分享]ThinkPad笔记本无法进入PE环境
首先参考:https://jingyan.baidu.com/article/72ee561a564358e16138df14.html 可以设置Secure Boot然后重启电脑,按F1重新进入BI ...
- ASP.NET Core使用Docker-Compose实现多容器应用部署
一.需求背景 人生苦短,我用.NET Core!前面的<ASP.NET Core使用Docker进行容器化托管和部署>基础课程我们学习了如何使用Docker来部署搭建ASP.NET Cor ...