在个人混合式开发框架里面,集成了WebAPI的访问,这种访问方式不只能够实现简便的数据交换,并且能够在多种平台上进行接入,如Winform程序、Web网站、移动端APP等多种接入方式,Web API的处理方式和微信提供的接口处理规则相似,也是经过向服务器得到访问令牌(AccessToken),而后传递给每一个Web API接口,实现数据的交换处理。本篇随笔主要介绍混合框架中Winform对Web API访问的处理。html
《混合式开发框架》混合了Web API接口访问、WCF接口访问,以及直接访问数据库三种方式的接入,以适应多种场景的应用,是基于门面层的一种接口实现处理和封装。是一种弹性化很是好的框架应用,既可用于单机版软件或者基于局域网内的应用软件,也能够用于分布式技术的互联网环境应用,是一种成熟稳定、安全高效的技术框架。数据库
关于这个框架的详细介绍,能够查看个人随笔《Winform混合式开发框架的特色总结》进行详细了解。api
这里主要关注Web API的接入方式,咱们知道,若是是通常的接口,若是公布在互联网上面,就会有不少接入的风险,所以须要对接口的调用进行检查校验,确保访问令牌有效,并且对数据发生修改的,还须要对数据的加密签名进行检查,才能保证咱们的接口运行在较为安全的环境中。浏览器
混合框架调用Web API接口的详细过程,能够经过《Web API应用架构在Winform混合框架中的应用(3)--Winfrom界面调用WebAPI的过程分解》、《Web API应用架构在Winform混合框架中的应用(1)》、《Web API接口设计经验总结》进行了解。缓存
因为咱们须要对接口访问的身份进行核实,所以通常要求咱们的接口都带有一个token参数,用来对用户身份进行识别,以下所示是Web API层的MVC控制器的接口定义。安全
[HttpGet] public UserInfo GetUserByName(string userName, string token) { //令牌检查,不经过则抛出异常 CheckResult checkResult = CheckToken(token); return BLLFactory<User>.Instance.GetUserByName(userName); }
若是咱们在客户端须要调用这个接口,那么就须要传入这个token参数,也就是说这个token令牌须要在调用任何接口前得到,这样才能为咱们后面的接口调用作好准备。服务器
而这个token的产生是很是重要的,须要严格颁发,所以须要对获取这个token的方法的参数进行签名校验,以下面代码是WebAPI接口对产生token的处理。微信
/// <summary> /// 注册用户获取访问令牌接口 /// </summary> /// <param name="username">用户登陆名称</param> /// <param name="password">用户密码</param> /// <param name="signature">加密签名字符串</param> /// <param name="timestamp">时间戳</param> /// <param name="nonce">随机数</param> /// <param name="appid">应用接入ID</param> [HttpGet] public TokenResult GetAccessToken(string username, string password, string signature, string timestamp, string nonce, string appid)
也就是须要传入用户名、密码、加密签名、时间戳、随机数、应用接入ID等信息,从而构建出来一个访问令牌,经过用户名、密码、加密签名校验等方式,能够实现对访问令牌(token)的严格颁发处理。架构
在客户端调用全部Web API接口前,咱们须要先经过上面的Web API接口,获取到该用户的访问令牌,为了方便,咱们能够在客户端封装一个函数,经过这个函数获取到对应的访问令牌,而后把它存储在缓存里面,方便各个模块的接口访问处理。app
/// <summary> /// 用户获取令牌的辅助类 /// </summary> public class AccessTokenHelper { private const string APPID = "APPID";//应用ID,由系统管理员分配 private const string APPSECRET = "APPSECRET";//应用秘钥,,由系统管理员分配 private const string DEFAULT_API_URL = "http://localhost:9001/api/Auth/GetAccessToken";//默认调试的Web API获取受权地址 /// <summary> /// 设置签名参数。 /// 因为Web API大多数的接口,都须要验证用户身份的访问令牌(accesstoken),所以用户在登录的时候,须要使用这个步骤去获取令牌信息,而后在继续后续的接口操做。 /// 该接口用到的应用ID、应用秘钥等参数,由系统管理员统一分配。 /// </summary> public static bool GetAccessToken(string username, string password) { bool result = false; //配置使用Web API模式,须要构建登录token才能访问 AppConfig config = new AppConfig(); string callerType = config.AppConfigGet("CallerType"); string apiUrl = config.AppConfigGet("AuthApiUrl"); apiUrl = string.IsNullOrEmpty(apiUrl) ? DEFAULT_API_URL : apiUrl; if (callerType.Equals("api", StringComparison.OrdinalIgnoreCase)) { //使用API方式,须要在缓存里面设置特殊的信息 var url = apiUrl + SignatureHelper.GetSignatureUrl(APPID, APPSECRET); url += string.Format("&username={0}&password={1}", username, password); TokenResult tokenResult = JsonHelper<TokenResult>.ConvertJson(url); result = !string.IsNullOrEmpty(tokenResult.access_token); if (tokenResult == null) { var message = "获取受权信息出错,请检查地址是否正确!"; MessageDxUtil.ShowError(message); } var SignatureInfo = new SignatureInfo() { appid = APPID, appsecret = APPSECRET, token = (tokenResult != null) ? tokenResult.access_token : null }; Cache.Instance.Add("SignatureInfo", SignatureInfo); } return result; }
有了这个辅助方法,咱们能够在程序启动后,用户进行身份登陆的时候,先调用这个方法来获取令牌。
string ip = NetworkUtil.GetLocalIP(); string macAddr = HardwareInfoHelper.GetMacAddress(); string loginName = this.txtLoginName.Text.Trim(); string password = this.txtPassword.Text; //若是没法获取访问令牌,则返回 bool hasGotToken = AccessTokenHelper.GetAccessToken(loginName, password); if (!hasGotToken) { return; }
刚才我提到了Web API层的MVC控制器的接口定义,默认后面通常都有一个token参数,以下代码所示
[HttpGet] public UserInfo GetUserByName(string userName, string token) { //令牌检查,不经过则抛出异常 CheckResult checkResult = CheckToken(token); return BLLFactory<User>.Instance.GetUserByName(userName); }
而咱们为了方便客户端调用,通常在客户端调用Web API的时候进行简化了一下,把token参数拿掉,它的值从缓存里面提取。如客户端调用的封装代码以下所示。
public UserInfo GetUserByName(string userName) { var action = "GetUserByName"; string url = GetTokenUrl(action) + string.Format("&userName={0}", userName); UserInfo result = JsonHelper<UserInfo>.ConvertJson(url); return result; }
其中GetTokenUrl就是咱们根据token和方法名称,构建一个链接字符串,函数实现以下所示。
/// <summary> /// 获取单纯包含token参数的链接 /// </summary> /// <param name="action">控制器方法名称</param> /// <returns></returns> protected string GetTokenUrl(string action) { string url = ""; if (this.SignatureInfo != null) { var append = string.Format("?token={0}", SignatureInfo.token); string baseUrl = GetBaseUrl(); url = CombindUrl(baseUrl, action + append);//组合为完整的访问地址 } else { throw new ArgumentNullException("没有在缓存里面设置SignatureInfo签名信息"); } return url; }
这样最终咱们能够得到相似下面的链接地址:
http://localhost:27206/api/Account/GetAccountTypeList?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxIiwiaWF0IjoxNDYzNTU3OTAzLCJqdGkiOiI3OGMyOGRhNC01ZjRjLTQxYzItOThkNC1lYmFkZTM3YjA4NjUiLCJuYW1lIjoiYWRtaW4iLCJjaGFubmVsIjoiMCIsInNoYXJlZGtleSI6IjEyMzRhYmNkIn0.DysdbGx70xuIxXBz3G3x3MkGh9ZxL2zF9Fzu8FGVS0w
有了这个令牌组装好的URL,咱们能够对访问结果的JSON字符串进行解析,把它解析为对应的数据就能够了。
固然,在实际的Web API接口开发过程当中,咱们还可使用Web API工具进行接口调试,以下所示。
下面的1-5的标识就是获取token所须要的签名数据,固然链接还带有几个帐号认证所须要的信息了,如帐号密码、所在公司等信息。
固然咱们也可使用浏览器进行测试获取Token的信息,只是没有那么方便而已。