WebApi 身份认 Basic基础认证
<body>
<div style="text-align:center;">
<div>用户名:<input type="text" id="txt_username" /></div>
<div>密 码:<input type="password" id="txt_password" /></div>
<div><input type="button" value="登录" id="btn_login" class="btn-default" /></div>
</div>
</body>
$(function () {
$("#btn_login").click(function () {
$.ajax({
type: "get",
url: "http://localhost:27221/api/User/Login",
data: { strUser: $("#txt_username").val(), strPwd: $("#txt_password").val() },
success: function (data, status) {
if (status == "success") {
if (!data.bRes){
alert("登录失败");
return;
}
alert("登录成功");
//登录成功之后将用户名和用户票据带到主界面
window.location = "/Home/Index?UserName=" + data.UserName + "&Ticket=" + data.Ticket;
}
},
error: function (e) {
},
complete: function () {
}
});
});
});
public class UserController : ApiController
{
/// <summary>
/// 用户登录
/// </summary>
/// <param name="strUser"></param>
/// <param name="strPwd"></param>
/// <returns></returns>
[HttpGet]
public object Login(string strUser, string strPwd)
{
if (!ValidateUser(strUser, strPwd))
{
return new { bRes = false };
}
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(0, strUser, DateTime.Now,
DateTime.Now.AddHours(1), true, string.Format("{0}&{1}", strUser, strPwd),
FormsAuthentication.FormsCookiePath);
//返回登录结果、用户信息、用户验证票据信息
var oUser = new UserInfo { bRes = true, UserName = strUser, Password = strPwd, Ticket = FormsAuthentication.Encrypt(ticket) };
//将身份信息保存在session中,验证当前请求是否是有效请求
HttpContext.Current.Session[strUser] = oUser;
return oUser;
}
//校验用户名密码(正式环境中应该是数据库校验)
private bool ValidateUser(string strUser, string strPwd)
{
if (strUser == "admin" && strPwd == "123456")
{
return true;
}
else
{
return false;
}
}
}
public class UserInfo
{
public bool bRes { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public string Ticket { get; set; }
}
如何开启WebApi里面的Session,请参考:http://www.cnblogs.com/tinya/p/4563641.html
正如上面的原理部分说的,登录如果失败,则直接返回;如果成功,则将生成的票据Ticket带到前端,传到主界面/Home/Index,下面,我们就来看看主界面Home/Index。
public class HomeController : Controller
{
// GET: Home
public ActionResult Index(string UserName, string Ticket)
{
ViewBag.UserName = UserName;
ViewBag.Ticket = Ticket;
return View();
}
}
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<script src="~/Content/jquery-1.9.1.js"></script>
<link href="~/Content/bootstrap/css/bootstrap.css" rel="stylesheet" />
<script src="~/Content/bootstrap/js/bootstrap.js"></script>
<script src="~/Scripts/Home/Index.js"></script>
<script type="text/javascript">
//打开页面的时候保存票据信息
var UserName = '@ViewBag.UserName';
var Ticket = '@ViewBag.Ticket';
</script>
</head>
<body>
<div>当前登录用户:'@ViewBag.UserName'</div>
<div id="div_test">
</div>
</body>
</html>
$(function () {
$.ajax({
type: "get",
url: "http://localhost:27221/api/Charging/GetAllChargingData",
data: {},
beforeSend: function (XHR) {
//发送ajax请求之前向http的head里面加入验证信息
XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket);
},
success: function (data, status) {
if (status == "success") {
$("#div_test").html(data);
}
},
error: function (e) {
$("#div_test").html("Error");
},
complete: function () {
}
});
});
继承我们的AuthorizeAttribute这个类。然后重写OnAuthorization方法,在这个方法里面取到请求头的Ticket信息,然后校验用户名密码是否合理。
/// <summary>
/// 自定义此特性用于接口的身份验证
/// </summary>
public class RequestAuthorizeAttribute : AuthorizeAttribute
{
//重写基类的验证方式,加入我们自定义的Ticket验证
public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
{
//从http请求的头里面获取身份验证信息,验证是否是请求发起方的ticket
var authorization = actionContext.Request.Headers.Authorization;
if ((authorization != null) && (authorization.Parameter != null))
{
//解密用户ticket,并校验用户名密码是否匹配
var encryptTicket = authorization.Parameter;
if (ValidateTicket(encryptTicket))
{
base.IsAuthorized(actionContext);
}
else
{
HandleUnauthorizedRequest(actionContext);
}
}
//如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401
else
{
var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);
if (isAnonymous) base.OnAuthorization(actionContext);
else HandleUnauthorizedRequest(actionContext);
}
}
//校验用户名密码(正式环境中应该是数据库校验)
private bool ValidateTicket(string encryptTicket)
{
//解密Ticket
var strTicket = FormsAuthentication.Decrypt(encryptTicket).UserData;
//从Ticket里面获取用户名和密码
var index = strTicket.IndexOf("&");
string strUser = strTicket.Substring(0, index);
string strPwd = strTicket.Substring(index + 1);
if (strUser == "admin" && strPwd == "123456")
{
return true;
}
else
{
return false;
}
}
}
[RequestAuthorize]
public class ChargingController : ApiController
{
/// <summary>
/// 得到所有数据
/// </summary>
/// <returns>返回数据</returns>
[HttpGet]
public string GetAllChargingData()
{
return "Success";
}
/// <summary>
/// 得到当前Id的所有数据
/// </summary>
/// <param name="id">参数Id</param>
/// <returns>返回数据</returns>
[HttpGet]
public string GetAllChargingData(string id)
{
return "ChargingData" + id;
}
}
增加了特性标注之后,每次请求这个API里面的接口之前,程序会先进入到我们override过的 OnAuthorization() 方法里面,验证通过之后,才会进到相应的方法里面去执行,否则返回401。
优化
namespace WebApiCORS.Controllers
{
[RequestAuthorize]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public class BaseApiController : ApiController
{
}
}
namespace WebApiCORS.Controllers
{
public class ChargingController : BaseApiController
{
/// <summary>
/// 得到所有数据
/// </summary>
/// <returns>返回数据</returns>
[HttpGet]
public string GetAllChargingData()
{
return "Success";
}
/// <summary>
/// 得到当前Id的所有数据
/// </summary>
/// <param name="id">参数Id</param>
/// <returns>返回数据</returns>
[HttpGet]
public string GetAllChargingData(string id)
{
return "ChargingData" + id;
}
}
}
解决ajax的问题
还记得我们在 JS组件系列——封装自己的JS组件,你也可以 这篇里面介绍的增加ajax的error事件的公共处理方法吗?我们是否也可以通过同样的机制去增加这个呢。新建一个文件Jquery_ajax_extention.js
(function ($) {
//1.得到$.ajax的对象
var _ajax = $.ajax;
$.ajax = function (options) {
//2.每次调用发送ajax请求的时候定义默认的error处理方法
var fn = {
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error(XMLHttpRequest.responseText, '错误消息', { closeButton: true, timeOut: 0, positionClass: 'toast-top-full-width' });
},
success: function (data, textStatus) { },
beforeSend: function (XHR) { },
complete: function (XHR, TS) { }
}
//3.扩展原生的$.ajax方法,返回最新的参数
var _options = $.extend({}, {
error: function (XMLHttpRequest, textStatus, errorThrown) {
fn.error(XMLHttpRequest, textStatus, errorThrown);
},
success: function (data, textStatus) {
fn.success(data, textStatus);
},
beforeSend: function (XHR) {
XHR.setRequestHeader('Authorization', 'BasicAuth ' + Ticket);
fn.beforeSend(XHR);
},
complete: function (XHR, TS) {
fn.complete(XHR, TS);
}
}, options);
//4.将最新的参数传回ajax对象
_ajax(_options);
};
})(jQuery);
解决特殊不想使用验证的方法
public class ChargingController : BaseApiController
{
/// <summary>
/// 得到所有数据
/// </summary>
/// <returns>返回数据</returns>
[HttpGet]
public string GetAllChargingData()
{
return "Success";
}
/// <summary>
/// 得到当前Id的所有数据
/// </summary>
/// <param name="id">参数Id</param>
/// <returns>返回数据</returns>
[HttpGet]
[AllowAnonymous]
public string GetAllChargingData(string id)
{
return "ChargingData" + id;
}
}

浙公网安备 33010602011771号