基于C#实现的单点登录

摘要:
那些知道或想探索单点登录的人应该对单点登录有一个大致的了解。我不会在这里过多地阐述单点登录概念。但是,此时,服务器已经具有全局会话。此时,服务器使用服务器生成的令牌直接重定向到客户端。2.上面已经描述了单点登录的过程。接下来,我们将用代码详细再现该过程。1.客户端登录时,检查是否存在本地会话。如果不是,然后重定向到统一认证中心进行登录操作publicoverridevoidOnActionExecuting{varrequest=filterContext.HttpContext.Request;varresponse=filterContext.HttpContext.Response;stringReturnURL=Request.Url.AbsolutionUri;//请求的路径stringPassport=System.Configuration.ConfigurationManager.AppSettings[“服务器”];//服务器端objectisLogin=filterContext上的路径。HttpContext。会话[“isLogin”];//如果(isLogin!

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

单点登录说的通俗一点,就是一处登录(统一认证中心--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#实现的单点登录》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Java后台进行分页参数类封装Tomcat常用的过滤器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

jdk8 新特性stream().map()

1.大写字符串列表 1.1 简单的Java示例将Strings列表转换为大写 TestJava8.java package com.mkyong.java8; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.uti...

redis 在 php 中的应用(key篇)

本文为我阅读了redis参考手册之后结合博友的博客编写,注意 php_redis 和 redis-cli 的区别(主要是返回值类型和参数用法) 目录: KEY(键) DEL EXISTS EXPIRE EXPIREAT keys MOVE PERSIST TTL RANDOMKEY RENAME RENAMENX TYPE SORT KEY(...

c# 获取相对路径(收藏)

c# 获取相对路径一、获取当前文件的路径 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName 获取模块的完整路径,包括文件名。 2. System.Environment.CurrentDirectory 获取和设置当前目录(该进程从中启动的目录)的完全限定目录。 3....

基于JWT的Token登录认证

1.JWT简介         JSON Web Token(缩写 JWT),是目前最流行的跨域认证解决方案。 2.JWT的原理        JWT的原理是,服务器认证以后,生成一个JSON格式的对象,发回给客户端,就像下面这样. { "用户名": "admin", "角色": "超级管理员", "到期时间": "2019-07-13...

java过滤特殊字符的正则表达式

// 过滤特殊字符 public staticString StringFilter(String str) throws PatternSyntaxException { // 只允许字母和数字 // String regEx ="[^a-zA-Z0-9]"; // 清除掉所有特殊字符 String regEx="[`~!@#$%^&*()+...

php string

一.字符串类型        php一共有8中数据类型        4种基本类型            boolean            integer            float(double)            string        2种符合类型            array            object       ...