微信小程序版狼人杀+服务端系列(2)

  • Post author:
  • Post category:小程序


这一篇主要讲创建房间以及用户登录拦截请求等

  1. 用户登录,用户进入小程序发起wx.login带上code请求服务端,服务端进行一系列的处理
  2. 用户登录之后,利用sessionKey来保持用户活动,那么我们将sessionKey带在HTTP请求头部,用户发起请求判断其行为是否符合要求。不符合进行拦截
  3. 创建房间,一个房间总共多少人,存在哪些身份牌,已经有多少人,游戏进程等等

以下实现逻辑

/// <summary>
        /// 微信登陆请求
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [SkipAuthorization]
        [Route("Login")]
        public Result<UserReuslt> Login()
        {
            string code = GetParams("code");
            string xmlRes = WxPayAPI.HttpService.Get("https://api.weixin.qq.com/sns/jscode2session?appid=你得ID&secret=你得密钥&js_code" +
                "=" + code + "&grant_type=authorization_code");
            var xmlJson = JsonConvert.DeserializeObject<Dictionary<string, string>>(xmlRes);
            if (xmlJson != null && xmlJson.ContainsKey("session_key"))
            {
                string openId = xmlJson["openid"];
                string sessionKey = xmlJson["session_key"];
                string unionId = "";
                if (xmlJson.ContainsKey("unionid"))
                    unionId = xmlJson["unionid"];

                //创建或者更新用户
                User user = _dbContext.Users.Where(o => o.Openid == openId).FirstOrDefault();
                if (user == null)
                {
                    //创建用户
                    User newU = new User()
                    {
                        Openid = openId
                    };
                    _dbContext.Users.Add(newU);
                    _dbContext.SaveChanges();
                }
                else
                {
                    user.Openid = openId;
                    _dbContext.Users.Update(user);
                    _dbContext.SaveChanges();
                }

                //获取用户
                user = _dbContext.Users.Where(o => o.Openid == openId).FirstOrDefault();
                //更新或者插入session
                SessionBag bag = SessionContainer.UpdateSession(null, openId, sessionKey,unionId);
                UserReuslt reuslt = new UserReuslt()
                {
                    User = user,
                    Key = bag.Key,
                    Openid = openId
                };
                return Result.Success(reuslt);
            }
            return Result.Fail("操作失败",new UserReuslt());
        }

        /// <summary>
        /// 登陆返回结果集
        /// </summary>
        public class UserReuslt
        {
            public User User { get; set; }
            public string Key { get; set; }
            public string Openid { get; set; }
        }

用户请求登录,带上code我们从微信服务器换取openid以及sessionKey,将sessionKey写入到SessionBag

封装了一个返回结果集,见下文

public class Result
    {
        internal const string DefaultExceptionMessage = "未知错误!";

        /// <summary>
        /// 构造方法
        /// </summary>
        public Result()
        {
            this.Code = HttpStatusCode.NotFound;
            this.Msg = "操作失败";
            this.Error = "";
            this.Url = "";
        }

        /// <summary>
        /// 返回成功的对象
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public Result Success(string msg)
        {
            if (string.IsNullOrEmpty(msg)) msg = "操作成功";
            return new Result
            {
                Code = HttpStatusCode.OK,
                Msg = msg,
                Error = "",
                Url = ""
            };
        }

        /// <summary>
        /// 返回成功的对象
        /// </summary>
        /// <returns></returns>
        public static Result Success()
        {
            return Success(string.Empty);
        }

        /// <summary>
        /// 返回成功的带结果集的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="msg"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Result<T> Success<T>(string msg, T data)
        {
            if (string.IsNullOrWhiteSpace(msg)) msg = "操作成功!";
            return new Result<T>
            {
                Code = HttpStatusCode.OK,
                Msg = msg,
                Error = "",
                Url = "",
                Data = data
            };
        }

        /// <summary>
        /// 返回成功的带结果集的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Result<T> Success<T>(T data)
        {
            return Success<T>(string.Empty, data);
        }

        /// <summary>
        /// 返回失败的带结果集的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="msg"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Result<T> Fail<T>(string msg, T data)
        {
            if (string.IsNullOrWhiteSpace(msg)) msg = "操作失败!";
            return new Result<T>
            {
                Code = HttpStatusCode.BadRequest,
                Msg = msg,
                Error = "",
                Url = "",
                Data = data
            };
        }

        /// <summary>
        /// 返回失败的带结果集的对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static Result<T> Fail<T>(string msg)
        {
            return Fail<T>(msg, default);
        }

        /// <summary>
        /// 返回失败的对象
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static Result Fail(string msg)
        {
            if (string.IsNullOrWhiteSpace(msg)) msg = "操作失败!";
            return new Result
            {
                Code = HttpStatusCode.BadRequest,
                Msg = msg,
                Error = "",
                Url = ""
            };
        }


        /// <summary>
        /// 状态码
        /// </summary>
        public HttpStatusCode Code { get; set; }
        /// <summary>
        /// 消息
        /// </summary>
        public string Msg { get; set; }
        /// <summary>
        /// 错误
        /// </summary>
        public string Error { get; set; }
        /// <summary>
        /// 错误Url
        /// </summary>
        public string Url { get; set; }

    }


    public class Result<T> : Result
    {
        private T _data = default;

        /// <summary>
        /// 构造方法
        /// </summary>
        public Result()
            : base()
        {
            _data = default;
        }

        /// <summary>
        /// 操作结果业务数据
        /// </summary>
        public T Data
        {
            get
            {
                if (typeof(T).BaseType == typeof(IEnumerator))
                    _data = Activator.CreateInstance<T>();
                return _data;
            }
            set
            {
                _data = value;
            }
        }

        /// <summary>
        /// 返回成功的带消息提示对象
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Result<T> Success(string msg, T data)
        {
            return Success<T>(msg, data);
        }

        /// <summary>
        /// 返回成功的带消息提示对象
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Result<T> Success(T data)
        {
            return Success(string.Empty, data);
        }

        /// <summary>
        /// 返回失败的带消息提示对象
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static Result<T> Fail(string msg, T data)
        {
            return Fail(msg, data);
        }

        /// <summary>
        /// 返回失败的带消息提示对象
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static new Result<T> Fail(string msg)
        {
            return Fail(msg, default);
        }

    }

以下为拦截器实现

public class ForeignAuthorize : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            //是否跳过验证
            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
            if (controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true).
                Any(o => o.GetType().Equals(typeof(SkipAuthorization))))
            {
                return;
            }
            var key = context.HttpContext.Request.Headers.TryGetValue("changqing-Header-Token", out var token);
            if (!key)
            {
                context.Result = new JsonResult(Result.Fail("签名无效,此请求已被拒绝!"));
            }
            else
            {
                var bag = SessionContainer.GetSession(token.ToString());
                if (bag == null || string.IsNullOrEmpty(bag.SessionKey))
                {
                    context.Result = new JsonResult(Result.Fail("令牌无效,此请求已被拒绝!"));
                }
            }
            //继续执行上下文
            base.OnActionExecuting(context);
        }


        /// <summary>
        /// 跳过检测
        /// </summary>
        public class SkipAuthorization : ActionFilterAttribute
        {
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                base.OnActionExecuting(context);
            }
        }
    }

所有的控制器全部继承了一个重写的base控制器,在base里面进行注入

整个项目已上传至GitHub,觉得有用的同学麻烦点个star 谢谢。

GitHub



版权声明:本文为qq_36479244原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。