• 偷懒小工具


    目的 

    目的很明确,就是搭建单点登录的帮助类,并且是一贯的极简风格(调用方法保持5行以内)。

    并且与其他类库,关联性降低。所以,不使用WebAPI或者WebService等。

    思路

     

    因为上次有朋友说,光看见一堆代码,看不见具体思路。所以,这次分享,我把思路先写出来。

    懒得看实现代码的朋友,可直接查看“思路”这个子标题。

    同时如果有好的想法,请修改后在github上推给我。Talk is cheap,Show me the code

    思路

     

    同域

    同域需要考虑的问题比较少。只需要考虑,MVC和WebForm的Request如何获取即可。

    实现流程图如下

    1. 因为是使用同样的Cookie所以名称和加密方式必须一致。

    2. 需要设置登录成功后,回跳的网址。因为Forms身份认证的ReturnURL不能获得请求原网址。

    3. 剩下的就如图所示了。不明白的可以追问,我就不细说了。

    跨域

    跨域除了需要考虑同域的问题外,还需要考虑状态共享。因为同源策略问题,故此使用JSONP。

    1. 因为不是Cookie共享,所以只需要设置相同的加密方法即可。

    2. 需要在认证网站,添加可登录的其他网站集合,使用逗号分隔。

    3. 需要在其他网站,创建一个Login页面并调用帮助类的验证方法。配置认证网站URL。

    4. 当认证网站登录成功后,会根据配置的其他网站,给他们发送JSONP请求,让他们自动登录。

    5. 注销同理。JSONP请求方式,可参考这篇文章:jsonp详解。使用的就是添加js标签的方式。

    至此,思路说明结束。不明白的可以追问。

     

    详细设计

    简介

     

    整个类库格式如下,我尽量进行了重构,让各位看着方便一些。因为懒所以只是尽量重构。

    SSO.js:跨域单点登录,需要在登录页面引用的Javascript脚本。

    SSOCrossDomain:跨域帮助类

    SSOSameDomain:同域帮助类

    App.config:跨域帮助类,涉及到的配置示例

    需要在认证网站和其他网站中,同时引用这个类。并根据自己的需求,看调用哪个帮助类。

    使用方法

    首先,我们创建如下结构的解决方案来进行演示。

    Authorize:是WebForm的认证网站,使用MVP的PV模式搭建。其他的均为需要共享的网站。

    MVC1:是MVC的认证网站。认证网站均实现了,最简单的登录功能。

    同域

    首先说一下同域如何使用。

    1. 我们需要配置相同的身份验证。那么我们在Web.Config中,写上如下代码。

    <system.web>

        <compilation debug="true" targetFramework="4.6.1" />

        <authentication mode="Forms">

          <forms loginUrl="~/Login.aspx" name="CookiesTest" cookieless="UseCookies"></forms>

        </authentication>

        <authorization>

          <deny users="?" />

        </authorization>

        <machineKey validationKey="5029E82E1779497186D46F83D78FAD3211D46F83D78FAD" validation="SHA1" decryptionKey="5029E82E1779497186D46F83D78FAD3211D46F83D78FAD" decryption="DES" />

      </system.web>

    <system.web>

        <compilation debug="true" targetFramework="4.6.1" />

        <authentication mode="Forms">

          <forms loginUrl="http://localhost:51666/Login.aspx?link=http://localhost:56757/WebForm1.aspx" name="CookiesTest" cookieless="UseCookies"></forms>

          <!--<forms loginUrl="~/Login.aspx" name="CookieWeb1" cookieless="UseCookies"></forms>-->

        </authentication>

        <authorization>

          <deny users="?" />

        </authorization>

        <machineKey validationKey="5029E82E1779497186D46F83D78FAD3211D46F83D78FAD" validation="SHA1" decryptionKey="5029E82E1779497186D46F83D78FAD3211D46F83D78FAD" decryption="DES" />

      </system.web>

    配置东西分别为:Forms认证,禁止匿名用户访问,配置单点登录加密方式。 

    其中Web1的Forms认证,指向的就是Authorize,并且使用link当做后缀,进行成功后跳转。

    2. 需要在Authorize网站中,添加登录页面,并添加登录后的调用方法。

    /// <summary>

    /// 用户登录方法

    /// </summary>

    private void LoginView_Submit(object sender, AuthorizeEventArgs e)

    {

        string userName = LoginView.UserName;

        string password = LoginView.Password;

        if (ValidationUserInfo(userName, password))

        {

            //同域单点登录

            SSOSameDomain sso = new SSOSameDomain(e.Page);

            sso.LogIn("CookiesTest", new TimeSpan(0, 1, 0), userName);

            ////跨域单点登录

            //SSOCrossDomain cross = new SSOCrossDomain(e.Page);

            //cross.LogIn("CookiesTest", new TimeSpan(0, 1, 0), userName);

        }

    }

    SSOSameDomain,分别可以接受Page和HttpContextBase,作为读取Request的媒介。

    所以各位如果不用MVP,可实例化时直接this。

    LogIn登录方法,需要传递配置的Cookie名称、过期时间和需要保存的内容。

    3. 配置注销功能,在点击注销后,执行如下方法。

    protected void SignOut_Click(object sender, EventArgs e)

    {

                new SSOSameDomain(this).LogOut();

                //new SSOCrossDomain(this).LogOut();

    }

    4. 获取用户内容,可以调用帮助类的GetUserData方法。传递Cookie名称,即可获取对应内容。

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

        {

            if (User.Identity.IsAuthenticated)

            {

                var result = new SSOSameDomain(this).GetUserData("CookiesTest");

                txtUserData.Text = result;

                //SSOCrossDomain cross = new SSOCrossDomain(this);

                //txtUserData.Text = cross.GetUserData("CookieWeb1");

            }

        }

    }

    至此,我们已经完成了同域的单点登录。

    跨域

    跨域因为需要验证,所以会比同域操作多几步。注意:每个网站都必须有类似Login.aspx页面用作登录存储。

    1. 首先配置相同的加密方式,因为我们的JSONP传递的是密文,所以解密方式必须一致。

    <system.web>

        <compilation debug="true" targetFramework="4.6.1" />

        <authentication mode="Forms">

          <forms loginUrl="~/Login.aspx" name="CookiesTest" cookieless="UseCookies"></forms>

        </authentication>

        <authorization>

          <deny users="?" />

        </authorization>

        <machineKey validationKey="5029E82E1779497186D46F83D78FAD3211D46F83D78FAD" validation="SHA1" decryptionKey="5029E82E1779497186D46F83D78FAD3211D46F83D78FAD" decryption="DES" />

      </system.web>

    其他网站的Forms认证页面,都指向本地的Login.aspx。注意加密方式必须一致,不然无法解密。

    2. 认证网站设置可登录的网址集合,在配置文件中添加集合,使用逗号分隔。

    <appSettings>

        <add key="LoginUrl" value="http://localhost:56757/Login.aspx,http://localhost/Web2/Login.aspx" />

      </appSettings>

    3. 其他网站设置统一认证的网址,并添加成功后跳转的地址。

    <appSettings>

        <add key="AuthorizeUrl" value="http://localhost:51666/Login.aspx?link=http://localhost:56757/WebForm1.aspx" />

      </appSettings>

    至此,配置结束,我们接下来说一下如何调用。

    4. 认证网站,添加验证登录和登录方法

    public void Initialize(Page page)

    {

            SSOCrossDomain cross = new SSOCrossDomain(page);

            cross.ValidationLogIn("CookiesTest", new TimeSpan(0, 1, 0));

    }

    ///<summary>

    /// 用户登录方法

    /// </summary>

    private void LoginView_Submit(object sender, AuthorizeEventArgs e)

    {

          string userName = LoginView.UserName;

          string password = LoginView.Password;

          if (ValidationUserInfo(userName, password))

          {

              ////同域单点登录

              //SSOSameDomain sso = new SSOSameDomain(e.Page);

              //sso.LogIn("CookiesTest", new TimeSpan(0, 1, 0), userName);

              //跨域单点登录

              SSOCrossDomain cross = new SSOCrossDomain(e.Page);

              cross.LogIn("CookiesTest", new TimeSpan(0, 1, 0), userName);

          }

    }

    Initialize:是Login.aspx页面初始化执行的方法,我们调用帮助类的

    ValidationLogin,验证是否登录。

    Login:调用帮助类的Login方法,可以保存登录状态,并向其他网站进行发送状态。

    5. 其他网站,添加验证登录方法。

    protected void Page_Load(object sender, EventArgs e)

    {

         if (!IsPostBack)

         {

              SSOCrossDomain cross = new SSOCrossDomain(this);

              cross.ValidationLogIn("CookieWeb1", new TimeSpan(0, 2, 0));

          }

    }

    ValidationLogIn :验证登录方法,传递参数:本地存储的Cookie名称,过期时间。

    6. 其他网站,添加注销方法和获取登录内容。

    protected void Page_Load(object sender, EventArgs e)

    {

        if (!IsPostBack)

        {

            if (User.Identity.IsAuthenticated)

            {

                var result = new SSOSameDomain(this).GetUserData("CookiesTest");

                txtUserData.Text = result;

                //SSOCrossDomain cross = new SSOCrossDomain(this);

                //txtUserData.Text = cross.GetUserData("CookieWeb1");

            }

        }

    }

    protected void SignOut_Click(object sender, EventArgs e)

    {

        //new SSOSameDomain(this).LogOut();

        new SSOCrossDomain(this).LogOut();

    }

    至此,我们已经完成了跨域的单点登录。每个调用,不超过5行代码,极简风格。

  • 相关阅读:
    jvm调优
    Spring 事务
    Spring Framework入门介绍
    redis入门介绍
    Spring与SpringMVC重复扫描问题
    跨域相关问题
    Spring MVC介绍
    Servlet、Servlet容器
    获取屏幕宽高
    mybatis中比较符的写法
  • 原文地址:https://www.cnblogs.com/zhangxiaolei521/p/6066700.html
Copyright © 2020-2023  润新知