Web API 令牌

http://blog.csdn.net/qq289523052/article/details/47750021

Web API数据传输加密

2015-08-18 12:03 15781人阅读 评论(1) 收藏 举报

分类:

Web API

目录(?)[+]

1、Web API的接口访问分类

Web API接口的访问方式,大概可以分为几类:

1)一个是使用用户令牌,通过Web API接口进行数据访问。这种方式,可以有效识别用户的身份,为用户接口返回用户相关的数据,如包括用户信息维护、密码修改、或者用户联系人等与用户身份相关的数据。

2)一种是使用安全签名进行数据提交。这种方式提交的数据,URL连接的签名参数是经过安全一定规则的加密的,服务器收到数据后也经过同样规则的安全加 密,确认数据没有被中途篡改后,再进行数据修改处理。因此我们可以为不同接入方式,如Web/APP/Winfrom等不同接入方式指定不同的加密秘钥, 但是秘钥是双方约定的,并不在网络连接上传输,连接传输的一般是这个接入的AppID,服务器通过这个AppID来进行签名参数的加密对比,这种方式,类 似微信后台的回调处理机制,它们就是经过这样的处理。

3)一种方式是提供公开的接口调用,不需要传入用户令牌、或者对参数进行加密签名的,这种接口一般较少,只是提供一些很常规的数据显示而已。

下面图示就是这几种接入方式的说明和大概应用场景。

2、Web API使用安全签名的实现

首先我们为用户注册的时候,需要由我们认可的终端发起,也就是它们需要进行安全签名,后台确认签名有效性,才能正常实现用户注册,否则遭到伪造数据,系统就失去原有的意义了。

    /// <summary>
    /// 注册用户信息接口
    /// </summary>
    public interface IUserApi
    {
        /// <summary>
        /// 注册用户处理,包括用户名,密码,身份证号,手机等信息
        /// </summary>
        /// <param name="json">注册用户信息</param>
        /// <param name="signature">加密签名字符串</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        /// <param name="appid">应用接入ID</param>
        /// <returns></returns>
        ResultData Add(UserJson json,
            string signature, string timestamp, string nonce, string appid);
    }

其实我们获得用户的令牌,也是需要进行用户安全签名认证的,这样我们才有效保证用户身份令牌获取的合法性。

    /// <summary>
    /// 系统认证等基础接口
    /// </summary>
    public interface IAuthApi
    {
        /// <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>
        /// <returns></returns>
        TokenResult GetAccessToken(string username, string password,
            string signature, string timestamp, string nonce, string appid);
    }

上面介绍到的参数,我们提及了几个参数,一个是加密签名字符串,一个是时间戳,一个是随机数,一个是应用接入ID,我们一般的处理规则如下所示。

1)Web API 为各种应用接入,如APP、Web、Winform等接入端分配应用AppID以及通信密钥AppSecret,双方各自存储。
2)接入端在请求Web API接口时需携带以下参数:signature、 timestamp、nonce、appid,签名是根据几个参数和加密秘钥生成。
3) Web API 收到接口调用请求时需先检查传递的签名是否合法,验证后才调用相关接口。

加密签名在服务端(Web API端)的验证流程参考微信的接口的处理方式,处理逻辑如下所示。

1)检查timestamp 与系统时间是否相差在合理时间内,如10分钟。
2)将appSecret、timestamp、nonce三个参数进行字典序排序
3)将三个参数字符串拼接成一个字符串进行SHA1加密
4)加密后的字符串可与signature对比,若匹配则标识该次请求来源于某应用端,请求是合法的。

