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

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

搭建项目

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

用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()进行验证。



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



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

//注册全局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

解决办法参考:

未能找到 CodeDom 提供程序类型

参考资料:

api token参考资料

api接口token验证

小程序登录逻辑参考资料

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

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

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

本文WebAPI源代码

ASP.NET WebAPI 双向token实现对接小程序登录逻辑的更多相关文章

  1. [转]微信小程序登录逻辑梳理

    本文转自:http://www.jianshu.com/p/d9996cafdb31 官方文档 文档相关地址: 用户登录 获取用户数据 用户数据的签名验证和加解密                   ...

  2. 微信小程序登录逻辑

    wx.getStorage({ key: 'session_id', success: function(res) { //如果本地缓存中有session_id,则说明用户登陆过 console.lo ...

  3. spring mvc+redis实现微信小程序登录

    本文将详细的介绍微信小程序的登录流程以及在ssm框架下如何实现小程序用户登录 登录流程概要 主要的登录流程可以参考官方提供的一张流程图: 1.微信前台页面: 在微信版本更新之后,提高了安全机制,我们需 ...

  4. django-微信小程序登录

    小程序登录逻辑前端通过调用wx.login()获取code, 将code和用户基本信息发送到后端,后端通过request.get向微信服务器发送get请求获取用户openid和session_key, ...

  5. 做一个开源的小程序登录模块组件(token)

    先了解下SSO 对于单点登陆浅显一点的说就是两种,一种web端的基于Cookie.另一种是跨端的基于Token,一般想要做的都优先做Token吧,个人建议,因为后期扩展也方便哦. 小程序也是呢,做成t ...

  6. 微信小程序登录对接Django后端实现JWT方式验证登录

    先上效果图 点击授权按钮后可以显示部分资料和头像,点击修改资料可以修改部分资料. 流程 1.使用微信小程序登录和获取用户信息Api接口 2.把Api获取的用户资料和code发送给django后端 3. ...

  7. 全栈项目|小书架|微信小程序-登录及token鉴权

    小程序登录 之前也写过微信小程序登录的相关文章: 微信小程序~新版授权用户登录例子 微信小程序-携带Token无感知登录的网络请求方案 微信小程序开通云开发并利用云函数获取Openid 也可以通过官方 ...

  8. 基于Shiro,JWT实现微信小程序登录完整例子

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ...

  9. 小程序登录、微信网页授权(Java版)

    首先呢,“登录”.“授权”.“授权登录”,是一样的意思,不用纠结. 写小程序授权登录的代码前,需要了解清楚openid与unionid的区别,这里再简单介绍一下: 腾讯有个 “微信·开放平台”,只有企 ...

随机推荐

  1. Angular学习第一步

    前端开发越来越流行了,作为后端开发人员,也开始需要学习前端了.随着前端技术的发展,前端技术也越来越复杂,复杂程度不亚于后端,各种框架各种设计模式前端都用上了,什么AngularJS,Angular, ...

  2. win7下安装mongodb

    1.下载mongodb,解压2.新建路径,如D:\mongodb,将解压出来的bin目录复制到该目录下3.在D:\mongodb目录下在新建data目录,在data目录下新建两个目录:db和log.4 ...

  3. 浅析JavaScript正则表达式

    1.正则表达式的定义 正则表达式是一个描述字符模式的对象.JavaScript的RegExp类表示正则表达式,String和RegExp都定义了方法,后者使用正则表达式进行强大的模式匹配和文本检索与替 ...

  4. Cassandra 数据模型

    Cassandra的数据模型类似于关系型数据库的模型,且提供了与SQL语言非常类似的CQL语言进行操作. 但是Cassandra的数据模型类似于多层键值对结构,与关系型数据库存在巨大差别. 本文基于: ...

  5. [Luogu4986] 逃离

    Description 给定次数为 \(n\) 的函数 \(A(x),B(x),C(x)\),求 \(A^2(x)+B^2(x)-C^2(x)\) 在 \([L,R]\) 的零点.\(n\leq 10 ...

  6. Redis持久化存储与复制功能简述

    一.分布式系统基础理论 分布式系统的两个基础理论: 1.CAP理论 如图: Consistency(强一致性):数据一致更新,所有数据变动都是同步的.Availability(可用性):好的响应性能. ...

  7. ExtJS4中设置tabpanel的tab高度问题

    最近碰到个问题,在ExtJS中应该如何设置tabpanel的tab的高度?因为默认情况下,tab的高度太矮了,以至于tab的标题底部字都被截掉.设置了个tabpanel.minHeight = ‘50 ...

  8. Java学习笔记之——switch-case条件结构

    语法: switch(变量){ case 常量1: 执行语句: break: case 常量2: 执行语句: break: case 常量3: 执行语句: break: ………… default: 语 ...

  9. 【IDEA&&Eclipse】3、IntelliJ IDEA 的 20 个代码自动完成的特性

    在这篇文章中,我想向您展示 IntelliJ IDEA 中最棒的 20 个代码自动完成的特性,可让 Java 编码变得更加高效.对任何集成开发环境来说,代码的自动完成都是最最重要的一项功能,它根据你输 ...

  10. C#设计模式——简单工厂模式、工厂模式和抽象工厂模式

    一:简单工厂模式 1:描述:简单工厂模式是由一个工厂对象根据接收到的消息决定要创建哪一个类的对象事例. 2:优点:工厂类中有相关逻辑判断,可以根据需要动态创建相关的对象事例,而客户端只需要告诉工厂类创 ...