用户身份认证是web应用程序中常见的功能,只有特定的用户才能访问资源,不允许匿名访问,也就是在未登录的状态下进行访问,那么就需要验证用户的身份,以及做出相应的处理。
当web应用程序接收到用户的请求,服务器端将试图去认证用户
授权:
校验已认证的用户是否有权限访问请求的资源
认证的方式:
实现认证的方法:
本案例使用VS2017进行测试开发。
1.首先创建MVC项目,然后在App_Data文件下添加数据库db(便捷方式):
App_Data文件–>右键–>新建项
添加数据表user:
添加测试数据即可
2.在Models文件夹中,使用EF设计工具由数据库生成数据模型类(DBFirst模式):
3.添加Account控制器:
处理用户的注册、登录、以及退出
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AuthenticationDemo.Models;
using System.Web.Security;
namespace AuthenticationDemo.Controllers
{
public class AccountController : Controller
{
dbEntities db = new dbEntities();
// GET: Account
/// <summary>
/// Signup页面初始化
/// </summary>
/// <returns></returns>
public ActionResult Signup()
{
return View();
}
/// <summary>
/// 接收表单提交
/// </summary>
/// <param name="u"></param>
/// <returns></returns>
[HttpPost]
public ActionResult Signup(user u)
{
if(ModelState.IsValid)//检测表单验证是否已通过
{
db.users.Add(u);//添加用户
if(db.SaveChanges()>0)//持久化操作,提交到数据库
{
return RedirectToAction("Login");//重定向到Login动作方法
}
}
return View();
}
/// <summary>
/// 登录页面初始化
/// </summary>
/// <returns></returns>
public ActionResult Login()
{
return View();
}
/// <summary>
/// 登录页面表单提交
/// </summary>
/// <param name="u"></param>
/// <param name="ReturnUrl"></param>
/// <returns></returns>
[HttpPost]
public ActionResult Login(user u,string ReturnUrl)
{
if (ModelState.IsValid)//检测表单是否已验证通过
{
var user = db.users.Where(x => x.username == u.username && x.password == u.password).FirstOrDefault();
if(user!=null)//检查用户是否存在
{
FormsAuthentication.SetAuthCookie(u.username, false);//为用户创建一个身份凭证,用来标识用户
Session["uname"] = u.username.ToString();//将用户名保存到Session中(可用户标识所处于的状态(已登录/未登录))
if (ReturnUrl != null)
{
return Redirect(ReturnUrl);
}
else
{
return Redirect("/Home/Service");
}
}
}
return View();
}
/// <summary>
/// 退出登录状态
/// </summary>
/// <returns></returns>
public ActionResult Logout()
{
FormsAuthentication.SignOut();//删除身份凭证
Session["uname"] = null;//删除session值
return Redirect("Login");//重定向到Login页面
}
}
}
添加SignUp注册页面:
@model AuthenticationDemo.Models.user
@{
ViewBag.Title = "Signup";
}
<h2>Signup</h2>
@using (Html.BeginForm("Signup", "Account"))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>user</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.username, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.username, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.username, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.password, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.password, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Signup" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
@Html.ActionLink("Login", "Login")
</div>
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
添加Login登录页面:
@model AuthenticationDemo.Models.user
@{
ViewBag.Title = "Login";
}
<h2>Login</h2>
@using (Html.BeginForm("Login","Account",FormMethod.Post))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>user</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.username, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.username, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.username, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.password, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.password, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.password, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Login" class="btn btn-default" />
</div>
</div>
</div>
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
4.添加Home控制器:
添加 Index、About、Service动作方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using AuthenticationDemo.Models;
namespace AuthenticationDemo.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Service()
{
return View();
}
}
}
对应的Index视图:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div class="breadcrumb">
<h3>This is MVC APP</h3>
<p>We are Learning Authentication</p>
</div>
About视图:
@{
ViewBag.Title = "About";
}
<h2>This is About View</h2>
Services视图:
@{
ViewBag.Title = "Service";
}
<h2>Service</h2>
<ul>
<li>Web Development</li>
<li>Web SEO</li>
<li>Web Designing</li>
<li>Logo Designing</li>
</ul>
实现认证过滤器:
在System.Web.Mvc命名空间下提供了一些以Attribute为结尾的注解属性类
AuthorizeAttribute类:
指定对控制器或操作方法的访问仅限于满足授权要求的用户。
5.在Home控制器的Service动作方法上,添加Authorize属性:
[Authorize]
public ActionResult Service()
{
return View();
}
运行并访问Service页面:显示无权访问
如果无权访问,应引导进行登录–>告诉MVC如果匿名访问,应先跳转到登录页面.
解决方案:
在Web.config配置文件中,配置认证节点:
forms authentication
此节点对应的是System.Web.Security命名空间下的FormsAuthentication类,提供了关于forms认证方式的信息
<system.web>
<!--配置authentication节点:拒绝匿名用户访问(相对于整个Web应用程序)
loginUrl:用户如果没有登录,则跳转到登录页面
-->
<authentication mode="Forms">
<forms loginUrl="~/Account/Login"></forms>
</authentication>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2" />
</system.web>
在View前台页面,根据Session中的key对应的value是否为空,控制内容的显示/隐藏:
@*检测用户是否已登录*@
@if (Session["uname"] != null)
{
<li><a href="">Dear @Session["uname"]</a></li>
<li>@Html.ActionLink("Logout", "Logout", "Account")</li>
}
else
{
<li>@Html.ActionLink("Login", "Login", "Account")</li>
}
添加退出登录的功能:
在Account控制器中,添加Logout动作方法:
/// <summary>
/// 退出登录状态
/// </summary>
/// <returns></returns>
public ActionResult Logout()
{
FormsAuthentication.SignOut();//删除身份凭证
Session["uname"] = null;//删除session值
return Redirect("Login");//重定向到Login页面
}
Home控制器:
[Authorize] //强制要进行身份验证(拒绝进行匿名访问)---控制器中的所有方法都需要认证
public class HomeController : Controller
{
dbEntities db = new dbEntities();
// GET: Home
[AllowAnonymous] //允许进行匿名访问
public ActionResult Index()
{
return View();
}
//[Authorize]
public ActionResult Service()
{
return View();
}
}
全局的认证过滤器:
在整个Web应用程序中,任何地方的调用都需要先进行认证
在Global.asax全局文件中:添加以下代码即可
GlobalFilters.Filters.Add(new AuthorizeAttribute());