C#端代码校验如下所示。

        /// <summary>
        /// 检查应用接入的数据完整性
        /// </summary>
        /// <param name="signature">加密签名内容</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机字符串</param>
        /// <param name="appid">应用接入Id</param>
        /// <returns></returns>
        public CheckResult ValidateSignature(string signature, string timestamp, string nonce, string appid)
        {
            CheckResult result = new CheckResult();
            result.errmsg = "数据完整性检查不通过";

            //根据Appid获取接入渠道的详细信息
            AppInfo channelInfo = BLLFactory<App>.Instance.FindByAppId(appid);
            if (channelInfo != null)
            {
                #region 校验签名参数的来源是否正确
                string[] ArrTmp = { channelInfo.AppSecret, timestamp, nonce };

                Array.Sort(ArrTmp);
                string tmpStr = string.Join("", ArrTmp);

                tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
                tmpStr = tmpStr.ToLower();

                if (tmpStr == signature && ValidateUtil.IsNumber(timestamp))
                {
                    DateTime dtTime = timestamp.ToInt32().IntToDateTime();
                    double minutes = DateTime.Now.Subtract(dtTime).TotalMinutes;
                    if (minutes > timspanExpiredMinutes)
                    {
                        result.errmsg = "签名时间戳失效";
                    }
                    else
                    {
                        result.errmsg = "";
                        result.success = true;
                        result.channel = channelInfo.Channel;
                    }
                }
                #endregion
            }
            return result;
        }

一旦我们完成对安全签名进行成功认证,也就是我们对数据提交的来源和完整性进行了确认,就可以进行更多和安全性相关的操作了,如获取用户的访问令牌信息的操作如下所示。

第一步是验证用户的签名是否符合要求,符合要求后进行用户信息的比对,并生成用户访问令牌数据JSON,返回给调用端即可。

3、Web API使用安全令牌的实现

通过上面的接口,我们获取到的用户访问令牌,以后和用户相关的信息调用,我们就可以通过这个令牌参数进行传递就可以了,这个令牌带有用户的一些基础信息,如用户ID,过期时间等等,这个Token的设计思路来源于JSON Web Token (JWT),具体可以参考http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html,以及GitHub上的项目https://github.com/jwt-dotnet/jwt

由于Web API的调用,都是一种无状态方式的调用方式,我们通过token来传递我们的用户信息,这样我们只需要验证Token就可以了。

JWT的令牌生成逻辑如下所示

令牌生成后,我们需要在Web API调用处理前,对令牌进行校验,确保令牌是正确有效的。

检查的代码,就是把令牌生成的过程逆反过来,获取相应的信息,并且对令牌签发的时间进行有效性判断,一般可以约定一个失效时间,如1天或者7天,也不用设置太短。

        /// <summary>
        /// 检查用户的Token有效性
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public CheckResult ValidateToken(string token)
        {
            //返回的结果对象
            CheckResult result = new CheckResult();
            result.errmsg = "令牌检查不通过";

            if (!string.IsNullOrEmpty(token))
            {
                try
                {
                    string decodedJwt = JsonWebToken.Decode(token, sharedKey);
                    if (!string.IsNullOrEmpty(decodedJwt))
                    {
                        #region 检查令牌对象内容
                        dynamic root = JObject.Parse(decodedJwt);
                        string username = root.name;
                        string userid = root.iss;
                        int jwtcreated = (int)root.iat;

                        //检查令牌的有效期,7天内有效
                        TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
                        int timestamp = (int)t.TotalDays;
                        if (timestamp - jwtcreated > expiredDays)
                        {
                            throw new ArgumentException("用户令牌失效.");
                        }

                        //成功校验
                        result.success = true;
                        result.errmsg = "";
                        result.userid = userid;
                        #endregion
                    }
                }
                catch (Exception ex)
                {
                    LogTextHelper.Error(ex);
                }
            }
            return result;
        }

一般来说,访问令牌不能永久有效,对于访问令牌的重新更新问题,可以设置一个规则,只允许最新的令牌使用,并把它存储在接口缓存里面进行对比,应用系统退出的时候,就把内存里面的Token移除就可以了。

4、ASP.NET Web API的开发

上面我们定义了一般的Web API接口,以及实现相应的业务实现,如果我们需要创建Web API层,还需要构建一个Web API项目的。

创建好相应的项目后,可以为项目添加一个Web API基类,方便控制共同的接口。

然后我们就可以在Controller目录上创建更多的应用API控制器了。

