天天看点

Asp.net+Vue+EmelentUI的实现(二)登录验证

在《Asp.net+Vue+EmelentUI的实现(一)框架搭建》一文中实现了简单的框架搭建,现在继续登录验证的实现。我们采用的是Asp.net来构建的,所以首选asp.net的验证机制。

1.web.config的配置

<?xml version="1.0" encoding="utf-8"?>

<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  https://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" executionTimeout="500" maxRequestLength="40960000" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100" />
    <customErrors mode="Off" />
    <authentication mode="Forms">
      <forms loginUrl="/Login/login.aspx" name=".ASPXAUTH" timeout="450" slidingExpiration="true" path="/" />
    </authentication>
    <authorization>
      <allow users="*" />
    </authorization>
  </system.web>
  <location path="Pages">
    <system.web>
      <authorization>
        <allow roles="AspNetVueElementUI" />
        <deny users="*" />
      </authorization>
    </system.web>
  </location>
  <location path="default.aspx">
    <system.web>
      <authorization>
        <allow roles="AspNetVueElementUI" />
        <deny users="*" />
      </authorization>
    </system.web>
  </location>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
<system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  </system.webServer></configuration>
           
  • 设置登录授权的页面为Login文件夹下的Login.aspx页面
Asp.net+Vue+EmelentUI的实现(二)登录验证

loginUrl指的是登录授权的页面,allow users="*" 指的是允许所有的用户访问该页面。登录页面是整个网站的入口,自然需要所有用户都可以访问。

  • 设置访问需要授权的页面
Asp.net+Vue+EmelentUI的实现(二)登录验证

path可以针对整个文件夹,也可以针对单个文件。由于Pages是文件夹,default.aspx是单个文件,所以分成了两个节点来定义。其中deny users="*"表示的是拒绝所有的用户,allow roles="AspNetVueElementUI"表示的是针对该roles可以访问,而roles是在login的时候通过代码来设定的,具体请看后续的步骤。

2.登录的roles的设置

对LoginController的Login方法进行修改,代码如下

public class LoginController : ApiController
    {
        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="account"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        [HttpGet]
        public BaseDataPackage<UserData> Login(string account,string password)
        {
            //使用account和password验证用户

            UserData userData = new UserData();
            userData.UserGuid = Guid.NewGuid().ToString();
            userData.UserName = "测试用户";

            //将登录信息形成票据并存入到cookie中
            DateTime dateTime = DateTime.Now.AddMinutes(600);
            var ticketDataStr =Newtonsoft.Json.JsonConvert.SerializeObject(userData);
            var ticket = new FormsAuthenticationTicket(2, ticketDataStr, DateTime.Now, dateTime, false, "AspNetVueElementUI", "/"); //建立身份验证票对象
            string HashTicket = FormsAuthentication.Encrypt(ticket); //加密序列化验证票为字符串
            HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, HashTicket);

            //将cookie的失效时间设置为和票据tikets的失效时间一致 
            if (ticket.IsPersistent)
            {
                cookie.Expires = ticket.Expiration;
            }

            //生成Cookie
            HttpContext.Current.Response.Cookies.Add(cookie); //输出Cookie

            var result = new BaseDataPackage<UserData>();
            result.Data = userData;
            result.Status = ApiStatusCode.OK;
            result.Message = "登录成功";
            return result;
        }
    }
           

在login的account和password验证成功后,将相关的用户数据放到FormsAuthenticationTicket中,这是验证的根本。

3.其他页面的验证

所有的页面都以asp.net的页面来构造,即xxx.aspx。这样访问这些页面时,都会通过Global.asax,这时可以作相应的验证。验证代码如下

/// <summary>
        /// 验证请求
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {
            // 提取窗体身份验证 cookie
            string cookieName = FormsAuthentication.FormsCookieName;
            HttpCookie authCookie = HttpContext.Current.Request.Cookies[cookieName];
            if (null == authCookie)
            {
                // 没有身份验证 cookie。
                return;
            }
            var authTicket = FormsAuthentication.Decrypt(authCookie.Value);

            if (null == authTicket)
            {
                // 无法解密 Cookie。
                return;
            }

            string[] roles = authTicket.UserData.Split(new char[] { ',' });
            FormsIdentity id = new FormsIdentity(authTicket);
            System.Security.Principal.GenericPrincipal principal = new System.Security.Principal.GenericPrincipal(id, roles);
            HttpContext.Current.User = principal;
        }
           

4.控制器的验证

  • 对方法的验证(在方法上添加Authorize的属性)
#region Logout
        /// <summary>
        /// 登出
        /// </summary>
        /// <returns></returns>
        [Authorize]
        [HttpGet]
        public BaseDataPackage<string> Logout()
        {
            var result = new BaseDataPackage<string>();
            try
            {
                HttpCookie cookie = HttpContext.Current.Response.Cookies[FormsAuthentication.FormsCookieName];

                if (cookie == null)
                {
                    cookie = new HttpCookie(FormsAuthentication.FormsCookieName);
                    HttpContext.Current.Response.Cookies.Add(cookie);
                }
                HttpContext.Current.Response.Cookies.Clear();
                cookie.Expires = DateTime.Now.AddYears(-10);
                FormsAuthentication.SignOut();

                result.Status = ApiStatusCode.OK;
                result.Message = "登出成功";
                return result;
            }
            catch (Exception ex)
            {
                result.Status = ApiStatusCode.EXCEPTION;
                result.Message = "登出异常=>" + ex.Message;
                return result;
            }
        }
        #endregion
           

在未登录时,直接访问Login控制器下的Logout方法会报错(如下图),从错误中可以看到是未授权的原因。

Asp.net+Vue+EmelentUI的实现(二)登录验证

在登录后,再执行则会提示【登出成功】

Asp.net+Vue+EmelentUI的实现(二)登录验证
  • 对控制器的验证(在控制器上添加Authorize属性)

为了便于其他控制器的继承,我们增加了授权的基础控制器BaseAuthController,代码如下

[Authorize]
    public class BaseAuthController:ApiController
    {

    }
           

比如增加一个产品控制器ProductController

public class ProductController:BaseAuthController
    {
        [HttpGet]
        public BaseDataPackage<string> GetName(string id)
        {
            var result = new BaseDataPackage<string>();
          
            try
            {
                result.Status = ApiStatusCode.OK;
                result.Message = "OK";
                result.Data = "测试";
                return result;
            }
            catch (Exception ex)
            {
                result.Status = ApiStatusCode.EXCEPTION;
                result.Message = "异常=>" + ex.Message;
                return result;
            }
        }
    }
           

在未登录时,直接访问该api,会报错(如下图),从错误中可以看到是因为没有登录授权导致的。

Asp.net+Vue+EmelentUI的实现(二)登录验证

在登录成功后,再访问该api时,则可以正常访问了,如下图

Asp.net+Vue+EmelentUI的实现(二)登录验证

经过以上几个步骤后,我们就实现了登录验证、api访问的验证、页面访问的验证。

源码下载