ASP.NET WebAPI 双向token实现对接小程序登录逻辑

时间:2023-03-08 15:54:01

最近在学习用asp.net webapi搭建小程序的后台服务,因为基于小程序端和后台二者的通信,不像OAuth(开放授权),存在第三方应用。所以这个token是双向的,一个是对用户的,一个是对接口的。本来做了一份是用Oauth的,用的是第三种密码策略模式。但是因为不存在第三方应用,所以不用Oauth这种授权标准。

这个Sample是用简单三层做的,书上得来终觉浅,绝知此事要躬行,实践一次就知道wepapi与前端如何通过token认证进行逻辑交互。

搭建项目

  1. 搭建项目这一点不多说,直接新建一个空的,

    ASP.NET WebAPI 双向token实现对接小程序登录逻辑

用AuthorizationFilter筛选器完成授权

 为什么会用MVC里用到的AuthorizationFilter呢,具体其实我当时不知道WebAPI里面能不能用,但因为领导说最好小程序访问进来,有一个统一验证的方法。因为我之前在另一个项目里创建了一个控件器基类,BaseController,用于做登录验证,权限验证,日志记录,以及公共方法。因为用了OnActionExecuting,所以当时想也没有想,直接搜索Web API OnActionExecuting,看到Web API也有Filter的相关资料。最后参考了[Web APi之认证(Authentication)]((https://www.cnblogs.com/CreateMyself/p/4857799.html),从而顺利完成了这个双向token认证逻辑。
首先,在Controllers文件夹里创建AuthFilterAttribute,即自定义Filter特性。这个class里面先重写OnAuthorization方法。 /// <summary>
/// 最先运行的Filter,被用作请求权限校验
/// </summary>
public class AuthFilterAttribute : AuthorizationFilterAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{}
}

Web APi之认证(Authentication)两种实现方式【二】(十三)

token规则以及解析请求报文头

   OnAuthorization是重写的。那么具体应该写什么呢?当然是进行验证当前的请求是否有授权,是否是 符合要求的请求报文头。
public override void OnAuthorization(HttpActionContext actionContext)
{
//如果用户方位的Action带有AllowAnonymousAttribute,则不进行授权验证
if (actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().Any())
{
return;
}
string authParameter = null;
var authValue = actionContext.Request.Headers.Authorization;//actionContext:Action方法请求上下文
if (authValue != null && authValue.Scheme == "BasicAuth")//这里有BasicAuth和参考资产里面的不同,我们没有认定类,这里的BasicAuth就算是我们自定义的token规则。其实主要是我还没有了解认证身份以及了解GenericIdentity。
{
authParameter = authValue.Parameter; //获取请求参数
var authToken = authParameter.Split('|'); //取出参数,参数格式为(当前时间:加密后的token)将其进行分割
Logging.Error(authParameter);
if (authToken.Length < 2)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.NotAcceptable);//参数不完整,返回406不接受
}
else
{ //参数完整,进行验证
if (ValidateToken(authToken[0],authToken[1]))
{
base.OnAuthorization(actionContext);
}
else
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.ExpectationFailed);//验证不通过,未满足期望值417
}
} }
else
{
//如果验证不通过,则返回401错误,并且Body中写入错误原因
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.Unauthorized, new HttpError("Token 不正确"));
} }

token验证

 //验证token
public bool ValidateToken(string loginTime,string token)
{
bool flag = true;
DateTime checkTime = DateTime.Parse(loginTime); //先验证时间是否过期
DateTime nowtime = DateTime.Now; TimeSpan a = nowtime - checkTime; Logging.Error("a:"+ a.TotalSeconds); if (a.TotalSeconds > 120)//时间过期
{
flag = false;
}
else
{
string checkToken = Utils.GetTokenString(loginTime);
Logging.Error("1:"+checkToken+";2:"+token);
//比较token
if (token.Equals(checkToken, StringComparison.CurrentCultureIgnoreCase))
{
flag = true;
}
else
{
flag = false;
} }
return flag;
}

测试请求授权

  1. 新建一个Contorller,添加一个名为Test的Action进行测试
[HttpGet]
[Authorize]
[Route("Test")]
//public string Test()
public WxResponseResultModel Test()
{
WxResponseResultModel rsEntity = new WxResponseResultModel();
rsEntity.Code = "200";
rsEntity.Message = "这是后台传的测试方法";
//return "这是后台传的测试方法";
return rsEntity;
}
  1. 前端页面请坟,在本机新建html页面进行测试,token使用了MD5加密方式。
 var keyStr = '123456';
var timestamp = getMyFormatDate(new Date(),'yyyy-MM-dd hh:mm:ss');//获取当前时间
console.log("timestamp:" + timestamp);
var token = hexMD5(keyStr + timestamp);
console.log("token:" + token);
var apiServiceBaseUri = "http://localhost:52545/";
$(function () {
var data = {code:"25"};
$.ajax({
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'BasicAuth ' + timestamp+"|"+token);//token规则
},
url: apiServiceBaseUri + 'Login/Test',
type: "GET",
dataType: 'json',
success: function (data) {
alert(data.Message);
//alert(Message);
}
});
});

首先测试没有[Authorize]的时候,因为最先执行的就是AuthorizationFilter,所以毫无悬念会进入OnAuthorization()进行验证。

ASP.NET WebAPI 双向token实现对接小程序登录逻辑

ASP.NET WebAPI 双向token实现对接小程序登录逻辑

其次,在Test这个Action添加[Authorize]看看,这里会有一个疑问,明明是应该认证的方法,添加了[Authorize]属性,更加应该进入OnAuthorization()才对,为什么会拒绝认证呢?

ASP.NET WebAPI 双向token实现对接小程序登录逻辑

ASP.NET WebAPI 双向token实现对接小程序登录逻辑

这是因为是配置文件中,配置了全局过滤器。

//注册全局Filter
config.Filters.Add(new AuthFilterAttribute());
把[Authorize]换成配置的[AuthFilter]属性,就可以成功访问了。

发布IIS,联合小程序测试

由于小程序对ajax这一块进行了封装,请求统一使用 wx.request请求,使用wx.request加入报文报求的时候,不像ajax这样,写在beforeSend里面。wx.request是写在header里面。token规则在app.js里面做了全局变量调用。

 wx.request({
url: app.globalData.api + 'Login/Test',
method: "GET",
header: {
'Authorization': app.globalData.header,
'content-type': 'application/json',
}, // 设置请求的 header
success: function (res) {
//如果是对象的话,写法为
console.log(res.data.Message);
// console.log(res.data);
},
fail:function(res){
console.log("fail:" + res)
}
});

测试期间出现一个bug,提示如下:

未能找到 CodeDom 提供程序类型“Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.3.0, Culture=neutral, PublicKeyToken=31bf385

ASP.NET WebAPI 双向token实现对接小程序登录逻辑

解决办法参考:

未能找到 CodeDom 提供程序类型

参考资料:

api token参考资料

api接口token验证

小程序登录逻辑参考资料

ASP.NET WebApi作服务端开发小程序实现微信授权用户登录实例——登录逻辑1

ASP.NET WebApi作服务端开发小程序实现微信授权用户登录实例——登录逻辑2

ASP.NET WebApi作服务端开发小程序实现微信授权用户登录实例——登录逻辑3

本文WebAPI源代码