最后我们为了统一所有的API接口都是返回JSON方式,我们需要对WebApiConfig里面的代码进行设置下。

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务
            config.SetCorsPolicyProviderFactory(new CorsPolicyFactory());
            config.EnableCors();

            // Web API 路由
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { action = "post", id = RouteParameter.Optional }
            );

            // Remove the JSON formatter
            //config.Formatters.Remove(config.Formatters.JsonFormatter);

            // Remove the XML formatter
            config.Formatters.Remove(config.Formatters.XmlFormatter);
        }
    }

5、Web API 接口的测试

接下来我们要做的就是需要增加业务接口,以便进行具体的测试了,建议使用Winform项目,对每个接口进行一个测试,或者也可以考虑使用单元测试的方式,看个人喜好吧。

例如我们如果要测试用户登陆的接口的话,我们的测试代码如下所示。

        /// <summary>
        /// 生成签名字符串
        /// </summary>
        /// <param name="appSecret">接入秘钥</param>
        /// <param name="timestamp">时间戳</param>
        /// <param name="nonce">随机数</param>
        private string SignatureString(string appSecret, string timestamp, string nonce)
        {
            string[] ArrTmp = { appSecret, timestamp, nonce };

            Array.Sort(ArrTmp);
            string tmpStr = string.Join("", ArrTmp);

            tmpStr = FormsAuthentication.HashPasswordForStoringInConfigFile(tmpStr, "SHA1");
            return tmpStr.ToLower();
        }

        private TokenResult GetTokenResult()
        {
            string timestamp = DateTime.Now.DateTimeToInt().ToString();
            string nonce = new Random().NextDouble().ToString();
            string signature = SignatureString(appSecret, timestamp, nonce);

            string appended = string.Format("&signature={0}&timestamp={1}&nonce={2}&appid={3}", signature, timestamp, nonce, appId);
            string queryUrl = url + "Auth/GetAccessToken?username=test&password=123456" + appended;

            HttpHelper helper = new HttpHelper();
            string token = helper.GetHtml(queryUrl);
            Console.WriteLine(token);
            TokenResult tokenResult = JsonConvert.DeserializeObject<TokenResult>(token);
            return tokenResult;
        }

如果我们已经获得了令牌,我们根据令牌传递参数给连接,并获取其他数据的测试处理代码如下所示。

            //获取访问令牌
            TokenResult tokenResult = GetTokenResult();

            string queryUrl = url + "/Contact/get?token=" + tokenResult.access_token;
            HttpHelper helper = new HttpHelper();
            string result = helper.GetHtml(queryUrl);
            Console.WriteLine(result);

如果需要POST数据的话,那么调用代码如下所示。

            //使用POST方式
            var data = new
            {
                name = "张三",
                certno = "123456789",
            };
            var postData = data.ToJson();

            queryUrl = url + "/Contact/Add?token=" + tokenResult.access_token;
            helper = new HttpHelper();
            helper.ContentType = "application/json";
            result = helper.GetHtml(queryUrl, postData, true);
            Console.WriteLine(result);

Web API后台,会自动把POST的JSON数据转换为对应的对象的。

如果是GET方式,我们可能可以直接通过浏览器进行调试,如果是POST方式,我们需要使用一些协助工具,如Fiddler等处理工具,但是最好的方式是自己根据需要弄一个测试工具,方便测试。

以下就是我为了自己Web API 接口开发的需要,专门弄的一个调试工具,可以自动组装相关的参数,包括使用安全签名的参数,还可以把所有参数数据进行存储。

转载自:点击打开链接

时间: 2024-10-08 12:32:50

Web API 令牌的相关文章

ASP.NET Web API 2基于令牌的身份验证

基于令牌的认证 我们知道WEB网站的身份验证一般通过session或者cookie完成的,登录成功后客户端发送的任何请求都带上cookie,服务端根据客户端发送来的cookie来识别用户. WEB API使用这样的方法不是很适合,于是就有了基于令牌的认证,使用令牌认证有几个好处:可扩展性.松散耦合.移动终端调用比较简单等等,别人都用上了,你还有理由不用吗? 下面我们花个20分钟的时间来实现一个简单的WEB API token认证: Step 1: 新建一个空的WEB API项目,项目名称就设置为

