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

最近在学习用asp.net webapi搭建小程序的后台服务,因为基于小程序端和后台二者的通信,不像OAuth(开放授权),存在第三方应用。所以这个token是双向的,一个是对用户的,一个是对接口的。本来做了一份是用Oauth的,用的是第三种密码策略模式。但是因为不存在第三方应用,所以不用Oauth这种授权标准。
这个Sample是用简单三层做的,书上得来终觉浅,绝知此事要躬行,实践一次就知道wepapi与前端如何通过token认证进行逻辑交互。

搭建项目
  1. 搭建项目这一点不多说,直接新建一个空的,
    579459-20180930114009713-407537750.png

    用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方法。

    ///
    /// 最先运行的Filter,被用作请求权限校验
    ///
    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()进行验证。
579459-20181008150746853-2077011133.png
579459-20181008150803181-413190040.png

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

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

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

579459-20181009093208348-1417112134.png

解决办法参考:

未能找到 CodeDom 提供程序类型

参考资料:

api token参考资料

api接口token验证

小程序登录逻辑参考资料

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

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

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

本文WebAPI源代码

转载于:https://www.cnblogs.com/mooncake-wong/p/9728828.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值