zoukankan      html  css  js  c++  java
  • Orchard Core 增加了一个API模块,要怎么调用

    如下,我在Orchard Core框架中添加了一个API的模块,并且定义了对应的权限才可以调用,那么我们现在考虑的就是要怎么去调用它。

    首先,我们用Fiddler查看下我们正常的登录的http报文,直接在浏览器输入路径例如: http://192.168.0.225:8082/admin ,会直接跳转到登录页,路径是:http://192.168.0.225:8082/Login?ReturnUrl=%2Fadmin

    admin被添加到一个ReturnUrl的参数后面,输入账号密码然后回车登录到后台。这样一个登录操作就完成了,我们再看看Fiddler的报文:

    在login的时候发送了一个__RequestVerificationToken参数,并且在返回的时候set了一个cookie,这个cookie包含了这个登录用户的身份信息等等,

    所以当我们关闭浏览器但没有logout退出,再次进入admin后台时,不需要再次登录操作,就是因为在这个时候记录了cookie。

    那么__RequestVerificationToken参数又是怎么来的呢?我们知道这整个过程,每一个http报文都是紧接着上一条报文的结果,

    我们看看上一个报文,它返回了一个Document,我们在这个Document找到了这个元素 name="__RequestVerificationToken" 

    这个元素的value就是__RequestVerificationToken参数的值。

    再看看这个Document,里面有一个Form,意思就是Form里的内容会submit到Form对应的action中。

    我一开始以为,了解了这个过程,我们就可以用ajax模拟登录得到cookie了,但是用如下代码,返回的总是400错误,浏览器拒绝了请求。

    $.ajax({
                    url: 'http://192.168.0.225:8082/admin',
                    type: 'get',
                    cache: false,
                    success: function (data) {
                        var objval = $(data).find("[name='__RequestVerificationToken']").val();
                        var url = $(data).find(".form-horizontal").attr("action");
                        $.ajax({
                            url: "http://192.168.0.225:8082" +url,
                            type: 'post',
                            cache: false,
                            async: false,
                            data: {
                                'UserName': 'admin',
                                'Password': 'XXXXXXXXX',
                                '__RequestVerificationToken': objval,
                                'RememberMe': false
                            },
                            success: function (data, status, xhr) {
                                alert("ok");
                                console.log(xhr.getAllResponseHeaders());
                            }
                        });
                    }
                });
    

    这里猜测,估计是因为浏览器的安全机制,拦截了我的ajax

    那么我就换C#模拟http请求,可以得到我要的API返回的结果,代码如下:

    //发送请求
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://192.168.0.225:8082");
                    try
                    {
                        //在没有登录之前,不管写什么路径,都会跳到login页面,而所写的路径会自动添加到returnurl这个参数后
                        //登录之后就会跳转到这个页面
                        //这一步是为了拿到__RequestVerificationToken
                        var cliPost = client.GetAsync("/warehouseapi/admin/index");
                        cliPost.Wait();
                        var result = cliPost.Result;
                        string resultContent = result.Content.ReadAsStringAsync().Result;
                        //返回了一个Document对象,用NSoup解析,NSoup可以用像jQuery那样的选择器选择元素
                        var htmlDoc = NSoup.NSoupClient.Parse(resultContent);
                        var __RequestVerificationToken = htmlDoc.Select("[name=__RequestVerificationToken]").Val();
                        var actionPath = htmlDoc.Select(".form-horizontal").Attr("action");
                        //准备Post的参数
                        var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("UserName", "admin"),
                                                                    new KeyValuePair<string, string>("Password", "ZXXXXXXXX@"),
                                                                    new KeyValuePair<string, string>("RememberMe", "false"),
                                                                    new KeyValuePair<string, string>("__RequestVerificationToken", __RequestVerificationToken),
    
                            });
                        try
                        {
                            //发送请求
                            //登录
                            var cliPost1 = client.PostAsync(actionPath, content);
                            cliPost1.Wait();
                            var result1 = cliPost1.Result;
                            string resultContent1 = result.Content.ReadAsStringAsync().Result;
    
                            //向API发送请求
                            var cliGet = client.GetAsync("/warehouseapi/admin/index");
                            cliGet.Wait();
                            var resultGet = cliGet.Result;
                            string resultContent2 = resultGet.Content.ReadAsStringAsync().Result;
                            Console.WriteLine(DateTime.Now + "======" + resultContent2);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                Console.Read();
    

      

     补充:上面是get请求方式,如果是post请求的时候,由于框架有ValidateAntiForgeryToken这个的验证,所以每次请求都要带上一个__RequestVerificationToken参数。

    ValidateAntiForgeryToken的用途是防止CSRF(跨网站请求伪造),这个具体的可以百度了解。

    总之每次post请求一个api路径都要带上__RequestVerificationToken参数,而__RequestVerificationToken参数是基于上一次请求返回的html页面中[name="__RequestVerificationToken"]的hidden标签的值,这个值每次是不一样的。

    post请求的示例如下:

    //发送请求
                using (HttpClient client = new HttpClient())
                {
                    client.BaseAddress = new Uri("http://192.168.0.225:8082");
                    try
                    {
                        //在没有登录之前,不管写什么路径,都会跳到login页面,而所写的路径会自动添加到returnurl这个参数后
                        //登录之后就会跳转到这个页面
                        //这一步是为了拿到__RequestVerificationToken
                        var cliPost = client.GetAsync("/Login?ReturnUrl=%2Fadmin");
                        cliPost.Wait();
                        var result = cliPost.Result;
                        string resultContent = result.Content.ReadAsStringAsync().Result;
                        //返回了一个Document对象,用NSoup解析,NSoup可以用像jQuery那样的选择器选择元素
                        var htmlDoc = NSoup.NSoupClient.Parse(resultContent);
                        var __RequestVerificationToken = htmlDoc.Select("[name=__RequestVerificationToken]").Val();
                        var actionPath = htmlDoc.Select(".form-horizontal").Attr("action");
                        //准备Post的参数 用户名、密码错误会跳回登录页
                        var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("UserName", "wXXXXXi"),
                                                                    new KeyValuePair<string, string>("Password", "XXXXXXXX21"),
                                                                    new KeyValuePair<string, string>("RememberMe", "false"),
                                                                    new KeyValuePair<string, string>("__RequestVerificationToken", __RequestVerificationToken),
                        });
                        try
                        {
                            //发送请求
                            //登录
                            var cliPost1 = client.PostAsync(actionPath, content);
                            cliPost1.Wait();
                            var result1 = cliPost1.Result;
                            string resultContent1 = result1.Content.ReadAsStringAsync().Result;
    
                            //返回了一个Document对象,用NSoup解析,NSoup可以用像jQuery那样的选择器选择元素
                            var htmlDoc1 = NSoup.NSoupClient.Parse(resultContent1);
                            var __RequestVerificationToken1 = htmlDoc1.Select("[name=__RequestVerificationToken]").Val();
                            var actionPath1 = htmlDoc1.Select(".form-horizontal").Attr("action");
    
                            //var cliGet = client.GetAsync("/warehouseapi/admin/index");
                            //cliGet.Wait();
                            //var rs = cliGet.Result;
                            //string rscontent = rs.Content.ReadAsStringAsync().Result;
    
                            //向API发送请求
                            DeliveryRecords drc = new DeliveryRecords()
                            {
                                CustCode = "001",    
                                LogisticCode = "SUER001",
                                Express = "速尔",        
                                OutNo = "abc01",        
                                Assistant = "何助理",    
                                DanQty = "1",            
                                JianQty = "13",          
                                SendDate = "2018-11-22"  
                            };
                            string rcJsonStr = JsonConvert.SerializeObject(drc);           
                            var rcContent = new FormUrlEncodedContent(new[] {
                                                                    new KeyValuePair<string, string>("__RequestVerificationToken", __RequestVerificationToken1),
                                                                    new KeyValuePair<string, string>("rcJson", rcJsonStr)
                            });
                            var cliRcPost = client.PostAsync("/warehouseapi/admin/InsertDeliRecoAsync", rcContent);
                            cliRcPost.Wait();
                            var rs = cliRcPost.Result;
                            var rsStr = rs.Content.ReadAsStringAsync().Result;
                            Console.WriteLine(rsStr);
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                Console.Read();
    

      

  • 相关阅读:
    CentOS 安装Python3, pip3
    Pyinstaller打包python程序,以及遇到的问题:Cannot find existing PyQt5 plugin directories
    [Python] fetchone()和fetchall()
    在Linux命令行下,如何登录mysql server
    管理MySQL的客户端软件-MySQL Workbench
    在win10修改jupyter notebook(Anaconda安装)工作路径
    安装spark过程中出现Exception in thread "main" java.lang.UnsupportedClassVersionError错误的解决办法
    如何在win10本地主机操作系统和virtualBox 的Ubuntu之间设置共享文件夹
    支持向量机(SVM)
    特征工程(python)
  • 原文地址:https://www.cnblogs.com/SasaL/p/9962113.html
Copyright © 2011-2022 走看看