基于.Net Framework 4.0 Web API开发(4):ASP.NET Web APIs 基于令牌TOKEN验证的实现

概述:  ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是在使用API的时候总会遇到跨域请求的问题, 特别各种APP万花齐放的今天,对API使用者身份角色验证是不能避免的(完全开发的API不需要对使用者身份角色进行管控,可以绕过),这篇文章就来谈谈基于令牌TOKEN身份验证的实现. 问题: 对于Web API的选择性的开放,使用者无论使用AJAX,还是HttpClient对接,总要对使用者的身份角色

Web API 身份验证 不记名令牌验证 Bearer Token Authentication

1. Startup.Auth.cs文件 添加属性 public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } 添加静态构造函数 /// <summary> /// 构造函数 /// </summary> static Startup() { OAuthBearerOptions = new OAuthBearerAuthenticationOptions(); }

asp.net Web API 身份验证 不记名令牌验证 Bearer Token Authentication 简单实现

1. Startup.Auth.cs文件 添加属性 1 public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; } 添加静态构造函数 1 2 3 4 5 6 7 /// <summary> /// 构造函数 /// </summary> static Startup() {     OAuthBearerOptions = new OAuthBearerAuthent

利用Java编码北京PK10平台制作测试CSRF令牌验证的Web API

拙文是利用了Jmeter来测试北京PK10平台制作(www.1159880099.com)QQ1159880099 带有CSRF令牌验证的Web API:最近几天趁着项目不忙,练习了用编码的方式实现. 有了之前Jmeter脚本的基础,基本上难点也就在两个地方:获取CSRF令牌.Cookie的传递. 首先添加依赖,在POM.xml中添加以下内容: <!-- https:// mvnrepository.com/artifact/org.apache.httpcomponents/httpclien

在ASP.NET Web API 2中使用Owin OAuth 刷新令牌

在上篇文章介绍了Web Api中使用令牌进行授权的后端实现方法,基于WebApi2和OWIN OAuth实现了获取access token,使用token访问需授权的资源信息.本文将介绍在Web Api中启用刷新令牌的后端实现. 本文要用到上篇文章所使用的代码,代码编写环境为VS 2017..Net Framework 4.7.2,数据库为MS SQL 2008 R2. OAuth 刷新令牌 上文已经搞了一套Token授权访问,这里有多出来一个刷新令牌(Refresh Token),平白添加程序

asp.net core 2.0 web api基于JWT自定义策略授权

JWT(json web token)是一种基于json的身份验证机制,流程如下: 通过登录,来获取Token,再在之后每次请求的Header中追加Authorization为Token的凭据,服务端验证通过即可能获取想要访问的资源.关于JWT的技术,可参考网络上文章,这里不作详细说明, 这篇博文,主要说明在asp.net core 2.0中,基于jwt的web api的权限设置,即在asp.net core中怎么用JWT,再次就是不同用户或角色因为权限问题,即使援用Token,也不能访问不该访

Web API应用架构在Winform混合框架中的应用(1)

在<Web API应用架构设计分析(1)>和<Web API应用架构设计分析(2)>中对WebAPI的架构进行了一定的剖析,在当今移动优先的口号下,传统平台都纷纷开发了属于自己的Web API平台,方便各种终端系统的接入,很多企业的需求都是以Web API优先的理念来设计整个企业应用体系的.Web API作为整个纽带的核心,在整个核心层需要考虑到统一性.稳定性.以及安全性等方面因素.本文主要介绍,Web API应用架构,在Winform整合中的角色,以及如何实现在Winform混合

asp.net core web api token验证和RestSharp访问

对与asp.net core web api验证,多种方式,本例子的方式采用的是李争的<微软开源跨平台移动开发实践>中的token验证方式. Asp.net core web api项目代码: 首先定义三个Token相关的类,一个Token实体类,一个TokenProvider类,一个TokenProviderOptions类 代码如下: /// <summary> /// Token实体 /// </summary> public class TokenEntity