WebApi接口安全校验

WebApi验证接口安全防止非法请求篡改数据

(1)法一:用户通过Api请求登录接口,在用户名密码验证通过后返回用户信息的同时携带唯一验证标识Token

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="userPwd">密码</param>
        /// <returns></returns>
        [HttpGet, Route("UserLogin")]
        public HttpResponseMessage UserLogin(string userName, string userPwd)
        {
            ResultMsg resultMsg = null;
            try
            {
                var _data = DAL.UserLogin(userName, userPwd);
                if (_data != null && _data.Rows.Count > 0)
                {
                    string F_UserId = _data.Rows[0]["F_UserId"].ToString();
                    //插入缓存
                    Token token = (Token)HttpRuntime.Cache.Get(F_UserId);
                    if (token == null)
                    {
                        token = new Token();
                        token.SignKey = Guid.NewGuid().ToString().Replace("-", ""); //签入身份key
                        token.SignToken = Models.CommonToken.GetToken(F_UserId); //生成token值
                        token.ExpireTime = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd HH:mm:ss");
                        HttpRuntime.Cache.Insert(token.SignKey, token.SignToken, null, Convert.ToDateTime(token.ExpireTime), TimeSpan.Zero);
                    }
                    _data.Rows[0]["SignKey"] = token.SignKey;
                    //返回用户和token信息
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)StatusCodeEnum.Success;
                    resultMsg.Info = "请求成功";
                    resultMsg.Data = _data;
                    return HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
                }
                else
                {
                    DataTable dt = new DataTable();
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)StatusCodeEnum.DBError;
                    resultMsg.Info = "用户名或密码错误!";
                    resultMsg.Data = dt;
                }
            }
            catch (Exception ex)
            {
                resultMsg = new ResultMsg();
                resultMsg.StatusCode = (int)StatusCodeEnum.Error;
                resultMsg.Info = ex.Message;
                resultMsg.Data = "登录异常!";
            }
            return HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
        }

(2) 客户端保存返回的Token 在请求除登录以外的Api接口时,每次请求必须携带Token做为服务器验证身份的票据,Token有效期为24小时,过期需要重新登录获取新的Token

        /// <summary>
        /// 通知
        /// </summary>
        /// <param name="SignKey"></param>
        /// <param name="keyword"></param>
        /// <param name="PageSize"></param>
        /// <param name="PageIndex"></param>
        /// <returns></returns>
        [HttpGet, Route("GetNoteList")]
        public HttpResponseMessage GetNoteList(string SignKey,string keyword, string PageSize, string PageIndex)
        {
            ResultMsg resultMsg = null;

            #region SignKey验证模块
            string[] sArray;
            if (string.IsNullOrEmpty(SignKey))
            {
                //必填参数项为空
                resultMsg = new ResultMsg();
                resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError;
                resultMsg.Info = "必填参数项不能为空";
                resultMsg.Data = "";
                return HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
            }
            else
            {
                sArray = SignKey.Split(',');
                if (sArray.Length < 2 || string.IsNullOrEmpty(sArray[1]))
                {
                    //验证SinKey
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)StatusCodeEnum.ParameterError;
                    resultMsg.Info = "SignKey参数不完整";
                    resultMsg.Data = "";
                    return HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
                }
                resultMsg = new Token().CheckSignToken(sArray[0]);
                if (Convert.ToInt32(resultMsg.Data) < 0)
                {
                    //验证SinKey
                    resultMsg.StatusCode = resultMsg.StatusCode;
                    resultMsg.Info = resultMsg.Info;
                    resultMsg.Data = "";
                    return HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
                }
            }
            #endregion

            #region Api处理模块
            if (string.IsNullOrEmpty(PageSize))
            {
                PageSize = "10";
            }
            if (string.IsNullOrEmpty(PageIndex))
            {
                PageIndex = "1";
            }
            int PageCount = 0;//总页数
            int RsCount = 0; //总条数
            try
            {
                var _data = Ad.GetNoteList(sArray[1],keyword, PageSize, PageIndex, ref PageCount, ref RsCount);
                if (_data != null && _data.Rows.Count > 0)
                {
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)StatusCodeEnum.Success;
                    resultMsg.Info = StatusCodeEnum.Success.GetEnumText();
                    resultMsg.PageCount = PageCount;
                    resultMsg.RsCount = RsCount;
                    resultMsg.Data = _data;
                }
                else
                {
                    DataTable dt = new DataTable();
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)StatusCodeEnum.Success;
                    resultMsg.Info = "未能获取数据";
                    resultMsg.Data = dt;
                }
            }
            catch (Exception ex)
            {
                resultMsg = new ResultMsg();
                resultMsg.StatusCode = (int)StatusCodeEnum.Error;
                resultMsg.Info = ex.Message;
                resultMsg.Data = "";
            }
            return HttpResponseExtension.toJson(JsonConvert.SerializeObject(resultMsg));
            #endregion
        }

(3)Token验证模块代码如下

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using HsApplication.WebApi.EnumAccess;
using HsApplication.WebApi.Common;

namespace HsApplication.WebApi.Models
{
    /// <summary>
    /// 身份令牌
    /// </summary>
    public class Token
    { 
        /// <summary>
        /// 签入身份key
        /// </summary>
        public string SignKey { get; set; }
        /// <summary>
        /// 对应签名Token
        /// </summary>
        public string SignToken { get; set; }
        /// <summary>
        /// Token过期时间
        /// </summary>
        public string ExpireTime { get; set; }

         /// <summary>
        /// 验证接口身份
        /// </summary>
        /// <param name="signkey"></param>
        /// <returns></returns>
        public ResultMsg CheckSignToken(string signkey)
        {
            ResultMsg resultMsg;
            //判断请求头是否包含以下参数
            if (string.IsNullOrEmpty(signkey))
            {
                resultMsg = new ResultMsg();
                resultMsg.StatusCode = (int)StatusCodeEnum.Unauthorized;
                resultMsg.Info = "身份验证失败";
                resultMsg.Data = "";
            }
            else
            {
                //判断token是否有效
                object token = HttpRuntime.Cache.Get(signkey.ToString());
                if (token == null)
                {
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)EnumAccess.StatusCodeEnum.TokenInvalid;
                    resultMsg.Info = StatusCodeEnum.TokenInvalid.GetEnumText();
                    resultMsg.Data =-1;
                }
                else
                {
                    resultMsg = new ResultMsg();
                    resultMsg.StatusCode = (int)StatusCodeEnum.Authorized;
                    resultMsg.Info = StatusCodeEnum.Authorized.GetEnumText();
                    resultMsg.Data = 1;
                }
            }
            return resultMsg;
        }

    }
}
posted @ 2019-12-13 11:27  沣惠南路  阅读(424)  评论(0)    收藏  举报