在《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=\"Web\" /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页面
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL2AjNxAzM1MTM2ATNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
loginUrl指的是登录授权的页面,allow users="*" 指的是允许所有的用户访问该页面。登录页面是整个网站的入口,自然需要所有用户都可以访问。
- 设置访问需要授权的页面
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方法会报错(如下图),从错误中可以看到是未授权的原因。
在登录后,再执行则会提示【登出成功】
- 对控制器的验证(在控制器上添加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,会报错(如下图),从错误中可以看到是因为没有登录授权导致的。
在登录成功后,再访问该api时,则可以正常访问了,如下图
经过以上几个步骤后,我们就实现了登录验证、api访问的验证、页面访问的验证。
源码下载